The branch, frodo has been updated
       via  105a79625b4885d0e5ef5680026155460e380d76 (commit)
      from  caaa3935a14c007dd429cab759d9654b41c01f3c (commit)

- Log -----------------------------------------------------------------
http://xbmc.git.sourceforge.net/git/gitweb.cgi?p=xbmc/plugins;a=commit;h=105a79625b4885d0e5ef5680026155460e380d76

commit 105a79625b4885d0e5ef5680026155460e380d76
Author: beenje <[email protected]>
Date:   Tue Aug 6 22:31:02 2013 +0200

    [plugin.video.twitch] updated to version 1.0.2

diff --git a/plugin.video.twitch/README.md b/plugin.video.twitch/README.md
index 9fb32b3..81ef59a 100644
--- a/plugin.video.twitch/README.md
+++ b/plugin.video.twitch/README.md
@@ -10,18 +10,18 @@ FAQ
 
 > In most cases this is caused by a too old librtmp version. Updating it could 
 > solve the problem: 
 
+> [Link: librtmp - Help Thread at 
xbmc.org](http://forum.xbmc.org/showthread.php?tid=162307 
"http://forum.xbmc.org/showthread.php?tid=162307";)
+>
 > [Link: How to update 
 > librtmp](http://wiki.xbmc.org/index.php?title=HOW-TO:Update_librtmp 
 > "http://wiki.xbmc.org/index.php?title=HOW-TO:Update_librtmp";)
 
 * I can't find the Twitch.tv add-on in the xbmc add-on manager!
 
-> Make sure you are using at least XBMC 11 Eden.
+> Make sure you are using at least XBMC 12 Frodo.
 
 What's next?
 ----------------
 
 Things that need to be done next:
 
-* Finish code refactoring
-* Test all features of the plug-in
 * Implement a user authentication
 * Implementation of a section for archived videos
diff --git a/plugin.video.twitch/addon.xml b/plugin.video.twitch/addon.xml
index d909d96..6a4a8d1 100644
--- a/plugin.video.twitch/addon.xml
+++ b/plugin.video.twitch/addon.xml
@@ -1,5 +1,5 @@
 <?xml version='1.0' encoding='UTF-8' standalone='yes'?>
-<addon id='plugin.video.twitch' version='1.0.0' name='TwitchTV' 
provider-name='StateOfTheArt'>
+<addon id='plugin.video.twitch' version='1.0.2' name='TwitchTV' 
provider-name='StateOfTheArt and ccaspers'>
   <requires>
     <import addon='xbmc.python' version='2.1.0'/>
     <import addon='script.module.simplejson' version='2.0.10'/>
diff --git a/plugin.video.twitch/changelog.txt 
b/plugin.video.twitch/changelog.txt
index 6c97b4a..56d68aa 100644
--- a/plugin.video.twitch/changelog.txt
+++ b/plugin.video.twitch/changelog.txt
@@ -43,4 +43,8 @@
 - major code refactoring
 - extracted twitch api
 - new search function
-- changed code style to match pep8 requirements
\ No newline at end of file
+- changed code style to match pep8 requirements
+1.0.1
+- fixed bug: streams with optional subscriptions
+1.0.2
+- fixed stream resolving
diff --git a/plugin.video.twitch/converter.py b/plugin.video.twitch/converter.py
index 19a1eeb..aa6ce51 100644
--- a/plugin.video.twitch/converter.py
+++ b/plugin.video.twitch/converter.py
@@ -1,107 +1,105 @@
 from twitch import Keys
 
+
 class JsonListItemConverter(object):
-    
+
     def __init__(self, PLUGIN, title_length):
         self.plugin = PLUGIN
         self.titleBuilder = TitleBuilder(PLUGIN, title_length)
-        
+
     def convertGameToListItem(self, game):
         name = game[Keys.NAME].encode('utf-8')
         image = game[Keys.LOGO].get(Keys.LARGE, '')
-        return {
-                'label': name,
+        return {'label': name,
                 'path': self.plugin.url_for('createListForGame',
-                                            gameName = name, index = '0'),
-                'icon' : image
+                                            gameName=name, index='0'),
+                'icon': image
                 }
-    
+
     def convertTeamToListItem(self, team):
         name = team['name']
-        return {
-                'label': name,
+        return {'label': name,
                 'path': self.plugin.url_for(endpoint='createListOfTeamStreams',
                                             team=name),
-                'icon' : team.get(Keys.LOGO,'')
+                'icon': team.get(Keys.LOGO, '')
                 }
-        
-    def convertTeamChannelToListItem(self,teamChannel):
-        images = teamChannel.get('image','')
-        image = '' if not images else images.get('size600','')
-    
+
+    def convertTeamChannelToListItem(self, teamChannel):
+        images = teamChannel.get('image', '')
+        image = '' if not images else images.get('size600', '')
+
         channelname = teamChannel['name']
-        titleValues = {'streamer':teamChannel.get('display_name'), 
-                       'title':teamChannel.get('title'), 
-                       'viewers':teamChannel.get('current_viewers')}
-        
+        titleValues = {'streamer': teamChannel.get('display_name'),
+                       'title': teamChannel.get('title'),
+                       'viewers': teamChannel.get('current_viewers')}
+
         title = self.titleBuilder.formatTitle(titleValues)
         return {'label': title,
                 'path': self.plugin.url_for(endpoint='playLive', 
name=channelname),
-                'is_playable' : True,
-                'icon' : image}
-        
+                'is_playable': True,
+                'icon': image}
+
     def extractTitleValues(self, channel):
-        return {
-                'streamer': channel.get(Keys.DISPLAY_NAME,
+        return {'streamer': channel.get(Keys.DISPLAY_NAME,
                                         self.plugin.get_string(34000)),
                 'title': channel.get(Keys.STATUS,
                                      self.plugin.get_string(34001)),
-                'viewers':channel.get(Keys.VIEWERS,
-                                      self.plugin.get_string(34002))
+                'viewers': channel.get(Keys.VIEWERS,
+                                       self.plugin.get_string(34002))
                 }
 
     def convertChannelToListItem(self, channel):
         videobanner = channel.get(Keys.VIDEO_BANNER, '')
         logo = channel.get(Keys.LOGO, '')
-        return {
-                'label': self.getTitleForChannel(channel),
-                'path': self.plugin.url_for(endpoint = 'playLive',
-                                            name = channel[Keys.NAME]),
+        return {'label': self.getTitleForChannel(channel),
+                'path': self.plugin.url_for(endpoint='playLive',
+                                            name=channel[Keys.NAME]),
                 'is_playable': True,
-                'icon' : videobanner if videobanner else logo
+                'icon': videobanner if videobanner else logo
                 }
-    
+
     def getTitleForChannel(self, channel):
         titleValues = self.extractTitleValues(channel)
         return self.titleBuilder.formatTitle(titleValues)
-        
+
+
 class TitleBuilder(object):
-    
+
     class Templates(object):
         TITLE = "{title}"
         STREAMER = "{streamer}"
         STREAMER_TITLE = "{streamer} - {title}"
         VIEWERS_STREAMER_TITLE = "{viewers} - {streamer} - {title}"
         ELLIPSIS = '...'
-        
+
     def __init__(self, PLUGIN, line_length):
         self.plugin = PLUGIN
         self.line_length = line_length
-        
+
     def formatTitle(self, titleValues):
-        titleSetting = int(self.plugin.get_setting('titledisplay'))
+        titleSetting = int(self.plugin.get_setting('titledisplay', unicode))
         template = self.getTitleTemplate(titleSetting)
-    
+
         for key, value in titleValues.iteritems():
             titleValues[key] = self.cleanTitleValue(value)
         title = template.format(**titleValues)
-    
+
         return self.truncateTitle(title)
-    
+
     def getTitleTemplate(self, titleSetting):
-        options = {0:TitleBuilder.Templates.STREAMER_TITLE,
-                   1:TitleBuilder.Templates.VIEWERS_STREAMER_TITLE,
-                   2:TitleBuilder.Templates.TITLE,
-                   3:TitleBuilder.Templates.STREAMER}
+        options = {0: TitleBuilder.Templates.STREAMER_TITLE,
+                   1: TitleBuilder.Templates.VIEWERS_STREAMER_TITLE,
+                   2: TitleBuilder.Templates.TITLE,
+                   3: TitleBuilder.Templates.STREAMER}
         return options.get(titleSetting, TitleBuilder.Templates.STREAMER)
-    
+
     def cleanTitleValue(self, value):
         if isinstance(value, basestring):
             return unicode(value).replace('\r\n', ' ').strip().encode('utf-8')
         else:
             return value
-    
+
     def truncateTitle(self, title):
         shortTitle = title[:self.line_length]
         ending = (title[self.line_length:] and TitleBuilder.Templates.ELLIPSIS)
-        return shortTitle + ending
\ No newline at end of file
+        return shortTitle + ending
diff --git a/plugin.video.twitch/default.py b/plugin.video.twitch/default.py
index 69d7352..214225d 100644
--- a/plugin.video.twitch/default.py
+++ b/plugin.video.twitch/default.py
@@ -1,9 +1,9 @@
 #!/usr/bin/python
 # -*- coding: utf-8 -*-
-from converter import JsonListItemConverter 
+from converter import JsonListItemConverter
 from functools import wraps
 from twitch import TwitchTV, TwitchVideoResolver, Keys, TwitchException
-from xbmcswift2 import Plugin #@UnresolvedImport
+from xbmcswift2 import Plugin  # @UnresolvedImport
 import sys
 
 ITEMS_PER_PAGE = 20
@@ -16,7 +16,7 @@ TWITCHTV = TwitchTV()
 
 def managedTwitchExceptions(func):
     @wraps(func)
-    def wrapper(*args,**kwargs):
+    def wrapper(*args, **kwargs):
         try:
             return func(*args, **kwargs)
         except TwitchException as error:
@@ -28,7 +28,7 @@ def handleTwitchException(exception):
     codeTranslations = {TwitchException.NO_STREAM_URL   : 32004,
                         TwitchException.STREAM_OFFLINE  : 32002,
                         TwitchException.HTTP_ERROR      : 32001,
-                        TwitchException.JSON_ERROR      : 32008 }
+                        TwitchException.JSON_ERROR      : 32008}
     code = exception.code
     title = 31000
     msg = codeTranslations[code]
@@ -38,29 +38,23 @@ def handleTwitchException(exception):
 @PLUGIN.route('/')
 def createMainListing():
     items = [
-        {
-         'label': PLUGIN.get_string(30005),
-         'path': PLUGIN.url_for(endpoint = 'createListOfFeaturedStreams')
+        {'label': PLUGIN.get_string(30005),
+         'path': PLUGIN.url_for(endpoint='createListOfFeaturedStreams')
          },
-        {
-         'label': PLUGIN.get_string(30001),
-         'path': PLUGIN.url_for(endpoint = 'createListOfGames', index = '0')
+        {'label': PLUGIN.get_string(30001),
+         'path': PLUGIN.url_for(endpoint='createListOfGames', index='0')
          },
-        {
-         'label': PLUGIN.get_string(30002),
-         'path': PLUGIN.url_for(endpoint = 'createFollowingList')
+        {'label': PLUGIN.get_string(30002),
+         'path': PLUGIN.url_for(endpoint='createFollowingList')
          },
-        {
-         'label': PLUGIN.get_string(30006),
-         'path': PLUGIN.url_for(endpoint = 'createListOfTeams')
+        {'label': PLUGIN.get_string(30006),
+         'path': PLUGIN.url_for(endpoint='createListOfTeams')
          },
-        {
-         'label': PLUGIN.get_string(30003),
-         'path': PLUGIN.url_for(endpoint = 'search')
+        {'label': PLUGIN.get_string(30003),
+         'path': PLUGIN.url_for(endpoint='search')
          },
-        {
-         'label': PLUGIN.get_string(30004),
-         'path': PLUGIN.url_for(endpoint = 'showSettings')
+        {'label': PLUGIN.get_string(30004),
+         'path': PLUGIN.url_for(endpoint='showSettings')
          }
     ]
     return items
@@ -93,7 +87,7 @@ def createListForGame(gameName, index):
     items = [CONVERTER.convertChannelToListItem(item[Keys.CHANNEL])for item
              in TWITCHTV.getGameStreams(gameName, offset, limit)]
 
-    items.append(linkToNextPage('createListForGame', index, gameName = 
gameName))
+    items.append(linkToNextPage('createListForGame', index, gameName=gameName))
     return items
 
 
@@ -110,20 +104,20 @@ def createFollowingList():
 def search():
     query = PLUGIN.keyboard('', PLUGIN.get_string(30101))
     if query:
-        target = PLUGIN.url_for(endpoint = 'searchresults', query = query, 
index = '0')
+        target = PLUGIN.url_for(endpoint='searchresults', query=query, 
index='0')
     else:
-        target = PLUGIN.url_for(endpoint = 'createMainListing')
+        target = PLUGIN.url_for(endpoint='createMainListing')
     PLUGIN.redirect(target)
 
 
 @PLUGIN.route('/searchresults/<query>/<index>/')
 @managedTwitchExceptions
-def searchresults(query, index = '0'):
+def searchresults(query, index='0'):
     index, offset, limit = calculatePaginationValues(index)
     streams = TWITCHTV.searchStreams(query, offset, limit)
-    
+
     items = [CONVERTER.convertChannelToListItem(stream[Keys.CHANNEL]) for 
stream in streams]
-    items.append(linkToNextPage('searchresults', index, query = query))
+    items.append(linkToNextPage('searchresults', index, query=query))
     return items
 
 
@@ -152,7 +146,7 @@ def createListOfTeams():
 @PLUGIN.route('/createListOfTeamStreams/<team>/')
 @managedTwitchExceptions
 def createListOfTeamStreams(team):
-    return [CONVERTER.convertTeamChannelToListItem(channel[Keys.CHANNEL]) 
+    return [CONVERTER.convertTeamChannelToListItem(channel[Keys.CHANNEL])
             for channel in TWITCHTV.getTeamStreams(team)]
 
 
@@ -164,23 +158,22 @@ def calculatePaginationValues(index):
 
 
 def getUserName():
-    username = PLUGIN.get_setting('username').lower()
+    username = PLUGIN.get_setting('username', unicode).lower()
     if not username:
         PLUGIN.open_settings()
-        username = PLUGIN.get_setting('username').lower()
+        username = PLUGIN.get_setting('username', unicode).lower()
     return username
 
 
 def getVideoQuality():
-    chosenQuality = PLUGIN.get_setting('video')
-    qualities = {'0':sys.maxint, '1':720, '2':480, '3':360}
+    chosenQuality = PLUGIN.get_setting('video', unicode)
+    qualities = {'0': sys.maxint, '1': 720, '2': 480, '3': 360}
     return qualities.get(chosenQuality, sys.maxint)
 
 
 def linkToNextPage(target, currentIndex, **kwargs):
-    return {
-            'label': PLUGIN.get_string(31001),
-            'path': PLUGIN.url_for(target, index = str(currentIndex+1), 
**kwargs)
+    return {'label': PLUGIN.get_string(31001),
+            'path': PLUGIN.url_for(target, index=str(currentIndex + 1), 
**kwargs)
             }
 
 if __name__ == '__main__':
diff --git a/plugin.video.twitch/twitch.py b/plugin.video.twitch/twitch.py
index 7530a2b..16b4fc8 100644
--- a/plugin.video.twitch/twitch.py
+++ b/plugin.video.twitch/twitch.py
@@ -9,11 +9,12 @@ except:
 
 USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 
Firefox/6.0'
 
+
 class JSONScraper(object):
     '''
     Encapsulates execution request and parsing of response
     '''
-    def _downloadWebData(self, url, headers = None):
+    def _downloadWebData(self, url, headers=None):
         req = urllib2.Request(url)
         req.add_header(Keys.USER_AGENT, USER_AGENT)
         response = urllib2.urlopen(req)
@@ -21,7 +22,7 @@ class JSONScraper(object):
         response.close()
         return data
 
-    def getJson(self, url, headers = None):
+    def getJson(self, url, headers=None):
         try:
             jsonString = self._downloadWebData(url, headers)
         except:
@@ -35,7 +36,7 @@ class JSONScraper(object):
 class TwitchTV(object):
     '''
     Uses Twitch API to fetch json-encoded objects
-    every method returns a dict containing the objects' values
+    every method returns a dict containing the objects\' values
     '''
     def __init__(self):
         self.scraper = JSONScraper()
@@ -44,23 +45,23 @@ class TwitchTV(object):
         url = ''.join([Urls.STREAMS, Keys.FEATURED])
         return self._fetchItems(url, Keys.FEATURED)
 
-    def getGames(self, offset = 10, limit = 10):
+    def getGames(self, offset=10, limit=10):
         options = Urls.OPTIONS_OFFSET_LIMIT.format(offset, limit)
         url = ''.join([Urls.GAMES, Keys.TOP, options])
         return self._fetchItems(url, Keys.TOP)
 
-    def getGameStreams(self, gameName, offset = 10, limit = 10):
+    def getGameStreams(self, gameName, offset=10, limit=10):
         quotedName = quote_plus(gameName)
         options = Urls.OPTIONS_OFFSET_LIMIT_GAME.format(offset, limit, 
quotedName)
         url = ''.join([Urls.BASE, Keys.STREAMS, options])
         return self._fetchItems(url, Keys.STREAMS)
 
-    def searchStreams(self, query, offset = 10, limit = 10):
+    def searchStreams(self, query, offset=10, limit=10):
         quotedQuery = quote_plus(query)
         options = Urls.OPTIONS_OFFSET_LIMIT_QUERY.format(offset, limit, 
quotedQuery)
         url = ''.join([Urls.SEARCH, Keys.STREAMS, options])
         return self._fetchItems(url, Keys.STREAMS)
-    
+
     def getFollowingStreams(self, username):
         #Get ChannelNames
         followingChannels = self.getFollowingChannelNames(username)
@@ -69,28 +70,27 @@ class TwitchTV(object):
         options = '?channel=' + ','.join(channelNames)
         url = ''.join([Urls.BASE, Keys.STREAMS, options])
         return self._fetchItems(url, Keys.STREAMS)
-        
+
     def getFollowingChannelNames(self, username):
         quotedUsername = quote_plus(username)
         url = Urls.FOLLOWED_CHANNELS.format(quotedUsername)
         return self._fetchItems(url, Keys.FOLLOWS)
-    
+
     def getTeams(self):
         return self._fetchItems(Urls.TEAMS, Keys.TEAMS)
-    
+
     def getTeamStreams(self, teamName):
         '''
-        Consider this method to be unstable, because the 
+        Consider this method to be unstable, because the
         requested resource is not part of the official Twitch API
         '''
         quotedTeamName = quote_plus(teamName)
         url = Urls.TEAMSTREAM.format(quotedTeamName)
         return self._fetchItems(url, Keys.CHANNELS)
-        
-        
+
     def _filterChannelNames(self, channels):
         return [item[Keys.CHANNEL][Keys.NAME] for item in channels]
-    
+
     def _fetchItems(self, url, key):
         items = self.scraper.getJson(url)
         return items[key] if items else []
@@ -101,24 +101,22 @@ class TwitchVideoResolver(object):
     Resolves the RTMP-Link to a given Channelname
     Uses Justin.TV API
     '''
-    
+
     def getRTMPUrl(self, channelName, maxQuality):
         swfUrl = self._getSwfUrl(channelName)
         streamQualities = self._getStreamsForChannel(channelName)
         # check that api response isn't empty (i.e. stream is offline)
-        if streamQualities: 
-            items = [
-                     self._parseStreamValues(stream, swfUrl)
+        if streamQualities:
+            items = [self._parseStreamValues(stream, swfUrl)
                      for stream in streamQualities
-                     if self._streamIsAccessible(stream)
-                     ]
+                     if self._streamIsAccessible(stream)]
             if items:
                 return self._bestMatchForChosenQuality(items, 
maxQuality)[Keys.RTMP_URL]
             else:
                 raise TwitchException(TwitchException.NO_STREAM_URL)
         else:
             raise TwitchException(TwitchException.STREAM_OFFLINE)
-    
+
     def _getSwfUrl(self, channelName):
         url = Urls.TWITCH_SWF + channelName
         headers = {Keys.USER_AGENT: USER_AGENT,
@@ -128,17 +126,21 @@ class TwitchVideoResolver(object):
         return response.geturl()
 
     def _streamIsAccessible(self, stream):
-        if not stream[Keys.TOKEN] and re.match(Patterns.IP, 
stream.get(Keys.CONNECT)): 
+        stream_is_public = (stream.get(Keys.NEEDED_INFO) != 
"channel_subscription")
+        stream_has_token = stream.get(Keys.TOKEN)
+
+        if stream.get(Keys.CONNECT) is None:
             return False
-        return True
+
+        return stream_is_public and stream_has_token
 
     def _getStreamsForChannel(self, channelName):
         scraper = JSONScraper()
-        url = Urls.TWITCH_API.format(channel = channelName)
+        url = Urls.TWITCH_API.format(channel=channelName)
         return scraper.getJson(url)
 
     def _parseStreamValues(self, stream, swfUrl):
-        streamVars = {Keys.SWF_URL : swfUrl}
+        streamVars = {Keys.SWF_URL: swfUrl}
         streamVars[Keys.RTMP] = stream[Keys.CONNECT]
         streamVars[Keys.PLAYPATH] = stream.get(Keys.PLAY)
 
@@ -153,17 +155,20 @@ class TwitchVideoResolver(object):
                 Keys.RTMP_URL: Urls.FORMAT_FOR_RTMP.format(**streamVars)}
 
     def _bestMatchForChosenQuality(self, streams, maxQuality):
-        streams = [stream for stream in streams 
-                   if stream[Keys.QUALITY] <= maxQuality]
-        streams.sort(key=lambda t: t[Keys.QUALITY], reverse=True)
-        return streams[0]
+        streams.sort(key=lambda t: t[Keys.QUALITY])
+        bestMatch = streams[0]
+        for stream in streams:
+            if stream[Keys.QUALITY] <= maxQuality:
+                bestMatch = stream
+        return bestMatch
 
 
 class Keys(object):
     '''
-    Should not be instantiated, just used to categorize 
+    Should not be instantiated, just used to categorize
     string-constants
     '''
+
     CHANNEL = 'channel'
     CHANNELS = 'channels'
     CONNECT = 'connect'
@@ -175,6 +180,7 @@ class Keys(object):
     LOGO = 'logo'
     LARGE = 'large'
     NAME = 'name'
+    NEEDED_INFO = 'needed_info'
     PLAY = 'play'
     PLAYPATH = 'playpath'
     QUALITY = 'quality'
@@ -189,53 +195,56 @@ class Keys(object):
     TOKEN = 'token'
     TOP = 'top'
     USER_AGENT = 'User-Agent'
-    VIDEO_BANNER  = 'video_banner'
+    VIDEO_BANNER = 'video_banner'
     VIDEO_HEIGHT = 'video_height'
     VIEWERS = 'viewers'
 
+
 class Patterns(object):
     '''
-    Should not be instantiated, just used to categorize 
+    Should not be instantiated, just used to categorize
     string-constants
     '''
     VALID_FEED = 
"^https?:\/\/(?:[^\.]*.)?(?:twitch|justin)\.tv\/([a-zA-Z0-9_]+).*$"
     IP = '.*\d+\.\d+\.\d+\.\d+.*'
     EXPIRATION = '.*"expiration": (\d+)[^\d].*'
 
+
 class Urls(object):
     '''
-    Should not be instantiated, just used to categorize 
+    Should not be instantiated, just used to categorize
     string-constants
     '''
     TWITCH_TV = 'http://www.twitch.tv/'
 
     BASE = 'https://api.twitch.tv/kraken/'
-    FOLLOWED_CHANNELS =  BASE + 'users/{0}/follows/channels'
+    FOLLOWED_CHANNELS = BASE + 'users/{0}/follows/channels?limit=100'
     GAMES = BASE + 'games/'
     STREAMS = BASE + 'streams/'
     SEARCH = BASE + 'search/'
     TEAMS = BASE + 'teams'
-    
+
     TEAMSTREAM = 'http://api.twitch.tv/api/team/{0}/live_channels.json'
-    
+
     OPTIONS_OFFSET_LIMIT = '?offset={0}&limit={1}'
     OPTIONS_OFFSET_LIMIT_GAME = OPTIONS_OFFSET_LIMIT + '&game={2}'
     OPTIONS_OFFSET_LIMIT_QUERY = OPTIONS_OFFSET_LIMIT + '&q={2}'
 
     TWITCH_API = 
"http://usher.justin.tv/find/{channel}.json?type=any&group=&channel_subscription=";
     TWITCH_SWF = "http://www.justin.tv/widgets/live_embed_player.swf?channel=";
-    FORMAT_FOR_RTMP = "{rtmp}/{playpath} swfUrl={swfUrl} swfVfy=1 {token} 
live=1" #Pageurl missing here
-    
+    FORMAT_FOR_RTMP = "{rtmp}/{playpath} swfUrl={swfUrl} swfVfy=1 {token} 
live=1"  # Pageurl missing here
+
+
 class TwitchException(Exception):
 
     NO_STREAM_URL = 0
     STREAM_OFFLINE = 1
     HTTP_ERROR = 2
     JSON_ERROR = 3
-    
+
     def __init__(self, code):
         Exception.__init__(self)
         self.code = code
-        
+
     def __str__(self):
         return repr(self.code)

-----------------------------------------------------------------------

Summary of changes:
 plugin.video.twitch/README.md     |    6 +-
 plugin.video.twitch/addon.xml     |    2 +-
 plugin.video.twitch/changelog.txt |    6 ++-
 plugin.video.twitch/converter.py  |   92 ++++++++++++++++++-------------------
 plugin.video.twitch/default.py    |   65 ++++++++++++--------------
 plugin.video.twitch/twitch.py     |   89 +++++++++++++++++++----------------
 6 files changed, 132 insertions(+), 128 deletions(-)


hooks/post-receive
-- 
Plugins

------------------------------------------------------------------------------
Get 100% visibility into Java/.NET code with AppDynamics Lite!
It's a free troubleshooting tool designed for production.
Get down to code-level detail for bottlenecks, with <2% overhead. 
Download for free and get started troubleshooting in minutes. 
http://pubads.g.doubleclick.net/gampad/clk?id=48897031&iu=/4140/ostg.clktrk
_______________________________________________
Xbmc-addons mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/xbmc-addons

Reply via email to