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
This commit is contained in:
shaun 2016-11-13 10:39:14 +11:00
parent 7a9e29c9b7
commit 0cf8f07daf
6 changed files with 181 additions and 171 deletions

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="plugin.video.emby" <addon id="plugin.video.emby"
name="Emby" name="Emby"
version="2.3.13" version="2.3.14"
provider-name="Emby.media"> provider-name="Emby.media">
<requires> <requires>
<import addon="xbmc.python" version="2.19.0"/> <import addon="xbmc.python" version="2.19.0"/>

View File

@ -98,6 +98,11 @@ class DatabaseConn(object):
log.info("opened: %s - %s", self.path, id(self.conn)) log.info("opened: %s - %s", self.path, id(self.conn))
self.cursor = self.conn.cursor() self.cursor = self.conn.cursor()
if self.db_file == "emby":
verify_emby_database(self.cursor)
self.conn.commit()
return self.cursor return self.cursor
def _SQL(self, media_type): def _SQL(self, media_type):
@ -129,7 +134,24 @@ class DatabaseConn(object):
self.cursor.close() self.cursor.close()
self.conn.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(): def db_reset():
dialog = xbmcgui.Dialog() dialog = xbmcgui.Dialog()

View File

@ -209,7 +209,6 @@ class DownloadUtils(object):
log.debug("===== ENTER downloadUrl =====") log.debug("===== ENTER downloadUrl =====")
kwargs = {} kwargs = {}
default_link = ""
try: try:
# Ensure server info is loaded # Ensure server info is loaded
@ -247,18 +246,17 @@ class DownloadUtils(object):
log.debug("====== 204 Success ======") log.debug("====== 204 Success ======")
# Read response to release connection # Read response to release connection
response.content 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: elif response.status_code == requests.codes.ok:
try: # UNICODE - JSON object
# UNICODE - JSON object json_data = response.json()
response = response.json() log.debug("====== 200 Success ======")
log.debug("====== 200 Success ======") log.debug("Response: %s", json_data)
log.debug("Response: %s", response) return json_data
return response
except Exception:
if response.headers.get('content-type') != "text/html":
log.info("Unable to convert the response for: %s", url)
else: # Bad status code else: # Bad status code
log.error("=== Bad status response: %s ===", response.status_code) log.error("=== Bad status response: %s ===", response.status_code)
@ -282,7 +280,7 @@ class DownloadUtils(object):
if response.status_code == 400: if response.status_code == 400:
log.error("Malformed request: %s", error) log.error("Malformed request: %s", error)
raise Warning('400') raise Warning('400:' + str(error))
if response.status_code == 401: if response.status_code == 401:
# Unauthorized # Unauthorized
@ -312,12 +310,13 @@ class DownloadUtils(object):
xbmcgui.Dialog().notification(heading="Error connecting", xbmcgui.Dialog().notification(heading="Error connecting",
message="Unauthorized.", message="Unauthorized.",
icon=xbmcgui.NOTIFICATION_ERROR) icon=xbmcgui.NOTIFICATION_ERROR)
raise Warning('401') raise Warning('401:' + str(error))
except requests.exceptions.RequestException as error: except requests.exceptions.RequestException as error:
log.error("unknown error connecting to: %s", url) 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): def _ensure_server(self, server_id=None):

View File

@ -606,20 +606,6 @@ class LibrarySync(threading.Thread):
# Database out of date. # Database out of date.
return False 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): def run(self):
try: try:

View File

@ -66,172 +66,178 @@ class Player(xbmc.Player):
break break
else: count += 1 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
itemId = window("emby_%s.itemid" % currentFile)
# We may need to wait for info to be set in kodi monitor tryCount = 0
while not itemId:
xbmc.sleep(200)
itemId = window("emby_%s.itemid" % currentFile) itemId = window("emby_%s.itemid" % currentFile)
tryCount = 0 if tryCount == 20: # try 20 times or about 10 seconds
while not itemId: log.info("Could not find itemId, cancelling playback report...")
break
xbmc.sleep(200) else: tryCount += 1
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))
# Only proceed if an itemId was found. else:
embyitem = "emby_%s" % currentFile log.info("ONPLAYBACK_STARTED: %s itemid: %s" % (currentFile, itemId))
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') # Only proceed if an itemId was found.
if window('emby_customPlaylist') == "true" and customseek: embyitem = "emby_%s" % currentFile
# Start at, when using custom playlist (play to Kodi from webclient) runtime = window("%s.runtime" % embyitem)
log.info("Seeking to: %s" % customseek) refresh_id = window("%s.refreshid" % embyitem)
self.xbmcplayer.seekTime(int(customseek)/10000000.0) playMethod = window("%s.playmethod" % embyitem)
window('emby_customPlaylist.seektime', clear=True) 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() seekTime = self.xbmcplayer.getTime()
except:
# at this point we should be playing and if not then bail out
return
# Get playback volume # Get playback volume
volume_query = { 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", "jsonrpc": "2.0",
"id": 1, "id": 1,
"method": "Application.GetProperties", "method": "Player.GetProperties",
"params": { "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 = json.loads(result)
result = result.get('result') result = result.get('result')
volume = result.get('volume')
muted = result.get('muted')
# Postdata structure to send to Emby server try: # Audio tracks
url = "{server}/emby/Sessions/Playing" indexAudio = result['currentaudiostream']['index']
postdata = { except (KeyError, TypeError):
indexAudio = 0
'QueueableMediaTypes': "Video", try: # Subtitles tracks
'CanSeek': True, indexSubs = result['currentsubtitle']['index']
'ItemId': itemId, except (KeyError, TypeError):
'MediaSourceId': itemId, indexSubs = 0
'PlayMethod': playMethod,
'VolumeLevel': volume,
'PositionTicks': int(seekTime * 10000000),
'IsMuted': muted
}
# Get the current audio track and subtitles try: # If subtitles are enabled
if playMethod == "Transcode": subsEnabled = result['subtitleenabled']
# property set in PlayUtils.py except (KeyError, TypeError):
postdata['AudioStreamIndex'] = window("%sAudioStreamIndex" % currentFile) subsEnabled = ""
postdata['SubtitleStreamIndex'] = window("%sSubtitleStreamIndex" % currentFile)
# 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: else:
# Get the current kodi audio and subtitles and convert to Emby equivalent postdata['SubtitleStreamIndex'] = ""
tracks_query = {
"jsonrpc": "2.0",
"id": 1,
"method": "Player.GetProperties",
"params": {
"playerid": 1, # Post playback to server
"properties": ["currentsubtitle","currentaudiostream","subtitleenabled"] log.debug("Sending POST play started: %s." % postdata)
} self.doUtils(url, postBody=postdata, action_type="POST")
}
result = xbmc.executeJSONRPC(json.dumps(tracks_query))
result = json.loads(result)
result = result.get('result')
try: # Audio tracks # Ensure we do have a runtime
indexAudio = result['currentaudiostream']['index'] try:
except (KeyError, TypeError): runtime = int(runtime)
indexAudio = 0 except ValueError:
runtime = self.xbmcplayer.getTotalTime()
try: # Subtitles tracks log.info("Runtime is missing, Kodi runtime: %s" % runtime)
indexSubs = result['currentsubtitle']['index']
except (KeyError, TypeError):
indexSubs = 0
try: # If subtitles are enabled # Save data map for updates and position calls
subsEnabled = result['subtitleenabled'] data = {
except (KeyError, TypeError):
subsEnabled = ""
# Postdata for the audio 'runtime': runtime,
postdata['AudioStreamIndex'] = indexAudio + 1 'item_id': itemId,
'refresh_id': refresh_id,
# Postdata for the subtitles 'currentfile': currentFile,
if subsEnabled and len(xbmc.Player().getAvailableSubtitleStreams()) > 0: 'AudioStreamIndex': postdata['AudioStreamIndex'],
'SubtitleStreamIndex': postdata['SubtitleStreamIndex'],
# Number of audiotracks to help get Emby Index 'playmethod': playMethod,
audioTracks = len(xbmc.Player().getAvailableAudioStreams()) 'Type': itemType,
mapping = window("%s.indexMapping" % embyitem) 'currentPosition': int(seekTime)
}
if mapping: # Set in playbackutils.py self.played_info[currentFile] = data
log.info("ADDING_FILE: %s" % self.played_info)
log.debug("Mapping for external subtitles index: %s" % mapping)
externalIndex = json.loads(mapping)
if externalIndex.get(str(indexSubs)): ga = GoogleAnalytics()
# If the current subtitle is in the mapping ga.sendEventData("PlayAction", itemType, playMethod)
postdata['SubtitleStreamIndex'] = externalIndex[str(indexSubs)] ga.sendScreenView(itemType)
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)
def reportPlayback(self): def reportPlayback(self):

View File

@ -100,9 +100,6 @@ class Service(object):
self.websocket_thread = wsc.WebSocketClient() self.websocket_thread = wsc.WebSocketClient()
self.library_thread = librarysync.LibrarySync() self.library_thread = librarysync.LibrarySync()
# Verify database structure, otherwise create it.
self.library_thread._verify_emby_database()
while not self.monitor.abortRequested(): while not self.monitor.abortRequested():
if window('emby_kodiProfile') != kodi_profile: if window('emby_kodiProfile') != kodi_profile: