From 0cf8f07daf7729fadba3be0e71bd7bacd1fa161b Mon Sep 17 00:00:00 2001 From: shaun Date: Sun, 13 Nov 2016 10:39:14 +1100 Subject: [PATCH] refactor the downloadutils a little move emby DB verify to the database class and run it for the first time an emby db con is created refactor the play class playback started function a little --- addon.xml | 2 +- resources/lib/database.py | 24 ++- resources/lib/downloadutils.py | 27 ++-- resources/lib/librarysync.py | 14 -- resources/lib/player.py | 282 +++++++++++++++++---------------- resources/lib/service_entry.py | 3 - 6 files changed, 181 insertions(+), 171 deletions(-) diff --git a/addon.xml b/addon.xml index 82dc9651..1a919b93 100644 --- a/addon.xml +++ b/addon.xml @@ -1,7 +1,7 @@ diff --git a/resources/lib/database.py b/resources/lib/database.py index a4746836..ec4906a9 100644 --- a/resources/lib/database.py +++ b/resources/lib/database.py @@ -98,6 +98,11 @@ class DatabaseConn(object): log.info("opened: %s - %s", self.path, id(self.conn)) self.cursor = self.conn.cursor() + + if self.db_file == "emby": + verify_emby_database(self.cursor) + self.conn.commit() + return self.cursor def _SQL(self, media_type): @@ -129,7 +134,24 @@ class DatabaseConn(object): self.cursor.close() self.conn.close() - + +def verify_emby_database(cursor): + # Create the tables for the emby database + # emby, view, version + + if window('emby_db_checked') != "true": + log.info("Verifying emby DB") + cursor.execute( + """CREATE TABLE IF NOT EXISTS emby( + emby_id TEXT UNIQUE, media_folder TEXT, emby_type TEXT, media_type TEXT, + kodi_id INTEGER, kodi_fileid INTEGER, kodi_pathid INTEGER, parent_id INTEGER, + checksum INTEGER)""") + cursor.execute( + """CREATE TABLE IF NOT EXISTS view( + view_id TEXT UNIQUE, view_name TEXT, media_type TEXT, kodi_tagid INTEGER)""") + cursor.execute("CREATE TABLE IF NOT EXISTS version(idVersion TEXT)") + window('emby_db_checked', value="true") + def db_reset(): dialog = xbmcgui.Dialog() diff --git a/resources/lib/downloadutils.py b/resources/lib/downloadutils.py index 57373204..790e8433 100644 --- a/resources/lib/downloadutils.py +++ b/resources/lib/downloadutils.py @@ -209,7 +209,6 @@ class DownloadUtils(object): log.debug("===== ENTER downloadUrl =====") kwargs = {} - default_link = "" try: # Ensure server info is loaded @@ -247,18 +246,17 @@ class DownloadUtils(object): log.debug("====== 204 Success ======") # Read response to release connection response.content + if action_type == "GET": + raise Warning("Response Code 204: No Content for GET request") + else: + return None elif response.status_code == requests.codes.ok: - try: - # UNICODE - JSON object - response = response.json() - log.debug("====== 200 Success ======") - log.debug("Response: %s", response) - return response - - except Exception: - if response.headers.get('content-type') != "text/html": - log.info("Unable to convert the response for: %s", url) + # UNICODE - JSON object + json_data = response.json() + log.debug("====== 200 Success ======") + log.debug("Response: %s", json_data) + return json_data else: # Bad status code log.error("=== Bad status response: %s ===", response.status_code) @@ -282,7 +280,7 @@ class DownloadUtils(object): if response.status_code == 400: log.error("Malformed request: %s", error) - raise Warning('400') + raise Warning('400:' + str(error)) if response.status_code == 401: # Unauthorized @@ -312,12 +310,13 @@ class DownloadUtils(object): xbmcgui.Dialog().notification(heading="Error connecting", message="Unauthorized.", icon=xbmcgui.NOTIFICATION_ERROR) - raise Warning('401') + raise Warning('401:' + str(error)) except requests.exceptions.RequestException as error: log.error("unknown error connecting to: %s", url) - return default_link + # something went wrong so return a None as we have no valid data + return None def _ensure_server(self, server_id=None): diff --git a/resources/lib/librarysync.py b/resources/lib/librarysync.py index bc89af22..3a6962cc 100644 --- a/resources/lib/librarysync.py +++ b/resources/lib/librarysync.py @@ -606,20 +606,6 @@ class LibrarySync(threading.Thread): # Database out of date. return False - def _verify_emby_database(self): - # Create the tables for the emby database - with database.DatabaseConn('emby') as cursor: - # emby, view, version - cursor.execute( - """CREATE TABLE IF NOT EXISTS emby( - emby_id TEXT UNIQUE, media_folder TEXT, emby_type TEXT, media_type TEXT, - kodi_id INTEGER, kodi_fileid INTEGER, kodi_pathid INTEGER, parent_id INTEGER, - checksum INTEGER)""") - cursor.execute( - """CREATE TABLE IF NOT EXISTS view( - view_id TEXT UNIQUE, view_name TEXT, media_type TEXT, kodi_tagid INTEGER)""") - cursor.execute("CREATE TABLE IF NOT EXISTS version(idVersion TEXT)") - def run(self): try: diff --git a/resources/lib/player.py b/resources/lib/player.py index a61f1b6a..bbb33085 100644 --- a/resources/lib/player.py +++ b/resources/lib/player.py @@ -66,172 +66,178 @@ class Player(xbmc.Player): break else: count += 1 + # if we did not get the current file return + if currentFile == "": + return - if currentFile: + # process the playing file + self.currentFile = currentFile - self.currentFile = currentFile - - # We may need to wait for info to be set in kodi monitor + # We may need to wait for info to be set in kodi monitor + itemId = window("emby_%s.itemid" % currentFile) + tryCount = 0 + while not itemId: + + xbmc.sleep(200) itemId = window("emby_%s.itemid" % currentFile) - tryCount = 0 - while not itemId: - - xbmc.sleep(200) - itemId = window("emby_%s.itemid" % currentFile) - if tryCount == 20: # try 20 times or about 10 seconds - log.info("Could not find itemId, cancelling playback report...") - break - else: tryCount += 1 - - else: - log.info("ONPLAYBACK_STARTED: %s itemid: %s" % (currentFile, itemId)) + if tryCount == 20: # try 20 times or about 10 seconds + log.info("Could not find itemId, cancelling playback report...") + break + else: tryCount += 1 - # Only proceed if an itemId was found. - embyitem = "emby_%s" % currentFile - runtime = window("%s.runtime" % embyitem) - refresh_id = window("%s.refreshid" % embyitem) - playMethod = window("%s.playmethod" % embyitem) - itemType = window("%s.type" % embyitem) - window('emby_skipWatched%s' % itemId, value="true") + else: + log.info("ONPLAYBACK_STARTED: %s itemid: %s" % (currentFile, itemId)) - customseek = window('emby_customPlaylist.seektime') - if window('emby_customPlaylist') == "true" and customseek: - # Start at, when using custom playlist (play to Kodi from webclient) - log.info("Seeking to: %s" % customseek) - self.xbmcplayer.seekTime(int(customseek)/10000000.0) - window('emby_customPlaylist.seektime', clear=True) + # Only proceed if an itemId was found. + embyitem = "emby_%s" % currentFile + runtime = window("%s.runtime" % embyitem) + refresh_id = window("%s.refreshid" % embyitem) + playMethod = window("%s.playmethod" % embyitem) + itemType = window("%s.type" % embyitem) + window('emby_skipWatched%s' % itemId, value="true") + customseek = window('emby_customPlaylist.seektime') + if window('emby_customPlaylist') == "true" and customseek: + # Start at, when using custom playlist (play to Kodi from webclient) + log.info("Seeking to: %s" % customseek) + self.xbmcplayer.seekTime(int(customseek)/10000000.0) + window('emby_customPlaylist.seektime', clear=True) + + try: seekTime = self.xbmcplayer.getTime() + except: + # at this point we should be playing and if not then bail out + return - # Get playback volume - volume_query = { + # Get playback volume + volume_query = { + + "jsonrpc": "2.0", + "id": 1, + "method": "Application.GetProperties", + "params": { + + "properties": ["volume", "muted"] + } + } + result = xbmc.executeJSONRPC(json.dumps(volume_query)) + result = json.loads(result) + result = result.get('result') + + volume = result.get('volume') + muted = result.get('muted') + + # Postdata structure to send to Emby server + url = "{server}/emby/Sessions/Playing" + postdata = { + + 'QueueableMediaTypes': "Video", + 'CanSeek': True, + 'ItemId': itemId, + 'MediaSourceId': itemId, + 'PlayMethod': playMethod, + 'VolumeLevel': volume, + 'PositionTicks': int(seekTime * 10000000), + 'IsMuted': muted + } + + # Get the current audio track and subtitles + if playMethod == "Transcode": + # property set in PlayUtils.py + postdata['AudioStreamIndex'] = window("%sAudioStreamIndex" % currentFile) + postdata['SubtitleStreamIndex'] = window("%sSubtitleStreamIndex" % currentFile) + else: + # Get the current kodi audio and subtitles and convert to Emby equivalent + tracks_query = { "jsonrpc": "2.0", "id": 1, - "method": "Application.GetProperties", + "method": "Player.GetProperties", "params": { - "properties": ["volume", "muted"] + "playerid": 1, + "properties": ["currentsubtitle","currentaudiostream","subtitleenabled"] } } - result = xbmc.executeJSONRPC(json.dumps(volume_query)) + result = xbmc.executeJSONRPC(json.dumps(tracks_query)) result = json.loads(result) result = result.get('result') - - volume = result.get('volume') - muted = result.get('muted') - # Postdata structure to send to Emby server - url = "{server}/emby/Sessions/Playing" - postdata = { + try: # Audio tracks + indexAudio = result['currentaudiostream']['index'] + except (KeyError, TypeError): + indexAudio = 0 - 'QueueableMediaTypes': "Video", - 'CanSeek': True, - 'ItemId': itemId, - 'MediaSourceId': itemId, - 'PlayMethod': playMethod, - 'VolumeLevel': volume, - 'PositionTicks': int(seekTime * 10000000), - 'IsMuted': muted - } + try: # Subtitles tracks + indexSubs = result['currentsubtitle']['index'] + except (KeyError, TypeError): + indexSubs = 0 - # Get the current audio track and subtitles - if playMethod == "Transcode": - # property set in PlayUtils.py - postdata['AudioStreamIndex'] = window("%sAudioStreamIndex" % currentFile) - postdata['SubtitleStreamIndex'] = window("%sSubtitleStreamIndex" % currentFile) + try: # If subtitles are enabled + subsEnabled = result['subtitleenabled'] + except (KeyError, TypeError): + subsEnabled = "" + + # Postdata for the audio + postdata['AudioStreamIndex'] = indexAudio + 1 + + # Postdata for the subtitles + if subsEnabled and len(xbmc.Player().getAvailableSubtitleStreams()) > 0: + + # Number of audiotracks to help get Emby Index + audioTracks = len(xbmc.Player().getAvailableAudioStreams()) + mapping = window("%s.indexMapping" % embyitem) + + if mapping: # Set in playbackutils.py + + log.debug("Mapping for external subtitles index: %s" % mapping) + externalIndex = json.loads(mapping) + + if externalIndex.get(str(indexSubs)): + # If the current subtitle is in the mapping + postdata['SubtitleStreamIndex'] = externalIndex[str(indexSubs)] + else: + # Internal subtitle currently selected + subindex = indexSubs - len(externalIndex) + audioTracks + 1 + postdata['SubtitleStreamIndex'] = subindex + + else: # Direct paths enabled scenario or no external subtitles set + postdata['SubtitleStreamIndex'] = indexSubs + audioTracks + 1 else: - # Get the current kodi audio and subtitles and convert to Emby equivalent - tracks_query = { + postdata['SubtitleStreamIndex'] = "" - "jsonrpc": "2.0", - "id": 1, - "method": "Player.GetProperties", - "params": { - "playerid": 1, - "properties": ["currentsubtitle","currentaudiostream","subtitleenabled"] - } - } - result = xbmc.executeJSONRPC(json.dumps(tracks_query)) - result = json.loads(result) - result = result.get('result') + # Post playback to server + log.debug("Sending POST play started: %s." % postdata) + self.doUtils(url, postBody=postdata, action_type="POST") - try: # Audio tracks - indexAudio = result['currentaudiostream']['index'] - except (KeyError, TypeError): - indexAudio = 0 - - try: # Subtitles tracks - indexSubs = result['currentsubtitle']['index'] - except (KeyError, TypeError): - indexSubs = 0 + # Ensure we do have a runtime + try: + runtime = int(runtime) + except ValueError: + runtime = self.xbmcplayer.getTotalTime() + log.info("Runtime is missing, Kodi runtime: %s" % runtime) - try: # If subtitles are enabled - subsEnabled = result['subtitleenabled'] - except (KeyError, TypeError): - subsEnabled = "" + # Save data map for updates and position calls + data = { - # Postdata for the audio - postdata['AudioStreamIndex'] = indexAudio + 1 - - # Postdata for the subtitles - if subsEnabled and len(xbmc.Player().getAvailableSubtitleStreams()) > 0: - - # Number of audiotracks to help get Emby Index - audioTracks = len(xbmc.Player().getAvailableAudioStreams()) - mapping = window("%s.indexMapping" % embyitem) + 'runtime': runtime, + 'item_id': itemId, + 'refresh_id': refresh_id, + 'currentfile': currentFile, + 'AudioStreamIndex': postdata['AudioStreamIndex'], + 'SubtitleStreamIndex': postdata['SubtitleStreamIndex'], + 'playmethod': playMethod, + 'Type': itemType, + 'currentPosition': int(seekTime) + } - if mapping: # Set in playbackutils.py - - log.debug("Mapping for external subtitles index: %s" % mapping) - externalIndex = json.loads(mapping) + self.played_info[currentFile] = data + log.info("ADDING_FILE: %s" % self.played_info) - if externalIndex.get(str(indexSubs)): - # If the current subtitle is in the mapping - postdata['SubtitleStreamIndex'] = externalIndex[str(indexSubs)] - else: - # Internal subtitle currently selected - subindex = indexSubs - len(externalIndex) + audioTracks + 1 - postdata['SubtitleStreamIndex'] = subindex - - else: # Direct paths enabled scenario or no external subtitles set - postdata['SubtitleStreamIndex'] = indexSubs + audioTracks + 1 - else: - postdata['SubtitleStreamIndex'] = "" - - - # Post playback to server - log.debug("Sending POST play started: %s." % postdata) - self.doUtils(url, postBody=postdata, action_type="POST") - - # Ensure we do have a runtime - try: - runtime = int(runtime) - except ValueError: - runtime = self.xbmcplayer.getTotalTime() - log.info("Runtime is missing, Kodi runtime: %s" % runtime) - - # Save data map for updates and position calls - data = { - - 'runtime': runtime, - 'item_id': itemId, - 'refresh_id': refresh_id, - 'currentfile': currentFile, - 'AudioStreamIndex': postdata['AudioStreamIndex'], - 'SubtitleStreamIndex': postdata['SubtitleStreamIndex'], - 'playmethod': playMethod, - 'Type': itemType, - 'currentPosition': int(seekTime) - } - - self.played_info[currentFile] = data - log.info("ADDING_FILE: %s" % self.played_info) - - ga = GoogleAnalytics() - ga.sendEventData("PlayAction", itemType, playMethod) - ga.sendScreenView(itemType) + ga = GoogleAnalytics() + ga.sendEventData("PlayAction", itemType, playMethod) + ga.sendScreenView(itemType) def reportPlayback(self): diff --git a/resources/lib/service_entry.py b/resources/lib/service_entry.py index 5ed15c5c..c58d8e3a 100644 --- a/resources/lib/service_entry.py +++ b/resources/lib/service_entry.py @@ -100,9 +100,6 @@ class Service(object): self.websocket_thread = wsc.WebSocketClient() self.library_thread = librarysync.LibrarySync() - # Verify database structure, otherwise create it. - self.library_thread._verify_emby_database() - while not self.monitor.abortRequested(): if window('emby_kodiProfile') != kodi_profile: