The branch, eden has been updated
via a23a8b705eaa9b586b253792ab872834cf293632 (commit)
from 95294e7f27f97a1620da028b32e070add5f78fe0 (commit)
- Log -----------------------------------------------------------------
http://xbmc.git.sourceforge.net/git/gitweb.cgi?p=xbmc/scripts;a=commit;h=a23a8b705eaa9b586b253792ab872834cf293632
commit a23a8b705eaa9b586b253792ab872834cf293632
Author: ronie <[email protected]>
Date: Sat Mar 3 16:57:49 2012 +0100
[script.watchlist] -v0.1.11
fixed episode and season thumb not set in some occasions
diff --git a/script.watchlist/addon.xml b/script.watchlist/addon.xml
index 7217d3d..10e7244 100644
--- a/script.watchlist/addon.xml
+++ b/script.watchlist/addon.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<addon id="script.watchlist" name="Watchlist" version="0.1.8"
provider-name="ronie, `Black">
+<addon id="script.watchlist" name="Watchlist" version="0.1.11"
provider-name="ronie, `Black">
<requires>
<import addon="xbmc.python" version="2.0"/>
<import addon="script.module.simplejson" version="2.0.10"/>
diff --git a/script.watchlist/changelog.txt b/script.watchlist/changelog.txt
index 828f0b2..9872ba7 100644
--- a/script.watchlist/changelog.txt
+++ b/script.watchlist/changelog.txt
@@ -1,3 +1,14 @@
+v0.1.11
+- fixed episode and season thumb not set in some occasions
+- use json module on systems with python 2.7 or up
+
+v0.1.10
+- fetch all episodes in a single query
+- only query for season thumbs when strictly needed
+
+v0.1.9
+- improved updating performance
+
v0.1.8
- script will now update only if necessary
diff --git a/script.watchlist/default.py b/script.watchlist/default.py
index a49f7e1..e97147d 100644
--- a/script.watchlist/default.py
+++ b/script.watchlist/default.py
@@ -1,9 +1,15 @@
from time import strptime, mktime
from operator import itemgetter
-import simplejson
+import itertools
+import sys, itertools
+if sys.version_info < (2, 7):
+ import simplejson
+else:
+ import json as simplejson
import xbmc, xbmcgui, xbmcaddon
# http://mail.python.org/pipermail/python-list/2009-June/596197.html
import _strptime
+from threading import Thread
__addon__ = xbmcaddon.Addon()
__addonversion__ = __addon__.getAddonInfo('version')
@@ -66,11 +72,13 @@ class Main:
def _fetch_movies( self ):
self.movies = []
+ self.movieList = []
json_query = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method":
"VideoLibrary.GetMovies", "params": {"properties": ["resume", "genre",
"studio", "tagline", "runtime", "fanart", "thumbnail", "file", "plot",
"plotoutline", "year", "lastplayed", "rating"]}, "id": 1}')
json_query = unicode(json_query, 'utf-8', errors='ignore')
json_response = simplejson.loads(json_query)
if json_response['result'].has_key('movies'):
for item in json_response['result']['movies']:
+ self.movieList.append(item)
if item['resume']['position'] > 0:
# this item has a resume point
label = item['label']
@@ -96,21 +104,32 @@ class Main:
else:
datetime = strptime(lastplayed, "%Y-%m-%d %H:%M:%S")
lastplayed = str(mktime(datetime))
- self.movies.append((lastplayed, label, year, genre,
studio, plot, plotoutline, tagline, runtime, fanart, thumbnail, path, rating))
+ self.movies.append([lastplayed, label, year, genre,
studio, plot, plotoutline, tagline, runtime, fanart, thumbnail, path, rating])
self.movies.sort(reverse=True)
log("movie list: %s items" % len(self.movies))
def _fetch_tvshows( self ):
self.tvshows = []
- json_query = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method":
"VideoLibrary.GetTVShows", "params": {"properties": ["studio", "thumbnail"]},
"id": 1}')
+ # fetch all episodes in one query
+ json_query = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method":
"VideoLibrary.GetEpisodes", "params": {"properties": ["playcount", "plot",
"season", "episode", "showtitle", "thumbnail", "file", "lastplayed", "rating"],
"sort": {"method": "episode"} }, "id": 1}' )
+ json_query = unicode(json_query, 'utf-8', errors='ignore')
+ json_response = simplejson.loads(json_query)
+ if json_response['result'].has_key('episodes'):
+ json_response = json_response['result']['episodes']
+ # our list is sorted by episode number, secondary we sort by
tvshow title (itertools.groupy needs contiguous items) and split it into
seperate lists for each tvshow
+ episodes = [list(group) for key,group in
itertools.groupby(sorted(json_response, key=itemgetter('showtitle')),
key=itemgetter('showtitle'))]
+ # fetch all tvshows, sorted by title
+ json_query = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method":
"VideoLibrary.GetTVShows", "params": {"properties": ["studio", "thumbnail",
"fanart"], "sort": {"method": "label"}}, "id": 1}')
json_query = unicode(json_query, 'utf-8', errors='ignore')
json_response = simplejson.loads(json_query)
if json_response['result'].has_key('tvshows'):
- for item in json_response['result']['tvshows']:
- tvshowid = item['tvshowid']
- thumbnail = item['thumbnail']
- studio = item['studio']
- self.tvshows.append((tvshowid, thumbnail, studio))
+ for count, tvshow in enumerate(json_response['result']['tvshows']):
+ item = [tvshow['tvshowid'], tvshow['thumbnail'],
tvshow['studio'], tvshow['label'], tvshow['fanart'], []]
+ for episodelist in episodes:
+ if episodelist[0]['showtitle'] == item[3]:
+ item[5] = episodelist
+ break
+ self.tvshows.append(item)
log("tv show list: %s items" % len(self.tvshows))
def _fetch_seasonthumb( self, tvshowid, seasonnumber ):
@@ -128,54 +147,60 @@ class Main:
self.episodes = []
for tvshow in self.tvshows:
lastplayed = ""
- json_query = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method":
"VideoLibrary.GetEpisodes", "params": {"properties": ["playcount", "plot",
"season", "episode", "showtitle", "thumbnail", "fanart", "file", "lastplayed",
"rating"], "sort": {"method": "episode"}, "tvshowid":%s}, "id": 1}' % tvshow[0])
- json_query = unicode(json_query, 'utf-8', errors='ignore')
- json_response = simplejson.loads(json_query)
- if json_response['result'].has_key('episodes'):
- for item in json_response['result']['episodes']:
- playcount = item['playcount']
- if playcount != 0:
- # this episode has been watched, record play date (we
need it for sorting the final list) and continue to next episode
- lastplayed = item['lastplayed']
- if lastplayed == '':
- # catch exceptions where the episode has been
played, but playdate wasn't stored in the db
- lastplayed = '0'
- else:
- datetime = strptime(lastplayed, "%Y-%m-%d
%H:%M:%S")
- lastplayed = str(mktime(datetime))
- continue
+ for item in tvshow[5]:
+ playcount = item['playcount']
+ if playcount != 0:
+ # this episode has been watched, record play date (we need
it for sorting the final list) and continue to next episode
+ lastplayed = item['lastplayed']
+ if lastplayed == '':
+ # catch exceptions where the episode has been played,
but playdate wasn't stored in the db
+ lastplayed = '0'
else:
- # this is the first unwatched episode, check if the
episode is partially watched
- playdate = item['lastplayed']
- if (lastplayed == "") and (playdate == ""):
- # it's a tv show with 0 watched episodes, continue
to the next tv show
- break
+ datetime = strptime(lastplayed, "%Y-%m-%d %H:%M:%S")
+ lastplayed = str(mktime(datetime))
+ continue
+ else:
+ # this is the first unwatched episode, check if the
episode is partially watched
+ playdate = item['lastplayed']
+ if (lastplayed == "") and (playdate == ""):
+ # it's a tv show with 0 watched episodes, continue to
the next tv show
+ break
+ else:
+ # this is the episode we need
+ label = item['label']
+ episode = "%.2d" % float(item['episode'])
+ path = item['file']
+ plot = item['plot']
+ season = "%.2d" % float(item['season'])
+ thumbnail = item['thumbnail']
+ showtitle = item['showtitle']
+ rating = str(round(float(item['rating']),1))
+ episodeno = "s%se%s" % ( season, episode, )
+ if not playdate == '':
+ # if the episode is partially watched, use it's
playdate for sorting
+ datetime = strptime(playdate, "%Y-%m-%d %H:%M:%S")
+ lastplayed = str(mktime(datetime))
+ resumable = "True"
else:
- # this is the episode we need
- label = item['label']
- fanart = item['fanart']
- episode = "%.2d" % float(item['episode'])
- path = item['file']
- plot = item['plot']
- season = "%.2d" % float(item['season'])
- thumbnail = item['thumbnail']
- showtitle = item['showtitle']
- rating = str(round(float(item['rating']),1))
- episodeno = "s%se%s" % ( season, episode, )
- if not playdate == '':
- # if the episode is partially watched, use
it's playdate for sorting
- datetime = strptime(playdate, "%Y-%m-%d
%H:%M:%S")
- lastplayed = str(mktime(datetime))
- resumable = "True"
- else:
- resumable = "False"
- showthumb = tvshow[1]
- studio = tvshow[2]
- seasonthumb = self._fetch_seasonthumb(tvshow[0],
season)
- self.episodes.append((lastplayed, label, episode,
season, plot, showtitle, path, thumbnail, fanart, episodeno, studio, showthumb,
seasonthumb, resumable, rating))
- # we have found our episode, collected all data,
so continue to next tv show
- break
+ resumable = "False"
+ tvshowid = tvshow[0]
+ showthumb = tvshow[1]
+ studio = tvshow[2]
+ fanart = tvshow[4]
+ seasonthumb = ''
+ self.episodes.append([lastplayed, label, episode,
season, plot, showtitle, path, thumbnail, fanart, episodeno, studio, showthumb,
seasonthumb, resumable, rating, playcount, tvshowid])
+ # we have found our episode, collected all data, so
continue to next tv show
+ break
self.episodes.sort(reverse=True)
+ # only fetch seasonthumbs for items that will actually show up in the
skin
+ for count, episode in enumerate( self.episodes ):
+ count += 1
+ tvshowid = episode[16]
+ season = episode[3]
+ episode[12] = self._fetch_seasonthumb(tvshowid, season)
+ if count == int(self.LIMIT):
+ # stop here if our list contains more items
+ break
log("episode list: %s items" % len(self.episodes))
def _fetch_songs( self ):
@@ -334,19 +359,90 @@ class Main:
# stop here if our list contains more items
break
- def _update( self, type ):
- log('playback stopped')
- xbmc.sleep(1000)
+ def _update( self, type, item, ended ):
if type == 'movie':
- self._fetch_movies()
+ found = False
+ # Delete movie from watch list movies
+ for count, movie in enumerate( self.movies ):
+ if movie[11] == item[11]:
+ item[9] = movie[9]
+ item[10] = movie[10]
+ del self.movies[count]
+ found = True
+ break
+ # If movie has a resume point, add it at the beginning
+ if not ended:
+ if found:
+ self.movies.insert( 0, item )
+ else:
+ for m in self.movieList:
+ if m['file'] == item[11]:
+ item[9] = m['fanart']
+ item[10] = m['thumbnail']
+ self.movies.insert( 0, item )
+ break
self._clear_movie_properties()
self._set_movie_properties()
elif type == 'episode':
- self._fetch_tvshows()
- self._fetch_episodes()
- self._clear_episode_properties()
- self._set_episode_properties()
+ # Only update if it was a new, unwatched episode
+ if item[15] == 0:
+ for tvshow in self.tvshows:
+ # If tv show names match, set missing values
+ if tvshow[3] == item[5]:
+ fanart = tvshow[4]
+ item[8] = fanart
+ item[10] = tvshow[2]
+ item[11] = tvshow[1]
+ tvshowid = tvshow[0]
+ item[16] = tvshowid
+ # Delete episode from watch list episodes
+ new = True
+ for count, episode in enumerate( self.episodes ):
+ if episode[5] == item[5]:
+ # record our seasonthumb here since we need it
later on
+ seasonthumb = episode[12]
+ item[12] = seasonthumb
+ item[7] = episode[7]
+ del self.episodes[count]
+ new = False
+ break
+ # If the show is marked as watched, check for a new
episode to add
+ # else add the episode at the beginning of the list
+ if ended:
+ update = False
+ insert = False
+ for ep in tvshow[5]:
+ seasonnumber = "%.2d" % float(ep['season'])
+ episodenumber = "%.2d" % float(ep['episode'])
+ if ( episodenumber != item[2] or seasonnumber
!= item[3] ) and ep['playcount'] == 0:
+ if seasonnumber != item[3]:
+ # our new episode is from the next
season, so fetch seasonthumb
+ seasonthumb =
self._fetch_seasonthumb(tvshowid, seasonnumber)
+ self.episodes.insert( 0,
[ep['lastplayed'], ep['label'], episodenumber, seasonnumber, ep['plot'],
ep['showtitle'], ep['file'], ep['thumbnail'], fanart, "s%se%s" % (
seasonnumber, episodenumber, ), tvshow[2], tvshow[1], seasonthumb, "True",
str(round(float(ep['rating']),1)), ep['playcount']] )
+ insert = True
+ if update:
+ break
+ elif episodenumber == item[2] and seasonnumber
== item[3]:
+ ep['playcount'] = 1
+ update = True
+ if insert:
+ break
+ else:
+ # If the episode wasn't in the watch list before,
set season and episode thumb
+ if new:
+ for ep in tvshow[5]:
+ seasonnumber = "%.2d" % float(ep['season'])
+ episodenumber = "%.2d" %
float(ep['episode'])
+ if episodenumber == item[2] and
seasonnumber == item[3]:
+ item[7] = ep['thumbnail']
+ item[12] =
self._fetch_seasonthumb(tvshowid, seasonnumber)
+ break
+ self.episodes.insert( 0, item )
+ break
+ self._clear_episode_properties()
+ self._set_episode_properties()
elif type == 'album':
+ xbmc.sleep(1000)
self._fetch_songs()
self._fetch_albums()
self._clear_album_properties()
@@ -360,12 +456,26 @@ class MyPlayer(xbmc.Player):
self.episodes = kwargs[ "episodes" ]
self.albums = kwargs[ "albums" ]
self.substrings = [ '-trailer', 'http://' ]
+ self.timer = ""
self.initValues()
-
+
def onPlayBackStarted( self ):
+ # Set values based on the file content
if ( self.isPlayingAudio() ):
- self.audioPlaycount += 1
+ self.setValues( 'album' )
else:
+ # Stop timer thread on start
+ self.stopTimer()
+ # Update if an item was played (player is playing a playlist)
+ if len(self.item) > 0:
+ if self.type == 'movie' and self.movies:
+ self.action( 'movie', self.item, ( self.time < 3*60 or
self.totalTime * 0.9 <= self.time ) )
+ if self.type == 'episode' and self.episodes:
+ self.action( 'episode', self.item, ( self.totalTime * 0.9
<= self.time ) )
+ self.initValues()
+ # Start timer thread
+ self.timer = Thread(target=self.startTimer)
+ self.timer.start()
if xbmc.getCondVisibility( 'VideoPlayer.Content(movies)' ):
filename = ''
isMovie = True
@@ -378,35 +488,101 @@ class MyPlayer(xbmc.Player):
if string in filename:
isMovie = False
break
- if isMovie: self.videoPlaylist.append( 'movie' )
+ if isMovie:
+ self.setValues( 'movie' )
elif xbmc.getCondVisibility( 'VideoPlayer.Content(episodes)' ):
- self.videoPlaylist.append( 'episode' )
+ # Check for tv show title and season to make sure it's really
an episode
+ if xbmc.getInfoLabel('VideoPlayer.Season') != "" and
xbmc.getInfoLabel('VideoPlayer.TVShowTitle') != "":
+ self.setValues( 'episode' )
def onPlayBackEnded( self ):
- # If an audio file, movie or episode was played, update watch list
- if self.audioPlaycount > 1 and self.albums:
- self.action( 'album' )
- if 'movie' in self.videoPlaylist and self.movies:
- self.action( 'movie' )
- if 'episode' in self.videoPlaylist and self.episodes:
- self.action( 'episode' )
+ self.stopTimer()
+ if self.type == 'album' and self.albums:
+ self.action( 'album', self.item, True )
+ if self.type == 'movie' and self.movies:
+ self.action( 'movie', self.item, True )
+ if self.type == 'episode' and self.episodes:
+ self.action( 'episode', self.item, True )
self.initValues()
def onPlayBackStopped( self ):
- # If at least one audio file was played completely (playcount update)
- # or if a movie or episode is in the playlist, update watch list
- if self.audioPlaycount > 1 and self.albums:
- self.action( 'album' )
- if 'movie' in self.videoPlaylist and self.movies:
- self.action( 'movie' )
- if 'episode' in self.videoPlaylist and self.episodes:
- self.action( 'episode' )
+ self.stopTimer()
+ if self.type == 'album' and self.albums:
+ self.action( 'album', self.item, True )
+ if self.type == 'movie' and self.movies:
+ self.action( 'movie', self.item, ( self.time < 3*60 or
self.totalTime * 0.9 <= self.time ) )
+ if self.type == 'episode' and self.episodes:
+ self.action( 'episode', self.item, ( self.totalTime * 0.9 <=
self.time ) )
self.initValues()
-
+
+ def setValues( self, type ):
+ self.type = type
+ self.totalTime = 0
+ try:
+ self.totalTime = self.getTotalTime()
+ except:
+ pass
+ if type == 'movie':
+ label = xbmc.getInfoLabel('VideoPlayer.Title')
+ year = xbmc.getInfoLabel('VideoPlayer.Year')
+ genre = xbmc.getInfoLabel('VideoPlayer.Genre')
+ studio = xbmc.getInfoLabel('VideoPlayer.Studio')
+ plot = xbmc.getInfoLabel('VideoPlayer.Plot')
+ plotoutline = xbmc.getInfoLabel('VideoPlayer.PlotOutline')
+ tagline = xbmc.getInfoLabel('VideoPlayer.TagLine')
+ runtime = xbmc.getInfoLabel('VideoPlayer.Duration')
+ path = xbmc.getInfoLabel('Player.Filenameandpath')
+ rating = str(xbmc.getInfoLabel('VideoPlayer.Rating'))
+ self.item = ["", label, year, genre, studio, plot, plotoutline,
tagline, runtime, "", "", path, rating]
+ elif type == 'episode':
+ label = xbmc.getInfoLabel('VideoPlayer.Title')
+ episode = "%.2d" % float(xbmc.getInfoLabel('VideoPlayer.Episode'))
+ path = xbmc.getInfoLabel('Player.Filenameandpath')
+ plot = xbmc.getInfoLabel('VideoPlayer.Plot')
+ season = "%.2d" % float(xbmc.getInfoLabel('VideoPlayer.Season'))
+ showtitle = xbmc.getInfoLabel('VideoPlayer.TVShowTitle')
+ rating = str(xbmc.getInfoLabel('VideoPlayer.Rating'))
+ episodeno = "s%se%s" % ( season, episode, )
+ studio = xbmc.getInfoLabel('VideoPlayer.Studio')
+ playcount = xbmc.getInfoLabel('VideoPlayer.PlayCount')
+ if playcount != "":
+ playcount = int(playcount)
+ else:
+ playcount = 0
+ self.item = ["", label, episode, season, plot, showtitle, path,
"", "", episodeno, "", "", "", "True", rating, playcount, ""]
+ elif type == 'album':
+ pass
+
def initValues( self ):
- self.videoPlaylist = [];
- self.audioPlaycount = 0;
-
+ self.item = []
+ self.type = ""
+ self.time = 0
+ self.totaltime = 0
+
+ def startTimer( self ):
+ runtime = 0
+ self.shutdown = False
+ setTime = False
+ while( self.isPlaying() and self.shutdown == False ):
+ try:
+ runtime = self.getTime()
+ setTime = True
+ except:
+ setTime = False
+ if (runtime <= 2):
+ xbmc.sleep(5000)
+ else:
+ xbmc.sleep(1000)
+ if setTime:
+ self.time = runtime
+
+ def stopTimer( self ):
+ if self.timer != "":
+ self.shutdown = True
+ xbmc.sleep(100)
+ if self.timer.isAlive():
+ self.timer.join()
+
if ( __name__ == "__main__" ):
- log('script version %s started' % __addonversion__)
- Main()
+ log('script version %s started' % __addonversion__)
+ Main()
-----------------------------------------------------------------------
Summary of changes:
script.watchlist/addon.xml | 2 +-
script.watchlist/changelog.txt | 11 ++
script.watchlist/default.py | 348 ++++++++++++++++++++++++++++++----------
3 files changed, 274 insertions(+), 87 deletions(-)
hooks/post-receive
--
Scripts
------------------------------------------------------------------------------
Virtualization & Cloud Management Using Capacity Planning
Cloud computing makes use of virtualization - but cloud computing
also focuses on allowing computing to be delivered as a service.
http://www.accelacomm.com/jaw/sfnl/114/51521223/
_______________________________________________
Xbmc-addons mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/xbmc-addons