The branch, eden has been updated
via f78acccc9af85eba80a61bd08221a4897b5359de (commit)
via ccbfbf609d0be00e704a171b2d9863d37bb07b66 (commit)
from a4bb2095355917ba2971d20e9b3cf04e8427ecbd (commit)
- Log -----------------------------------------------------------------
http://xbmc.git.sourceforge.net/git/gitweb.cgi?p=xbmc/plugins;a=commit;h=f78acccc9af85eba80a61bd08221a4897b5359de
commit f78acccc9af85eba80a61bd08221a4897b5359de
Author: beenje <[email protected]>
Date: Wed Feb 20 21:40:00 2013 +0100
[plugin.video.rbk.no] updated to version 2.0.9
diff --git a/plugin.video.rbk.no/addon.xml b/plugin.video.rbk.no/addon.xml
index e7327cf..48f49b9 100644
--- a/plugin.video.rbk.no/addon.xml
+++ b/plugin.video.rbk.no/addon.xml
@@ -1,12 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="plugin.video.rbk.no"
name="RBK.no"
- version="2.0.8"
+ version="2.0.9"
provider-name="spiff">
<requires>
<import addon="xbmc.python" version="2.0"/>
<import addon="script.module.beautifulsoup" version="3.0.8"/>
- <import addon="plugin.video.youtube" version="2.0.5"/>
</requires>
<extension point="xbmc.python.pluginsource"
provides="video"
diff --git a/plugin.video.rbk.no/changelog.txt
b/plugin.video.rbk.no/changelog.txt
index ea934e7..4e82a7f 100644
--- a/plugin.video.rbk.no/changelog.txt
+++ b/plugin.video.rbk.no/changelog.txt
@@ -1,3 +1,6 @@
+[B]2.0.9:[/B]
+Update for site changes
+
[B]2.0.8:[/B]
Update for site changes. Lacks pagination support due to javascript
diff --git a/plugin.video.rbk.no/default.py b/plugin.video.rbk.no/default.py
index f638c20..797fd4d 100644
--- a/plugin.video.rbk.no/default.py
+++ b/plugin.video.rbk.no/default.py
@@ -27,12 +27,28 @@ def INDEX():
response = urllib2.urlopen(req)
link=response.read()
response.close()
- links = string.split(link,'<div class="vodList"')[1].split('<div
class="vodItems"')
+ links = string.split(link,'<div class="vodList')[1].split('<div
class="vodItems')
del links[0]
for link in links:
url = 'http://www.rbk.no'+link.split('<a href="')[1].split('"')[0]
- name = link.split('<a href="')[1].split('>')[1].split('<')[0].strip()
+ name = link.split('<a href="')[2].split('>')[1].split('<')[0].strip()
+ datetab = {" januar " : ".01.",
+ " februar " : ".02.",
+ " mars " : ".03.",
+ " april " : ".04.",
+ " mai " : ".05.",
+ " juni " : ".06.",
+ " juli " : ".07.",
+ " august " : ".08.",
+ " september " : ".09.",
+ " oktober" : ".10.",
+ " november " : ".11.",
+ " desember " : ".12."}
date = link.split('<div class="vodItemDate">')[1].split('<')[0].strip()
+ pattern = re.compile('(' + '|'.join(datetab.keys()) + ')')
+ date = pattern.sub(lambda x: datetab[x.group()], date)
+ if date[2] is not '.':
+ date = '0'+date
thumb = 'http://www.rbk.no'+link.split('<img src="')[1].split('"')[0]
addLink(name,url,thumb,date)
@@ -97,4 +113,6 @@ if len(url) > 0:
else:
INDEX()
xbmcplugin.addSortMethod(int(sys.argv[1]),xbmcplugin.SORT_METHOD_DATE)
+ xbmcplugin.addSortMethod(int(sys.argv[1]),xbmcplugin.SORT_METHOD_LABEL)
+ xbmcplugin.addSortMethod(int(sys.argv[1]),xbmcplugin.SORT_METHOD_UNSORTED)
xbmcplugin.endOfDirectory(int(sys.argv[1]))
http://xbmc.git.sourceforge.net/git/gitweb.cgi?p=xbmc/plugins;a=commit;h=ccbfbf609d0be00e704a171b2d9863d37bb07b66
commit ccbfbf609d0be00e704a171b2d9863d37bb07b66
Author: beenje <[email protected]>
Date: Wed Feb 20 21:39:45 2013 +0100
[plugin.video.synopsi] updated to version 0.5.1
diff --git a/plugin.video.synopsi/addon.py b/plugin.video.synopsi/addon.py
index e1b007c..739d226 100644
--- a/plugin.video.synopsi/addon.py
+++ b/plugin.video.synopsi/addon.py
@@ -29,6 +29,7 @@ import threading
from utilities import *
from cache import StvList
from xbmcrpc import xbmc_rpc
+import resources.const as const
threading.current_thread().name = 'addon.py'
@@ -49,7 +50,8 @@ class AddonClient(object):
try:
json_data = {
'command': command,
- 'arguments': arguments
+ 'arguments': arguments,
+ 'iface_version': const.SERVICE_IFACE_VERSION
}
response = None
@@ -71,7 +73,17 @@ class AddonClient(object):
response_json = json.loads(response)
#~ xbmc.log('CLIENT / JSON RESPONSE / ' +
dump(response))
+ # handle exceptions
+ if response_json.get('exception'):
+ exc = response_json['exception']
+ if exc['type'] == 'VersionMismatch':
+ if
dialog_need_restart(t_needrestart_update):
+ raise
ShutdownRequestedException('User requested shutdown')
+
+
# TODO: some handling
+ except ShutdownRequestedException, e:
+ raise
except:
xbmc.log('CLIENT / ERROR / RESPONSE ' + str(response))
#~ raise
@@ -137,6 +149,7 @@ class AddonClient(object):
try:
dirhandle = int(sys.argv[1])
+ log('SYNOPSI ADDON (%s) START' % VERSION)
log('SYS ARGV:' + str(sys.argv))
url_parsed = urlparse.urlparse(sys.argv[2])
@@ -255,7 +268,7 @@ try:
}
]
- dialog.open_list_dialog({ 'items': items }, close=True)
+ dialog.open_list_dialog({ 'items': items }, close=False)
elif p['mode']==972:
@@ -273,6 +286,7 @@ try:
elif p['mode']==973:
+ #~ addonclient.show_video_dialog_byId(2406418)
addonclient.debug_3()
else:
raise UnknownModeException('Unknown mode: %s' % p['mode'])
diff --git a/plugin.video.synopsi/addon.xml b/plugin.video.synopsi/addon.xml
index 5046d31..38fadf6 100644
--- a/plugin.video.synopsi/addon.xml
+++ b/plugin.video.synopsi/addon.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="plugin.video.synopsi"
name="SynopsiTV"
- version="0.5.0"
+ version="0.5.1"
provider-name="Synopsi.TV">
<requires>
<import addon="xbmc.python" version="2.0"/>
diff --git a/plugin.video.synopsi/addonservice.py
b/plugin.video.synopsi/addonservice.py
index e244759..2a6d0a0 100644
--- a/plugin.video.synopsi/addonservice.py
+++ b/plugin.video.synopsi/addonservice.py
@@ -7,6 +7,7 @@ import thread
# application
from utilities import *
import dialog
+import resources.const as const
class ServiceTCPHandler(SocketServer.StreamRequestHandler):
def __init__(self, *args, **kwargs):
@@ -25,6 +26,14 @@ class ServiceTCPHandler(SocketServer.StreamRequestHandler):
return
try:
+ # check interface version
+ iface_version = json_data['iface_version']
+ if iface_version != const.SERVICE_IFACE_VERSION:
+ exc = { 'type': 'VersionMismatch',
+ 'message': 'plugin version (%s)
doesn\'t match service version (%s). Please restart service' % (iface_version,
const.SERVICE_IFACE_VERSION) }
+ self.wfile.write(json.dumps({'exception': exc}))
+ return
+
# handle requested method
methodName = json_data['command']
arguments = json_data.get('arguments', {})
@@ -33,10 +42,10 @@ class ServiceTCPHandler(SocketServer.StreamRequestHandler):
result = method(**arguments)
# convert non-string result to json string
- if not isinstance(result, str):
- result = json.dumps(result)
- elif not result:
+ if result == None:
result = '{}'
+ elif not isinstance(result, str):
+ result = json.dumps(result)
self.server._log.debug('RESULT: ' + result)
@@ -100,10 +109,10 @@ class AddonHandler(ServiceTCPHandler):
thread.start_new_thread(dialog.show_submenu, (), kwargs)
def show_video_dialog(self, json_data):
- thread.start_new_thread(dialog.show_video_dialog, (json_data))
+ thread.start_new_thread(dialog.show_video_dialog, (json_data, ))
def show_video_dialog_byId(self, stv_id):
- thread.start_new_thread(dialog.show_video_dialog_byId, (stv_id))
+ thread.start_new_thread(dialog.show_video_dialog_byId, (stv_id,
))
def open_settings(self):
__addon__ = get_current_addon()
diff --git a/plugin.video.synopsi/apiclient.py
b/plugin.video.synopsi/apiclient.py
index 26be6f3..7f92119 100644
--- a/plugin.video.synopsi/apiclient.py
+++ b/plugin.video.synopsi/apiclient.py
@@ -14,6 +14,8 @@ import httplib
# application
from utilities import *
import loggable
+import resources.const as const
+
RATING_CODE = {
1: 'like',
@@ -81,14 +83,14 @@ class ApiClient(loggable.Loggable):
# get or generate install-unique ID
ApiClient._instance = cls(
- __addon__.getSetting('BASE_URL'),
- __addon__.getSetting('KEY'),
- __addon__.getSetting('SECRET'),
+ const.BASE_URL,
+ const.KEY,
+ const.SECRET,
__addon__.getSetting('USER'),
__addon__.getSetting('PASS'),
iuid,
debugLvl=logging.ERROR,
- rel_api_url=__addon__.getSetting('REL_API_URL'),
+ rel_api_url=const.REL_API_URL
)
return ApiClient._instance
diff --git a/plugin.video.synopsi/cache.py b/plugin.video.synopsi/cache.py
index a275fd9..81d56f8 100644
--- a/plugin.video.synopsi/cache.py
+++ b/plugin.video.synopsi/cache.py
@@ -98,7 +98,7 @@ class OfflineStvList(object):
def addorupdate(self, atype, aid):
if not atype in playable_types:
return
-
+
# find out actual data about movie
movie = xbmc_rpc.get_details(atype, aid)
movie['type'] = atype
@@ -111,7 +111,7 @@ class OfflineStvList(object):
movie['stv_title_hash'] = stv_hash(path)
movie['os_title_hash'] = hash_opensubtitle(path)
-
+
# TODO: stv_subtitle_hash - hash of the subtitle file
if present
ident = {}
self._translate_xbmc2stv_keys(ident, movie)
@@ -191,6 +191,7 @@ class OfflineStvList(object):
def update(self, item):
+ changed_keys = []
typeIdStr = self._getKey(item['type'], item['id'])
cacheItem = self.byTypeId[typeIdStr]
@@ -201,8 +202,10 @@ class OfflineStvList(object):
if not cacheItem.has_key(key) or not item[key] ==
cacheItem[key]:
updateStr += key + ': ' +
str(getattr(cacheItem, key, None)) + ' -> ' + str(item[key]) + ' | '
cacheItem[key] = item[key]
+ changed_keys.append(key)
self.log('UPDATE / ' + typeIdStr + ' / ' + updateStr)
+ return (cacheItem, changed_keys)
def remove(self, atype, aid):
typeIdStr = self._getKey(atype, aid)
@@ -427,7 +430,8 @@ class OnlineStvList(OfflineStvList):
def __init__(self, uuid, apiclient, filePath=None):
super(OnlineStvList, self).__init__(uuid, filePath)
self.apiClient = apiclient
-
+ self._block_rating = None
+
@classmethod
def getDefaultList(cls, apiClient=None):
if cls._instance:
@@ -448,7 +452,17 @@ class OnlineStvList(OfflineStvList):
# if known by synopsi, add to list
if item.has_key('stvId'):
self.apiClient.libraryTitleAdd(item['stvId'])
+ # if already watched, check-in to title
+ if item.get('lastplayed'):
+ self.apiClient.titleWatched(item['stvId'],
created_time=item.get('lastplayed'))
+ def update(self, item):
+ cacheItem, changed_keys = OfflineStvList.update(self, item)
+
+ # update lastplayed only if it is not in the rating process,
and it is not the 'unwatched' action
+ if 'lastplayed' in changed_keys and cacheItem.get('lastplayed')
and not self.getBlockEvents(item['type'], item['id']):
+ self.apiClient.titleWatched(cacheItem['stvId'],
created_time=cacheItem.get('lastplayed'))
+
def remove(self, atype, aid):
if self.hasTypeId(atype, aid):
item = self.getByTypeId(atype, aid)
@@ -466,6 +480,19 @@ class OnlineStvList(OfflineStvList):
return new_item
+ def setBlockEvents(self, atype, aid):
+ self._block_rating = (atype, aid)
+
+ def resetBlockEvents(self):
+ self._block_rating = None
+
+ def getBlockEvents(self, atype, aid):
+ if self._block_rating == (atype, aid):
+ return True
+
+ return False
+
+
class AppStvList(OnlineStvList):
def get_local_tvshows(self):
local_tvshows = self.getAllByType('tvshow')
diff --git a/plugin.video.synopsi/changelog.txt
b/plugin.video.synopsi/changelog.txt
index 0416ec2..d547882 100644
--- a/plugin.video.synopsi/changelog.txt
+++ b/plugin.video.synopsi/changelog.txt
@@ -1,3 +1,13 @@
+[B]Version 0.5.1 [/B]
+
+- Fixed: labels in movie details
+- Fixed: dialog navigation, back button, hide dialogs on movie play
+- Added: mark as already watched when adding files to library
+- Added: mark as watched from context menu is properly handled
+- Fixed: bug with movie time evaluation
+- Fixed: dialogs and windows are now opened immediately after user's requests,
data are filled in afterwards
+- Fixed: few minor bugs
+
[B]Version 0.5.0 [/B]
- Added: send software info on checkin
diff --git a/plugin.video.synopsi/dialog.py b/plugin.video.synopsi/dialog.py
index c7a4e26..60959c1 100644
--- a/plugin.video.synopsi/dialog.py
+++ b/plugin.video.synopsi/dialog.py
@@ -18,6 +18,7 @@ from utilities import *
from app_apiclient import AppApiClient, AuthenticationError
from cache import StvList, DuplicateStvIdException
import top
+from threading import Thread
ACTIONS_CLICK = [7, 100]
LIST_ITEM_CONTROL_ID = 500
@@ -36,11 +37,13 @@ __profile__ = __addon__.getAddonInfo('profile')
itemFolderBack = {'name': '...', 'cover_medium': 'DefaultFolderBack.png',
'id': HACK_GO_BACK, 'type': 'HACK'}
-opendialogs = []
+open_dialogs = []
+closed_dialogs = []
+stashed_dialogs = []
def get_current_dialog():
- if opendialogs:
- return opendialogs[-1]
+ if open_dialogs:
+ return open_dialogs[-1]
else:
return None
@@ -49,33 +52,92 @@ def close_current_dialog():
if d:
d.close()
+ return d
+
def close_all_dialogs():
- for d in opendialogs:
- d.close()
- del d
+ while 1:
+ d = close_current_dialog()
+ if not d:
+ break
+
+def stash_all_dialogs():
+ while 1:
+ d = close_current_dialog()
+ if not d:
+ break
+
+ stashed_dialogs.append(d)
+
+def unstash_all_dialogs():
+ log('stashed_dialogs:' + str(stashed_dialogs))
+ for d in stashed_dialogs:
+ open_dialogs.append(d)
+ d.doModal()
+
+def open_dialog(dialogClass, xmlFile, tpl_data, close=False):
+ if close:
+ close_current_dialog()
+
+ ui = dialogClass(xmlFile, __cwd__, "Default", data=tpl_data)
+ ui.doModal()
+
+ result = ui.result
+ return result
+
+class MyDialog(xbmcgui.WindowXMLDialog):
+ def __init__(self):
+ self.parentWindow = open_dialogs[-1] if open_dialogs else None
+ open_dialogs.append(self)
+ self.result = None
+
+ def close(self):
+ # check if closing the currently opened dialog
+ if open_dialogs[-1] != self:
+ log('WARNING: Dialog queue inconsistency. Non-top
dialog close')
-class ListDialog(xbmcgui.WindowXMLDialog):
- """ Dialog for choosing movie corrections """
- def __init__(self, *args, **kwargs):
+ xbmcgui.WindowXMLDialog.close(self)
+ open_dialogs.remove(self)
+
+class ListDialog(MyDialog):
+ """ Dialog for synopsi listings with custom cover overlays """
+ def __init__(self, strXMLname, strFallbackPath, strDefaultName,
**kwargs):
+ super(ListDialog, self).__init__()
self.data = kwargs['data']
+
+ if kwargs['data'].has_key('_async_init'):
+ self._async_init = kwargs['data']['_async_init']
+
self.controlId = None
self.selectedMovie = None
- opendialogs.append(self)
+ self.listControl = None
def onInit(self):
- self.updateItems()
+ self.listControl = self.getControl(LIST_ITEM_CONTROL_ID)
+ self.listControl.reset()
+ if self.__dict__.get('_async_init'):
+ result = {}
+ kwargs = self._async_init.get('kwargs', {})
+ kwargs['result'] = result
+ try:
+ self._async_init['method'](**kwargs)
+ except (AuthenticationError, ListEmptyException) as e:
+ self.close()
+ return
+
+ self.data = result
+
+ self.updateItems()
+
def updateItems(self):
items = []
items.append(self._getListItem(itemFolderBack))
for item in self.data['items']:
li = self._getListItem(item)
items.append(li)
-
try:
- listControl = self.getControl(LIST_ITEM_CONTROL_ID)
- listControl.addItems(items)
- self.setFocus(listControl)
+ self.listControl.addItems(items)
+ self.setFocus(self.listControl)
except:
log('Adding items failed')
@@ -137,55 +199,86 @@ class ListDialog(xbmcgui.WindowXMLDialog):
else:
show_video_dialog({'type':
item.getProperty('type'), 'id': stv_id}, close=False)
- def close(self):
- # check if closing the currently opened dialog
- if opendialogs[-1] != self:
- log('WARNING: Dialog queue inconsistency. Non-top
dialog close')
-
- opendialogs.remove(self)
- xbmcgui.WindowXMLDialog.close(self)
-
-def open_list_dialog(tpl_data, close=True):
- #~ path = '/home/smid/projects/XBMC/resources/skins/Default/720p/'
- path = ''
-
- try:
- win = xbmcgui.Window(xbmcgui.getCurrentWindowDialogId())
- except ValueError, e:
- log('Window ValueError')
- ui = ListDialog(path + "custom_MyVideoNav.xml", __addonpath__,
"Default", data=tpl_data)
- ui.doModal()
- del ui
- else:
- win = xbmcgui.WindowDialog(xbmcgui.getCurrentWindowDialogId())
- if close:
- close_current_dialog()
- ui = ListDialog(path + "custom_MyVideoNav.xml", __addonpath__,
"Default", data=tpl_data)
- ui.doModal()
- del ui
+def open_list_dialog(tpl_data, close=False):
+ open_dialog(ListDialog, "custom_MyVideoNav.xml", tpl_data, close)
def show_movie_list(item_list):
open_list_dialog({ 'items': item_list })
-
def show_tvshows_episodes(stv_id):
- items = top.apiClient.get_tvshow_season(stv_id)
- open_list_dialog({'items': items })
+ def init_data(result, **kwargs):
+ log('asyn handler show_tvshows_episodes: ' + str(kwargs))
+ result['items'] = top.apiClient.get_tvshow_season(stv_id)
+
+ tpl_data = { '_async_init': { 'method': init_data, 'kwargs': {} }}
+ open_list_dialog(tpl_data)
-class VideoDialog(xbmcgui.WindowXMLDialog):
+
+class VideoDialog(MyDialog):
"""
Dialog about video information.
"""
def __init__(self, *args, **kwargs):
+ super(VideoDialog, self).__init__()
self.data = kwargs['data']
- self.parentWindow = opendialogs[-1]
self.controlId = None
- opendialogs.append(self)
+
+ def _init_data(self):
+ json_data = self.data
+ if json_data.get('type') == 'tvshow':
+ stv_details = top.apiClient.tvshow(json_data['id'],
cast_props=defaultCastProps)
+ else:
+ stv_details = top.apiClient.title(json_data['id'],
defaultDetailProps, defaultCastProps)
+
+ top.stvList.updateTitle(stv_details)
+
+ # add xbmc id if available
+ if json_data.has_key('id') and
top.stvList.hasStvId(json_data['id']):
+ cacheItem = top.stvList.getByStvId(json_data['id'])
+ json_data['xbmc_id'] = cacheItem['id']
+ try:
+ json_data['xbmc_movie_detail'] =
xbmc_rpc.get_details('movie', json_data['xbmc_id'], True)
+ except:
+ pass
+
+ # add similars or seasons (bottom covers list)
+ if stv_details['type'] == 'movie':
+ # get similar movies
+ t1_similars =
top.apiClient.titleSimilar(stv_details['id'])
+ if t1_similars.has_key('titles'):
+ stv_details['similars'] = t1_similars['titles']
+ elif stv_details['type'] == 'tvshow' and
stv_details.has_key('seasons'):
+ seasons =
top.stvList.get_tvshow_local_seasons(stv_details['id'])
+ log('seasons on disk:' + str(seasons))
+ stv_details['similars'] = [ {'id': i['id'], 'name':
'Season %d' % i['season_number'], 'cover_medium': i['cover_medium'], 'watched':
i['episodes_count'] == i['watched_count'], 'file': i['season_number'] in
seasons} for i in stv_details['seasons'] ]
+
+ # similar overlays
+ if stv_details.has_key('similars'):
+ for item in stv_details['similars']:
+ top.stvList.updateTitle(item)
+
+ oc = 0
+ if item.get('file'):
+ oc |= OverlayCode.OnYourDisk
+ if item.get('watched'):
+ oc |= OverlayCode.AlreadyWatched
+
+ if oc:
+ item['overlay'] = overlay_image[oc]
+
+ self.data = video_dialog_template_fill(stv_details, json_data)
def onInit(self):
+ # reset some default garbage
+ self.getControl(59).reset()
+
+ # initialze data for the form
+ self._init_data()
+
+ # fill-in the form
win = xbmcgui.Window(xbmcgui.getCurrentWindowDialogId())
win.setProperty("Movie.Title", self.data["name"] +
'[COLOR=gray] (' + unicode(self.data.get('year')) + ')[/COLOR]')
win.setProperty("Movie.Plot", self.data["plot"])
@@ -196,7 +289,7 @@ class VideoDialog(xbmcgui.WindowXMLDialog):
# set available labels
i = 1
- for key, value in self.data['labels'].iteritems():
+ for key, value in self.data['labels']:
win.setProperty("Movie.Label.{0}.1".format(i), key)
win.setProperty("Movie.Label.{0}.2".format(i), value)
i = i + 1
@@ -246,11 +339,11 @@ class VideoDialog(xbmcgui.WindowXMLDialog):
# play
if controlId == 5:
- self.close()
+ close_all_dialogs()
# trailer
elif controlId == 10:
- self.close()
+ close_all_dialogs()
# already watched
elif controlId == 11:
@@ -267,7 +360,6 @@ class VideoDialog(xbmcgui.WindowXMLDialog):
stv_id = int(selected_item.getProperty('id'))
if self.data['type'] == 'tvshow':
- self.close()
show_tvshows_episodes(stv_id)
else:
show_video_dialog_byId(stv_id, close=True)
@@ -301,12 +393,8 @@ class VideoDialog(xbmcgui.WindowXMLDialog):
try:
search_term =
common.getUserInput(t_correct_search_title, "")
if search_term:
- results = top.apiClient.search(search_term,
SEARCH_RESULT_LIMIT)
- if len(results['search_result']) == 0:
- dialog_ok('No results')
- else:
- data = { 'movies':
results['search_result'] }
- return open_select_movie_dialog(data)
+ data = { 'search_term': search_term }
+ return open_select_movie_dialog(data)
else:
dialog_ok(t_enter_title_to_search)
except:
@@ -314,45 +402,48 @@ class VideoDialog(xbmcgui.WindowXMLDialog):
return
- def close(self):
- # check if closing the currently opened dialog
- if opendialogs[-1] != self:
- log('WARNING: Dialog queue inconsistency. Non-top
dialog close')
-
- opendialogs.remove(self)
- xbmcgui.WindowXMLDialog.close(self)
-
-class SelectMovieDialog(xbmcgui.WindowXMLDialog):
+class SelectMovieDialog(MyDialog):
""" Dialog for choosing movie corrections """
def __init__(self, *args, **kwargs):
+ super(SelectMovieDialog, self).__init__()
self.data = kwargs['data']
self.controlId = None
self.selectedMovie = None
- opendialogs.append(self)
+
+ def _init_data(self):
+ results = top.apiClient.search(self.data['search_term'],
SEARCH_RESULT_LIMIT)
+ if len(results['search_result']) == 0:
+ dialog_ok('No results')
+ self.close()
+ return False
+ else:
+ self.data.update({ 'movies': results['search_result']
})
+ return True
def onInit(self):
- items = []
- for item in self.data['movies']:
- text = '%s [COLOR=gray](%s)[/COLOR]' % (item['name'],
item.get('year', '?'))
+ if self._init_data():
+ items = []
+ for item in self.data['movies']:
+ text = '%s [COLOR=gray](%s)[/COLOR]' %
(item['name'], item.get('year', '?'))
- if item.get('type') == 'episode':
- text = 'S%sE%s - ' % (item.get('season_number',
'??'), item.get('episode_number', '??')) + text
+ if item.get('type') == 'episode':
+ text = 'S%sE%s - ' %
(item.get('season_number', '??'), item.get('episode_number', '??')) + text
- li = xbmcgui.ListItem(text,
iconImage=item['cover_medium'])
- li.setProperty('id', str(item['id']))
- li.setProperty('director', ',
'.join(item.get('directors')) if item.has_key('directors') else t_unavail)
- cast = ', '.join([i['name'] for i in item['cast']]) if
item.has_key('cast') else t_unavail
- li.setProperty('cast', cast)
- items.append(li)
+ li = xbmcgui.ListItem(text,
iconImage=item['cover_medium'])
+ li.setProperty('id', str(item['id']))
+ li.setProperty('director', ',
'.join(item.get('directors')) if item.has_key('directors') else t_unavail)
+ cast = ', '.join([i['name'] for i in
item['cast']]) if item.has_key('cast') else t_unavail
+ li.setProperty('cast', cast)
+ items.append(li)
- self.getControl(59).addItems(items)
+ self.getControl(59).addItems(items)
def onClick(self, controlId):
log('onClick: ' + str(controlId))
if self.controlId == 59:
sel_index = self.getControl(59).getSelectedPosition()
- self.selectedMovie = self.data['movies'][sel_index]
+ self.result = self.data['movies'][sel_index]
self.close()
@@ -364,77 +455,15 @@ class SelectMovieDialog(xbmcgui.WindowXMLDialog):
if (action.getId() in CANCEL_DIALOG):
self.close()
- def close(self):
- # check if closing the currently opened dialog
- if opendialogs[-1] != self:
- log('WARNING: Dialog queue inconsistency. Non-top
dialog close')
-
- opendialogs.remove(self)
- xbmcgui.WindowXMLDialog.close(self)
-
def open_select_movie_dialog(tpl_data):
- ui = SelectMovieDialog("SelectMovie.xml", __cwd__, "Default",
data=tpl_data)
- ui.doModal()
- result = ui.selectedMovie
- del ui
- return result
+ return open_dialog(SelectMovieDialog, "SelectMovie.xml", tpl_data)
-def show_video_dialog_byId(stv_id, close=False):
- stv_details = top.apiClient.title(stv_id, defaultDetailProps,
defaultCastProps)
- top.stvList.updateTitle(stv_details)
- show_video_dialog_data(stv_details, close=close)
+def show_video_dialog_byId(stv_id, close=False):
+ show_video_dialog({'id': stv_id}, close)
def show_video_dialog(json_data, close=False):
- if json_data.get('type') == 'tvshow':
- stv_details = top.apiClient.tvshow(json_data['id'],
cast_props=defaultCastProps)
- else:
- stv_details = top.apiClient.title(json_data['id'],
defaultDetailProps, defaultCastProps)
-
- top.stvList.updateTitle(stv_details)
- show_video_dialog_data(stv_details, json_data, close)
-
-def show_video_dialog_data(stv_details, json_data={}, close=False):
- log('stv_details:' + dump(stv_details))
-
- # add xbmc id if available
- if json_data.has_key('id') and top.stvList.hasStvId(json_data['id']):
- cacheItem = top.stvList.getByStvId(json_data['id'])
- json_data['xbmc_id'] = cacheItem['id']
- try:
- json_data['xbmc_movie_detail'] =
xbmc_rpc.get_details('movie', json_data['xbmc_id'], True)
- except:
- pass
-
- # add similars or seasons (bottom covers list)
- if stv_details['type'] == 'movie':
- # get similar movies
- t1_similars = top.apiClient.titleSimilar(stv_details['id'])
- if t1_similars.has_key('titles'):
- stv_details['similars'] = t1_similars['titles']
- elif stv_details['type'] == 'tvshow' and stv_details.has_key('seasons'):
- seasons =
top.stvList.get_tvshow_local_seasons(stv_details['id'])
- log('seasons on disk:' + str(seasons))
- stv_details['similars'] = [ {'id': i['id'], 'name': 'Season %d'
% i['season_number'], 'cover_medium': i['cover_medium'], 'watched':
i['episodes_count'] == i['watched_count'], 'file': i['season_number'] in
seasons} for i in stv_details['seasons'] ]
-
-
-
- # similar overlays
- if stv_details.has_key('similars'):
- for item in stv_details['similars']:
- top.stvList.updateTitle(item)
-
- oc = 0
- if item.get('file'):
- oc |= OverlayCode.OnYourDisk
- if item.get('watched'):
- oc |= OverlayCode.AlreadyWatched
-
- if oc:
- item['overlay'] = overlay_image[oc]
-
- tpl_data = video_dialog_template_fill(stv_details, json_data)
- open_video_dialog(tpl_data, close)
+ open_video_dialog(json_data, close)
def video_dialog_template_fill(stv_details, json_data={}):
@@ -449,77 +478,50 @@ def video_dialog_template_fill(stv_details, json_data={}):
tpl_data=stv_details
- stv_labels = {}
- if tpl_data.get('genres'):
- stv_labels['Genre'] = ', '.join(tpl_data['genres'])
- if tpl_data.get('runtime'):
- stv_labels['Runtime'] = '%d min' % tpl_data['runtime']
- if tpl_data.get('directors'):
- stv_labels['Director'] = ', '.join(tpl_data['directors'])
- if tpl_data.get('cast'):
- stv_labels['Cast'] = ', '.join(map(lambda x:x['name'],
tpl_data['cast']))
- #~ if tpl_data.get('writers'):
- #~ stv_labels['Writer'] = ', '.join(tpl_data['writers'])
- if tpl_data.get('date'):
- tpl_data['release_date'] =
datetime.fromtimestamp(tpl_data['date'])
- stv_labels['Release date'] =
tpl_data['release_date'].strftime('%x')
-
- xbmclabels = {}
+ # store file in tpl
if tpl_data.has_key('xbmc_movie_detail'):
- d = tpl_data['xbmc_movie_detail']
- if d.get('director'):
- xbmclabels["Director"] = ', '.join(d['director'])
- #~ if d.get('writer'):
- #~ xbmclabels["Writer"] = d['writer']
- if d.get('runtime'):
- xbmclabels["Runtime"] = d['runtime'] + ' min'
- if d.get('premiered'):
- xbmclabels["Release date"] = d['premiered']
- if not tpl_data.get('release_date'):
- try:
- tpl_data['release_date'] =
datetime.strptime(d['premiered'], '%m/%d/%y')
- except:
- pass
-
if d.get('file'):
tpl_data['file'] = d.get('file')
- labels = {}
- labels.update(xbmclabels)
- labels.update(stv_labels)
-
- # set unavail labels
- for label in ['Genre', 'Runtime', 'Director','Cast']:
- if not labels.has_key(label):
- labels[label] = t_unavail
+ # store labels
+ labels = []
+ # append tuple to labels, translated by trfn, or the N/A string
+ def append_tuple(stv_label, tpl_label, trfn):
+ if tpl_data.get(tpl_label):
+ val = trfn(tpl_data[tpl_label])
+ else:
+ val = t_unavail
+
+ labels.append((stv_label, val))
+
+ # translate functions
+ def tr_genre(data): return ', '.join(data)
+ def tr_cast(data): return ', '.join(map(lambda x:x['name'], data))
+ def tr_runtime(data): return '%d min' % data
+
+ append_tuple('Genre', 'genres', tr_genre)
+ append_tuple('Cast', 'cast', tr_cast)
+ append_tuple('Director', 'directors', tr_genre) # reuse
tr_genre here
+ append_tuple('Runtime', 'runtime', tr_runtime)
+
+ if tpl_data.get('date'):
+ tpl_data['release_date'] =
datetime.fromtimestamp(tpl_data['date'])
+ labels.append(('Release date',
tpl_data['release_date'].strftime('%x')))
+
tpl_data['labels'] = labels
tpl_data['BottomListingLabel'] =
type2listinglabel.get(tpl_data['type'], '')
return tpl_data
def open_video_dialog(tpl_data, close=False):
- try:
- win = xbmcgui.Window(xbmcgui.getCurrentWindowDialogId())
- except ValueError, e:
- log('Window ValueError')
- ui = VideoDialog("VideoInfo.xml", __cwd__, "Default",
data=tpl_data)
- ui.doModal()
- del ui
- else:
- win = xbmcgui.WindowDialog(xbmcgui.getCurrentWindowDialogId())
- if close:
- close_current_dialog()
- ui = VideoDialog("VideoInfo.xml", __cwd__, "Default",
data=tpl_data)
- ui.doModal()
- del ui
-
+ open_dialog(VideoDialog, "VideoInfo.xml", tpl_data, close)
-def show_submenu(action_code, **kwargs):
+def get_submenu_item_list(action_code, **kwargs):
try:
item_list =
top.apiClient.get_item_list(action_code=action_code, **kwargs)
-
+
# hack HACK_SHOW_ALL_LOCAL_MOVIES
if action_code==ActionCode.LocalMovieRecco:
item_list.append(item_show_all_movies_hack)
@@ -530,16 +532,26 @@ def show_submenu(action_code, **kwargs):
except AuthenticationError as e:
if dialog_check_login_correct():
show_submenu(action_code, **kwargs)
-
- return
+
+ raise
except ListEmptyException:
dialog_ok(exc_text_by_mode(action_code))
- return
+ raise
except:
log(traceback.format_exc())
dialog_ok(t_listing_failed)
+ raise
- show_movie_list(item_list)
+ return item_list
+
+def show_submenu(action_code, **kwargs):
+ def init_data(result, **kwargs):
+ log('init_data kwargs: ' + str(kwargs))
+ result['items'] = get_submenu_item_list(**kwargs)
+
+ kwargs['action_code'] = action_code
+ tpl_data = { '_async_init': { 'method': init_data, 'kwargs': kwargs }}
+ open_list_dialog(tpl_data)
diff --git a/plugin.video.synopsi/resources/settings.xml
b/plugin.video.synopsi/resources/settings.xml
index 5803bc9..5100da8 100644
--- a/plugin.video.synopsi/resources/settings.xml
+++ b/plugin.video.synopsi/resources/settings.xml
@@ -2,21 +2,13 @@
<settings>
<category label="69500">
- <setting id="SETTINGS_VERSION" option="hidden" type="number"
visible="false" default="1" />
-
<!--Login-->
<setting label="69700" type="lsep" />
<setting id="USER" label="69503" type="text" default=""/>
<setting id="PASS" label="69502" option="hidden" type="text"
enable="!eq(-1,)" default=""/>
-
<!--TOKENS-->
- <setting id="BASE_URL" option="hidden" type="text" visible="false"
default="https://api.synopsi.tv/" />
- <setting id="REL_API_URL" option="hidden" type="text" visible="false"
default="1.0/" />
- <setting id="KEY" option="hidden" type="text" visible="false"
default="59c53964b1013defcff0155f6e4d54a4" />
- <setting id="SECRET" option="hidden" type="text" visible="false"
default="487615d20b22cdce510fd3476ed84d924e2b0c45ce7c49dc621764e05fae0904" />
-
<setting id="ADDON_SERVICE_PORT" option="hidden" type="number"
visible="false" default="9091" />
<setting id="ACCTOKEN" option="hidden" type="text" visible="false"
default=""/>
diff --git a/plugin.video.synopsi/scrobbler.py
b/plugin.video.synopsi/scrobbler.py
index 0d1cd2e..62162f2 100644
--- a/plugin.video.synopsi/scrobbler.py
+++ b/plugin.video.synopsi/scrobbler.py
@@ -12,7 +12,7 @@ import json
# application
from utilities import *
import top
-
+import dialog
TIME_UNKNOWN = 65535
CANCEL_DIALOG = (9, 10, 92, 216, 247, 257, 275, 61467, 61448, )
@@ -31,7 +31,6 @@ class SynopsiPlayer(xbmc.Player):
ended = False
stopped = False
paused = False
- ended_without_rating = False
apiclient = None
playing = False
@@ -123,7 +122,7 @@ class SynopsiPlayer(xbmc.Player):
if self.playing:
self.resumed()
- def get_time(self, default=TIME_UNKNOWN):
+ def get_time(self, default=None):
try:
if self.isPlayingVideo():
t = int(self.getTime())
@@ -131,7 +130,7 @@ class SynopsiPlayer(xbmc.Player):
raise Exception('fix: xbmc missing exception')
except:
return default
-
+
return t
def get_media_info_tag(self):
@@ -156,11 +155,9 @@ class SynopsiPlayerDecor(SynopsiPlayer):
tries to update time while we are in the
onPlayBackStopped method and handlers """
t = self.get_time()
-
if t or not self.playing:
self.current_time = t
-
#~ self.get_media_info_tag()
def started(self):
@@ -173,12 +170,10 @@ class SynopsiPlayerDecor(SynopsiPlayer):
# rate file
self.rate_file(self.last_played_file)
- def ended_without_rating(self):
- self.playerEvent('end')
+ self.onAfterStop()
def stopped(self):
self.playerEvent('stop')
- #~ self.log(dump(self.playerEvents))
percent = self.current_time / self.total_time
self.log('percent:' + str(self.current_time / self.total_time))
@@ -187,6 +182,14 @@ class SynopsiPlayerDecor(SynopsiPlayer):
self.rate_file(self.last_played_file)
else:
self.send_checkin(self.last_played_file)
+
+ self.onAfterStop()
+
+ def onAfterStop(self):
+ # unstash all dialogs, if any
+ #~ dialog.unstash_all_dialogs()
+ pass
+
def paused(self):
self.update_current_time()
@@ -204,12 +207,15 @@ class SynopsiPlayerDecor(SynopsiPlayer):
# get stv id
detail = self.cache.getByFilename(filename)
- self.log('detail: ' + str(detail))
+ self.log('rating detail: ' + str(detail))
# only for identified by synopsi
if not detail.has_key('stvId'):
return False
-
+
+ # disallow sending 'watched' event for this file from scrobbler
+ self.cache.setBlockEvents(detail['type'], detail['id'])
+
## prepare the data
data = { 'player_events': json.dumps(self.playerEvents) }
@@ -225,10 +231,14 @@ class SynopsiPlayerDecor(SynopsiPlayer):
if rating < 4:
data['rating'] = rating
- self.apiclient.titleWatched(detail['stvId'], **data)
-
- # clear the player events
- self.playerEvents = []
+ try:
+ self.apiclient.titleWatched(detail['stvId'], **data)
+ finally:
+ # allow sending 'watched' event for this file from
scrobbler
+ self.cache.resetBlockEvents()
+
+ # clear the player events
+ self.playerEvents = []
def send_checkin(self, filename):
self.rate_file(filename, rate=False)
diff --git a/plugin.video.synopsi/service.py b/plugin.video.synopsi/service.py
index 5b7c419..c8b81f5 100644
--- a/plugin.video.synopsi/service.py
+++ b/plugin.video.synopsi/service.py
@@ -14,7 +14,7 @@ import time
from scrobbler import SynopsiPlayerDecor
from library import RPCListenerHandler
from cache import *
-from utilities import home_screen_fill, login_screen, log
+from utilities import home_screen_fill, login_screen, log, VERSION
from app_apiclient import AppApiClient
from addonservice import AddonService
import top
@@ -30,6 +30,8 @@ __addon__.setSetting('ADDON_SERVICE_FIRSTRUN', "false")
DEFAULT_SERVICE_PORT=int(__addon__.getSetting('ADDON_SERVICE_PORT'))
def main():
+ log('SYNOPSI SERVICE (%s) START' % VERSION)
+
apiclient1 = AppApiClient.getDefaultClient()
top.apiClient = apiclient1
diff --git a/plugin.video.synopsi/utilities.py
b/plugin.video.synopsi/utilities.py
index 7335f02..b918ad2 100644
--- a/plugin.video.synopsi/utilities.py
+++ b/plugin.video.synopsi/utilities.py
@@ -21,6 +21,9 @@ import time
import sys
import xml.etree.ElementTree as et
+# application
+import resources.const
+
common = CommonFunctions
common.plugin = "SynopsiTV"
@@ -29,7 +32,7 @@ __addon__ = xbmcaddon.Addon()
__addonname__ = __addon__.getAddonInfo('name')
__addonpath__ = __addon__.getAddonInfo('path')
__author__ = __addon__.getAddonInfo('author')
-__version__ = __addon__.getAddonInfo('version')
+VERSION = __addon__.getAddonInfo('version')
__profile__ = xbmc.translatePath(__addon__.getAddonInfo('profile'))
__lockLoginScreen__ = threading.Lock()
@@ -85,6 +88,7 @@ t_nounwatched = 'There are no unwatched episodes in your TV
Show tracking'
t_nolocalrecco = 'There are no items in this list. Either you have no movies
in your library or they have not been recognized by Synopsi'
t_nolocaltvshow = 'There are no items in this list. Either you have no
episodes in your library or they have not been recognized by Synopsi'
t_needrestart = 'To start the SynopsiTV service, please turn off your media
center then turn it back on again. Do this now?'
+t_needrestart_update = 'Addon service has been updated. For the plugin to work
correctly, turn off your media center then turn it back on again. Do this now?'
t_enter_title_to_search = 'Enter a title name to search for.'
t_correct_search_title = 'Search for the correct title'
@@ -135,7 +139,7 @@ def os_info():
return info
def software_info():
- i = { 'os_info': os_info() }
+ i = { 'plugin_version': VERSION, 'os_info': os_info() }
i.update(player_info())
return i
@@ -269,21 +273,6 @@ def clear_setting_cache():
if os.path.exists(settingsPath):
os.remove(settingsPath)
-def get_settings_file_version():
- path = os.path.join(__addonpath__, 'resources', 'settings.xml')
-
- value = None
- try:
- with open(path, 'r') as _file:
- temp = _file.read()
- if "SETTINGS_VERSION" in temp:
- version = re.compile('\<setting
id="SETTINGS_VERSION" option="hidden" type="number" visible="false"
default="(\d+)" /\>').findall(temp)
- value = int(version[0])
- except (IOError, IndexError):
- pass
-
- return value
-
def setting_cache_append_string(string):
settingsPath = os.path.join(__profile__, 'settings.xml')
@@ -671,9 +660,9 @@ def dialog_login_fail_yesno():
return result
-def dialog_need_restart():
+def dialog_need_restart(reason=t_needrestart):
dialog = xbmcgui.Dialog()
- yes = dialog_yesno(t_needrestart)
+ yes = dialog_yesno(reason)
return yes
@@ -711,7 +700,7 @@ def show_categories():
xbmc.executebuiltin("Container.SetViewMode(503)")
add_directory("Movie Recommendations", "url", ActionCode.MovieRecco,
"list.png")
add_directory("Popular TV Shows", "url", ActionCode.TVShows, "list.png")
- add_directory("Local Movie recommendations", "url",
ActionCode.LocalMovieRecco, "list.png")
+ add_directory("Local Movie Recommendations", "url",
ActionCode.LocalMovieRecco, "list.png")
add_directory("Local TV Shows", "url", ActionCode.LocalTVShows,
"list.png")
add_directory("Unwatched TV Show Episodes", "url",
ActionCode.UnwatchedEpisodes, "list.png")
add_directory("Upcoming TV Episodes", "url",
ActionCode.UpcomingEpisodes, "list.png")
-----------------------------------------------------------------------
Summary of changes:
plugin.video.rbk.no/addon.xml | 3 +-
plugin.video.rbk.no/changelog.txt | 3 +
plugin.video.rbk.no/default.py | 22 +-
plugin.video.synopsi/_src/install_xbmc_version.sh | 1 +
plugin.video.synopsi/_src/pull_request.sh | 15 +
plugin.video.synopsi/_src/usefull_queries.sql | 12 +
plugin.video.synopsi/addon.py | 18 +-
plugin.video.synopsi/addon.xml | 2 +-
plugin.video.synopsi/addonservice.py | 19 +-
plugin.video.synopsi/apiclient.py | 10 +-
plugin.video.synopsi/cache.py | 33 ++-
plugin.video.synopsi/changelog.txt | 10 +
plugin.video.synopsi/dialog.py | 424 ++++++++++----------
.../CommonFunctions.py => resources/__init__.py} | 0
plugin.video.synopsi/resources/const.py | 9 +
plugin.video.synopsi/resources/settings.xml | 8 -
plugin.video.synopsi/scrobbler.py | 40 ++-
plugin.video.synopsi/service.py | 4 +-
plugin.video.synopsi/utilities.py | 29 +-
19 files changed, 393 insertions(+), 269 deletions(-)
create mode 100755 plugin.video.synopsi/_src/install_xbmc_version.sh
create mode 100755 plugin.video.synopsi/_src/pull_request.sh
create mode 100644 plugin.video.synopsi/_src/usefull_queries.sql
copy plugin.video.synopsi/{tests/fakeenv/CommonFunctions.py =>
resources/__init__.py} (100%)
create mode 100644 plugin.video.synopsi/resources/const.py
hooks/post-receive
--
Plugins
------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_feb
_______________________________________________
Xbmc-addons mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/xbmc-addons