mirror of
https://github.com/jellyfin/jellyfin-kodi.git
synced 2025-01-24 17:06:11 +00:00
Pylint (#59)
This commit is contained in:
parent
e941674e74
commit
b945459dfb
8 changed files with 447 additions and 419 deletions
321
contextmenu.py
321
contextmenu.py
|
@ -5,171 +5,204 @@
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import urlparse
|
|
||||||
|
|
||||||
import xbmc
|
import xbmc
|
||||||
import xbmcaddon
|
import xbmcaddon
|
||||||
import xbmcgui
|
|
||||||
|
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
_addon = xbmcaddon.Addon(id='plugin.video.emby')
|
_ADDON = xbmcaddon.Addon(id='plugin.video.emby')
|
||||||
_addon_path = _addon.getAddonInfo('path').decode('utf-8')
|
_CWD = _ADDON.getAddonInfo('path').decode('utf-8')
|
||||||
_base_resource = xbmc.translatePath(os.path.join(_addon_path, 'resources', 'lib')).decode('utf-8')
|
_BASE_LIB = xbmc.translatePath(os.path.join(_CWD, 'resources', 'lib')).decode('utf-8')
|
||||||
sys.path.append(_base_resource)
|
sys.path.append(_BASE_LIB)
|
||||||
|
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
import api
|
import api
|
||||||
import artwork
|
import loghandler
|
||||||
import downloadutils
|
|
||||||
import librarysync
|
|
||||||
import read_embyserver as embyserver
|
import read_embyserver as embyserver
|
||||||
import embydb_functions as embydb
|
import embydb_functions as embydb
|
||||||
import kodidb_functions as kodidb
|
|
||||||
import musicutils as musicutils
|
import musicutils as musicutils
|
||||||
from utils import settings, language as lang, kodiSQL
|
from utils import settings, dialog, language as lang, kodiSQL
|
||||||
|
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
import loghandler
|
|
||||||
|
|
||||||
loghandler.config()
|
loghandler.config()
|
||||||
log = logging.getLogger("EMBY.contextmenu")
|
log = logging.getLogger("EMBY.contextmenu")
|
||||||
|
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
|
OPTIONS = {
|
||||||
|
|
||||||
|
'Refresh': lang(30410),
|
||||||
|
'Delete': lang(30409),
|
||||||
|
'Addon': lang(30408),
|
||||||
|
'AddFav': lang(30405),
|
||||||
|
'RemoveFav': lang(30406),
|
||||||
|
'RateSong': lang(30407)
|
||||||
|
}
|
||||||
|
|
||||||
|
class ContextMenu(object):
|
||||||
|
|
||||||
|
_selected_option = None
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
|
||||||
|
self.emby = embyserver.Read_EmbyServer()
|
||||||
|
|
||||||
|
self.kodi_id = xbmc.getInfoLabel('ListItem.DBID').decode('utf-8')
|
||||||
|
self.item_type = self._get_item_type()
|
||||||
|
self.item_id = self._get_item_id(self.kodi_id, self.item_type)
|
||||||
|
|
||||||
|
log.info("Found item_id: %s item_type: %s", self.item_id, self.item_type)
|
||||||
|
|
||||||
|
if self.item_id:
|
||||||
|
|
||||||
|
self.item = self.emby.getItem(self.item_id)
|
||||||
|
self.api = api.API(self.item)
|
||||||
|
|
||||||
|
if self._select_menu():
|
||||||
|
self._action_menu()
|
||||||
|
|
||||||
|
xbmc.sleep(500)
|
||||||
|
xbmc.executebuiltin('Container.Refresh')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _get_item_type(cls):
|
||||||
|
|
||||||
|
item_type = xbmc.getInfoLabel('ListItem.DBTYPE').decode('utf-8')
|
||||||
|
|
||||||
|
if not item_type:
|
||||||
|
|
||||||
|
if xbmc.getCondVisibility('Container.Content(albums)'):
|
||||||
|
item_type = "album"
|
||||||
|
elif xbmc.getCondVisibility('Container.Content(artists)'):
|
||||||
|
item_type = "artist"
|
||||||
|
elif xbmc.getCondVisibility('Container.Content(songs)'):
|
||||||
|
item_type = "song"
|
||||||
|
elif xbmc.getCondVisibility('Container.Content(pictures)'):
|
||||||
|
item_type = "picture"
|
||||||
|
else:
|
||||||
|
log.info("item_type is unknown")
|
||||||
|
|
||||||
|
return item_type
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _get_item_id(cls, kodi_id, item_type):
|
||||||
|
|
||||||
|
item_id = xbmc.getInfoLabel('ListItem.Property(embyid)')
|
||||||
|
|
||||||
|
if not item_id and kodi_id and item_type:
|
||||||
|
|
||||||
|
conn = kodiSQL('emby')
|
||||||
|
cursor = conn.cursor()
|
||||||
|
emby_db = embydb.Embydb_Functions(cursor)
|
||||||
|
item = emby_db.getItem_byKodiId(kodi_id, item_type)
|
||||||
|
cursor.close()
|
||||||
|
try:
|
||||||
|
item_id = item[0]
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return item_id
|
||||||
|
|
||||||
|
def _select_menu(self):
|
||||||
|
# Display select dialog
|
||||||
|
userdata = self.api.getUserData()
|
||||||
|
options = []
|
||||||
|
|
||||||
|
if userdata['Favorite']:
|
||||||
|
# Remove from emby favourites
|
||||||
|
options.append(OPTIONS['RemoveFav'])
|
||||||
|
else:
|
||||||
|
# Add to emby favourites
|
||||||
|
options.append(OPTIONS['AddFav'])
|
||||||
|
|
||||||
|
if self.item_type == "song":
|
||||||
|
# Set custom song rating
|
||||||
|
options.append(OPTIONS['RateSong'])
|
||||||
|
|
||||||
|
# Refresh item
|
||||||
|
options.append(OPTIONS['Refresh'])
|
||||||
|
# Delete item
|
||||||
|
options.append(OPTIONS['Delete'])
|
||||||
|
# Addon settings
|
||||||
|
options.append(OPTIONS['Addon'])
|
||||||
|
|
||||||
|
resp = dialog(type_="select", heading=lang(30401), list=options)
|
||||||
|
if resp > -1:
|
||||||
|
self._selected_option = options[resp]
|
||||||
|
|
||||||
|
return self._selected_option
|
||||||
|
|
||||||
|
def _action_menu(self):
|
||||||
|
|
||||||
|
selected = self._selected_option
|
||||||
|
|
||||||
|
if selected == OPTIONS['Refresh']:
|
||||||
|
self.emby.refreshItem(self.item_id)
|
||||||
|
|
||||||
|
elif selected == OPTIONS['AddFav']:
|
||||||
|
self.emby.updateUserRating(self.item_id, favourite=True)
|
||||||
|
|
||||||
|
elif selected == OPTIONS['RemoveFav']:
|
||||||
|
self.emby.updateUserRating(self.item_id, favourite=False)
|
||||||
|
|
||||||
|
elif selected == OPTIONS['RateSong']:
|
||||||
|
self._rate_song()
|
||||||
|
|
||||||
|
elif selected == OPTIONS['Addon']:
|
||||||
|
xbmc.executebuiltin('Addon.OpenSettings(plugin.video.emby)')
|
||||||
|
|
||||||
|
elif selected == OPTIONS['Delete']:
|
||||||
|
self._delete_item()
|
||||||
|
|
||||||
|
def _rate_song(self):
|
||||||
|
|
||||||
|
conn = kodiSQL('music')
|
||||||
|
cursor = conn.cursor()
|
||||||
|
query = "SELECT rating FROM song WHERE idSong = ?"
|
||||||
|
cursor.execute(query, (self.kodi_id,))
|
||||||
|
try:
|
||||||
|
value = cursor.fetchone()[0]
|
||||||
|
current_value = int(round(float(value), 0))
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
new_value = dialog("numeric", 0, lang(30411), str(current_value))
|
||||||
|
if new_value > -1:
|
||||||
|
|
||||||
|
new_value = int(new_value)
|
||||||
|
if new_value > 5:
|
||||||
|
new_value = 5
|
||||||
|
|
||||||
|
if settings('enableUpdateSongRating') == "true":
|
||||||
|
musicutils.updateRatingToFile(new_value, self.api.getFilePath())
|
||||||
|
|
||||||
|
query = "UPDATE song SET rating = ? WHERE idSong = ?"
|
||||||
|
cursor.execute(query, (new_value, self.kodi_id,))
|
||||||
|
conn.commit()
|
||||||
|
finally:
|
||||||
|
cursor.close()
|
||||||
|
|
||||||
|
def _delete_item(self):
|
||||||
|
|
||||||
|
delete = True
|
||||||
|
if settings('skipContextMenu') != "true":
|
||||||
|
|
||||||
|
if not dialog(type_="yesno", heading="{emby}", line1=lang(33041)):
|
||||||
|
log.info("User skipped deletion for: %s", self.item_id)
|
||||||
|
delete = False
|
||||||
|
|
||||||
|
if delete:
|
||||||
|
log.info("Deleting request: %s", self.item_id)
|
||||||
|
self.emby.deleteItem(self.item_id)
|
||||||
|
|
||||||
|
|
||||||
# Kodi contextmenu item to configure the emby settings
|
# Kodi contextmenu item to configure the emby settings
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
||||||
kodiId = xbmc.getInfoLabel('ListItem.DBID').decode('utf-8')
|
log.info("plugin.video.emby contextmenu started")
|
||||||
itemType = xbmc.getInfoLabel('ListItem.DBTYPE').decode('utf-8')
|
ContextMenu()
|
||||||
itemId = ""
|
log.info("plugin.video.emby contextmenu stopped")
|
||||||
|
|
||||||
if not itemType:
|
|
||||||
|
|
||||||
if xbmc.getCondVisibility("Container.Content(albums)"):
|
|
||||||
itemType = "album"
|
|
||||||
elif xbmc.getCondVisibility("Container.Content(artists)"):
|
|
||||||
itemType = "artist"
|
|
||||||
elif xbmc.getCondVisibility("Container.Content(songs)"):
|
|
||||||
itemType = "song"
|
|
||||||
elif xbmc.getCondVisibility("Container.Content(pictures)"):
|
|
||||||
itemType = "picture"
|
|
||||||
else:
|
|
||||||
log.info("ItemType is unknown.")
|
|
||||||
|
|
||||||
if (not kodiId or kodiId == "-1") and xbmc.getInfoLabel("ListItem.Property(embyid)"):
|
|
||||||
itemId = xbmc.getInfoLabel("ListItem.Property(embyid)")
|
|
||||||
|
|
||||||
elif kodiId and itemType:
|
|
||||||
embyconn = kodiSQL('emby')
|
|
||||||
embycursor = embyconn.cursor()
|
|
||||||
emby_db = embydb.Embydb_Functions(embycursor)
|
|
||||||
item = emby_db.getItem_byKodiId(kodiId, itemType)
|
|
||||||
embycursor.close()
|
|
||||||
try:
|
|
||||||
itemId = item[0]
|
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
log.info("Found ItemId: %s ItemType: %s" % (itemId, itemType))
|
|
||||||
if itemId:
|
|
||||||
|
|
||||||
dialog = xbmcgui.Dialog()
|
|
||||||
|
|
||||||
emby = embyserver.Read_EmbyServer()
|
|
||||||
item = emby.getItem(itemId)
|
|
||||||
API = api.API(item)
|
|
||||||
userdata = API.getUserData()
|
|
||||||
likes = userdata['Likes']
|
|
||||||
favourite = userdata['Favorite']
|
|
||||||
|
|
||||||
options = []
|
|
||||||
|
|
||||||
if favourite:
|
|
||||||
# Remove from emby favourites
|
|
||||||
options.append(lang(30406))
|
|
||||||
else:
|
|
||||||
# Add to emby favourites
|
|
||||||
options.append(lang(30405))
|
|
||||||
|
|
||||||
if itemType == "song":
|
|
||||||
# Set custom song rating
|
|
||||||
options.append(lang(30407))
|
|
||||||
|
|
||||||
# Refresh item
|
|
||||||
options.append(lang(30410))
|
|
||||||
# Delete item
|
|
||||||
options.append(lang(30409))
|
|
||||||
# Addon settings
|
|
||||||
options.append(lang(30408))
|
|
||||||
|
|
||||||
# Display select dialog and process results
|
|
||||||
resp = xbmcgui.Dialog().select(lang(30401), options)
|
|
||||||
if resp > -1:
|
|
||||||
selected = options[resp]
|
|
||||||
|
|
||||||
if selected == lang(30410):
|
|
||||||
# Refresh item
|
|
||||||
emby.refreshItem(itemId)
|
|
||||||
elif selected == lang(30405):
|
|
||||||
# Add favourite
|
|
||||||
emby.updateUserRating(itemId, favourite=True)
|
|
||||||
elif selected == lang(30406):
|
|
||||||
# Delete favourite
|
|
||||||
emby.updateUserRating(itemId, favourite=False)
|
|
||||||
elif selected == lang(30407):
|
|
||||||
# Update song rating
|
|
||||||
kodiconn = kodiSQL('music')
|
|
||||||
kodicursor = kodiconn.cursor()
|
|
||||||
query = "SELECT rating FROM song WHERE idSong = ?"
|
|
||||||
kodicursor.execute(query, (kodiId,))
|
|
||||||
try:
|
|
||||||
value = kodicursor.fetchone()[0]
|
|
||||||
current_value = int(round(float(value),0))
|
|
||||||
except TypeError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
new_value = dialog.numeric(0, lang(30411), str(current_value))
|
|
||||||
if new_value > -1:
|
|
||||||
|
|
||||||
new_value = int(new_value)
|
|
||||||
if new_value > 5:
|
|
||||||
new_value = 5
|
|
||||||
|
|
||||||
if settings('enableUpdateSongRating') == "true":
|
|
||||||
musicutils.updateRatingToFile(new_value, API.getFilePath())
|
|
||||||
|
|
||||||
query = "UPDATE song SET rating = ? WHERE idSong = ?"
|
|
||||||
kodicursor.execute(query, (new_value, kodiId,))
|
|
||||||
kodiconn.commit()
|
|
||||||
|
|
||||||
'''if settings('enableExportSongRating') == "true":
|
|
||||||
like, favourite, deletelike = musicutils.getEmbyRatingFromKodiRating(new_value)
|
|
||||||
emby.updateUserRating(itemId, like, favourite, deletelike)'''
|
|
||||||
finally:
|
|
||||||
kodicursor.close()
|
|
||||||
|
|
||||||
elif selected == lang(30408):
|
|
||||||
# Open addon settings
|
|
||||||
xbmc.executebuiltin("Addon.OpenSettings(plugin.video.emby)")
|
|
||||||
|
|
||||||
elif selected == lang(30409):
|
|
||||||
# delete item from the server
|
|
||||||
delete = True
|
|
||||||
if settings('skipContextMenu') != "true":
|
|
||||||
resp = dialog.yesno(
|
|
||||||
heading=lang(29999),
|
|
||||||
line1=lang(33041))
|
|
||||||
if not resp:
|
|
||||||
log.info("User skipped deletion for: %s." % itemId)
|
|
||||||
delete = False
|
|
||||||
|
|
||||||
if delete:
|
|
||||||
log.info("Deleting request: %s" % itemId)
|
|
||||||
emby.deleteItem(itemId)
|
|
||||||
|
|
||||||
xbmc.sleep(500)
|
|
||||||
xbmc.executebuiltin('Container.Refresh')
|
|
||||||
|
|
173
default.py
173
default.py
|
@ -9,52 +9,74 @@ import urlparse
|
||||||
|
|
||||||
import xbmc
|
import xbmc
|
||||||
import xbmcaddon
|
import xbmcaddon
|
||||||
import xbmcgui
|
|
||||||
|
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
_addon = xbmcaddon.Addon(id='plugin.video.emby')
|
_ADDON = xbmcaddon.Addon(id='plugin.video.emby')
|
||||||
_addon_path = _addon.getAddonInfo('path').decode('utf-8')
|
_CWD = _ADDON.getAddonInfo('path').decode('utf-8')
|
||||||
_base_resource = xbmc.translatePath(os.path.join(_addon_path, 'resources', 'lib')).decode('utf-8')
|
_BASE_LIB = xbmc.translatePath(os.path.join(_CWD, 'resources', 'lib')).decode('utf-8')
|
||||||
sys.path.append(_base_resource)
|
sys.path.append(_BASE_LIB)
|
||||||
|
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
import entrypoint
|
import entrypoint
|
||||||
import utils
|
import loghandler
|
||||||
from utils import window, language as lang
|
from utils import window, dialog, language as lang
|
||||||
|
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
import loghandler
|
|
||||||
|
|
||||||
loghandler.config()
|
loghandler.config()
|
||||||
log = logging.getLogger("EMBY.default")
|
log = logging.getLogger("EMBY.default")
|
||||||
|
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
|
|
||||||
class Main():
|
class Main(object):
|
||||||
|
|
||||||
|
|
||||||
# MAIN ENTRY POINT
|
# MAIN ENTRY POINT
|
||||||
#@utils.profiling()
|
#@utils.profiling()
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
# Parse parameters
|
# Parse parameters
|
||||||
base_url = sys.argv[0]
|
base_url = sys.argv[0]
|
||||||
params = urlparse.parse_qs(sys.argv[2][1:])
|
path = sys.argv[2]
|
||||||
log.warn("Parameter string: %s" % sys.argv[2])
|
params = urlparse.parse_qs(path[1:])
|
||||||
|
log.warn("Parameter string: %s", path)
|
||||||
try:
|
try:
|
||||||
mode = params['mode'][0]
|
mode = params['mode'][0]
|
||||||
itemid = params.get('id')
|
except (IndexError, KeyError):
|
||||||
if itemid:
|
|
||||||
itemid = itemid[0]
|
|
||||||
except:
|
|
||||||
params = {}
|
|
||||||
mode = ""
|
mode = ""
|
||||||
|
|
||||||
|
if "/extrafanart" in base_url:
|
||||||
|
|
||||||
|
emby_path = path[1:]
|
||||||
|
emby_id = params.get('id', [""])[0]
|
||||||
|
entrypoint.getExtraFanArt(emby_id, emby_path)
|
||||||
|
|
||||||
|
elif "/Extras" in base_url or "/VideoFiles" in base_url:
|
||||||
|
|
||||||
|
emby_path = path[1:]
|
||||||
|
emby_id = params.get('id', [""])[0]
|
||||||
|
entrypoint.getVideoFiles(emby_id, emby_path)
|
||||||
|
|
||||||
|
elif not self._modes(mode, params):
|
||||||
|
# Other functions
|
||||||
|
if mode == 'settings':
|
||||||
|
xbmc.executebuiltin('Addon.OpenSettings(plugin.video.emby)')
|
||||||
|
|
||||||
|
elif mode in ('manualsync', 'fastsync', 'repair'):
|
||||||
|
self._library_sync(mode)
|
||||||
|
|
||||||
|
elif mode == 'texturecache':
|
||||||
|
import artwork
|
||||||
|
artwork.Artwork().fullTextureCacheSync()
|
||||||
|
else:
|
||||||
|
entrypoint.doMainListing()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _modes(cls, mode, params):
|
||||||
|
import utils
|
||||||
modes = {
|
modes = {
|
||||||
|
|
||||||
'reset': utils.reset,
|
'reset': utils.reset,
|
||||||
|
@ -75,76 +97,63 @@ class Main():
|
||||||
'delete': entrypoint.deleteItem,
|
'delete': entrypoint.deleteItem,
|
||||||
'connect': entrypoint.emby_connect
|
'connect': entrypoint.emby_connect
|
||||||
}
|
}
|
||||||
|
if mode in modes:
|
||||||
if "/extrafanart" in sys.argv[0]:
|
|
||||||
embypath = sys.argv[2][1:]
|
|
||||||
embyid = params.get('id',[""])[0]
|
|
||||||
entrypoint.getExtraFanArt(embyid,embypath)
|
|
||||||
return
|
|
||||||
|
|
||||||
if "/Extras" in sys.argv[0] or "/VideoFiles" in sys.argv[0]:
|
|
||||||
embypath = sys.argv[2][1:]
|
|
||||||
embyid = params.get('id',[""])[0]
|
|
||||||
entrypoint.getVideoFiles(embyid, embypath)
|
|
||||||
return
|
|
||||||
|
|
||||||
if modes.get(mode):
|
|
||||||
# Simple functions
|
# Simple functions
|
||||||
if mode == "play":
|
action = modes[mode]
|
||||||
dbid = params.get('dbid')
|
item_id = params.get('id')
|
||||||
modes[mode](itemid, dbid)
|
if item_id:
|
||||||
|
item_id = item_id[0]
|
||||||
|
|
||||||
elif mode in ("nextup", "inprogressepisodes", "recentepisodes"):
|
if mode == 'play':
|
||||||
|
database_id = params.get('dbid')
|
||||||
|
action(item_id, database_id)
|
||||||
|
|
||||||
|
elif mode in ('nextup', 'inprogressepisodes', 'recentepisodes'):
|
||||||
limit = int(params['limit'][0])
|
limit = int(params['limit'][0])
|
||||||
modes[mode](itemid, limit)
|
action(item_id, limit)
|
||||||
|
|
||||||
elif mode in ("channels","getsubfolders"):
|
|
||||||
modes[mode](itemid)
|
|
||||||
|
|
||||||
elif mode == "browsecontent":
|
|
||||||
modes[mode](itemid, params.get('type',[""])[0], params.get('folderid',[""])[0])
|
|
||||||
|
|
||||||
elif mode == "channelsfolder":
|
elif mode in ('channels', 'getsubfolders'):
|
||||||
|
action(item_id)
|
||||||
|
|
||||||
|
elif mode == 'browsecontent':
|
||||||
|
action(item_id, params.get('type', [""])[0], params.get('folderid', [""])[0])
|
||||||
|
|
||||||
|
elif mode == 'channelsfolder':
|
||||||
folderid = params['folderid'][0]
|
folderid = params['folderid'][0]
|
||||||
modes[mode](itemid, folderid)
|
action(item_id, folderid)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
modes[mode]()
|
action()
|
||||||
else:
|
|
||||||
# Other functions
|
return True
|
||||||
if mode == "settings":
|
|
||||||
xbmc.executebuiltin('Addon.OpenSettings(plugin.video.emby)')
|
return False
|
||||||
|
|
||||||
elif mode in ("manualsync", "fastsync", "repair"):
|
@classmethod
|
||||||
|
def _library_sync(cls, mode):
|
||||||
if window('emby_online') != "true":
|
|
||||||
# Server is not online, do not run the sync
|
if window('emby_online') != "true":
|
||||||
xbmcgui.Dialog().ok(heading=lang(29999),
|
# Server is not online, do not run the sync
|
||||||
line1=lang(33034))
|
dialog(type_="ok",
|
||||||
log.warn("Not connected to the emby server.")
|
heading="{emby}",
|
||||||
return
|
line1=lang(33034))
|
||||||
|
log.warn("Not connected to the emby server.")
|
||||||
if window('emby_dbScan') != "true":
|
|
||||||
import librarysync
|
elif window('emby_dbScan') != "true":
|
||||||
lib = librarysync.LibrarySync()
|
import librarysync
|
||||||
if mode == "manualsync":
|
library_sync = librarysync.LibrarySync()
|
||||||
librarysync.ManualSync().sync()
|
|
||||||
elif mode == "fastsync":
|
if mode == 'manualsync':
|
||||||
lib.startSync()
|
librarysync.ManualSync().sync()
|
||||||
else:
|
elif mode == 'fastsync':
|
||||||
lib.fullSync(repair=True)
|
library_sync.startSync()
|
||||||
else:
|
else:
|
||||||
log.warn("Database scan is already running.")
|
library_sync.fullSync(repair=True)
|
||||||
|
else:
|
||||||
elif mode == "texturecache":
|
log.warn("Database scan is already running.")
|
||||||
import artwork
|
|
||||||
artwork.Artwork().fullTextureCacheSync()
|
|
||||||
|
|
||||||
else:
|
|
||||||
entrypoint.doMainListing()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
log.info('plugin.video.emby started')
|
|
||||||
|
log.info("plugin.video.emby started")
|
||||||
Main()
|
Main()
|
||||||
log.info('plugin.video.emby stopped')
|
log.info("plugin.video.emby stopped")
|
||||||
|
|
|
@ -98,9 +98,9 @@ class PlaybackUtils():
|
||||||
dummyPlaylist = True
|
dummyPlaylist = True
|
||||||
playlist.add(playurl, listitem, index=startPos)
|
playlist.add(playurl, listitem, index=startPos)
|
||||||
# Remove the original item from playlist
|
# Remove the original item from playlist
|
||||||
self.pl.removefromPlaylist(startPos+1)
|
self.pl.remove_from_playlist(startPos+1)
|
||||||
# Readd the original item to playlist - via jsonrpc so we have full metadata
|
# Readd the original item to playlist - via jsonrpc so we have full metadata
|
||||||
self.pl.insertintoPlaylist(currentPosition+1, dbid, self.item['Type'].lower())
|
self.pl.insert_to_playlist(currentPosition+1, dbid, self.item['Type'].lower())
|
||||||
currentPosition += 1
|
currentPosition += 1
|
||||||
|
|
||||||
############### -- CHECK FOR INTROS ################
|
############### -- CHECK FOR INTROS ################
|
||||||
|
@ -131,7 +131,7 @@ class PlaybackUtils():
|
||||||
pbutils = PlaybackUtils(intro)
|
pbutils = PlaybackUtils(intro)
|
||||||
pbutils.setProperties(introPlayurl, introListItem)
|
pbutils.setProperties(introPlayurl, introListItem)
|
||||||
|
|
||||||
self.pl.insertintoPlaylist(currentPosition, url=introPlayurl)
|
self.pl.insert_to_playlist(currentPosition, url=introPlayurl)
|
||||||
introsPlaylist = True
|
introsPlaylist = True
|
||||||
currentPosition += 1
|
currentPosition += 1
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ class PlaybackUtils():
|
||||||
# Extend our current playlist with the actual item to play
|
# Extend our current playlist with the actual item to play
|
||||||
# only if there's no playlist first
|
# only if there's no playlist first
|
||||||
log.info("Adding main item to playlist.")
|
log.info("Adding main item to playlist.")
|
||||||
self.pl.addtoPlaylist(dbid, self.item['Type'].lower())
|
self.pl.add_to_playlist(dbid, self.item['Type'].lower())
|
||||||
|
|
||||||
# Ensure that additional parts are played after the main item
|
# Ensure that additional parts are played after the main item
|
||||||
currentPosition += 1
|
currentPosition += 1
|
||||||
|
@ -166,7 +166,7 @@ class PlaybackUtils():
|
||||||
pbutils.setArtwork(additionalListItem)
|
pbutils.setArtwork(additionalListItem)
|
||||||
|
|
||||||
playlist.add(additionalPlayurl, additionalListItem, index=currentPosition)
|
playlist.add(additionalPlayurl, additionalListItem, index=currentPosition)
|
||||||
self.pl.verifyPlaylist()
|
self.pl.verify_playlist()
|
||||||
currentPosition += 1
|
currentPosition += 1
|
||||||
|
|
||||||
if dummyPlaylist:
|
if dummyPlaylist:
|
||||||
|
@ -181,7 +181,7 @@ class PlaybackUtils():
|
||||||
log.debug("Resetting properties playback flag.")
|
log.debug("Resetting properties playback flag.")
|
||||||
window('emby_playbackProps', clear=True)
|
window('emby_playbackProps', clear=True)
|
||||||
|
|
||||||
#self.pl.verifyPlaylist()
|
#self.pl.verify_playlist()
|
||||||
########## SETUP MAIN ITEM ##########
|
########## SETUP MAIN ITEM ##########
|
||||||
|
|
||||||
# For transcoding only, ask for audio/subs pref
|
# For transcoding only, ask for audio/subs pref
|
||||||
|
|
|
@ -38,7 +38,7 @@ class Player(xbmc.Player):
|
||||||
|
|
||||||
self.clientInfo = clientinfo.ClientInfo()
|
self.clientInfo = clientinfo.ClientInfo()
|
||||||
self.doUtils = downloadutils.DownloadUtils().downloadUrl
|
self.doUtils = downloadutils.DownloadUtils().downloadUrl
|
||||||
self.ws = wsc.WebSocket_Client()
|
self.ws = wsc.WebSocketClient()
|
||||||
self.xbmcplayer = xbmc.Player()
|
self.xbmcplayer = xbmc.Player()
|
||||||
|
|
||||||
log.debug("Starting playback monitor.")
|
log.debug("Starting playback monitor.")
|
||||||
|
|
|
@ -2,18 +2,16 @@
|
||||||
|
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
import json
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import xbmc
|
import xbmc
|
||||||
import xbmcgui
|
import xbmcgui
|
||||||
import xbmcplugin
|
|
||||||
|
|
||||||
import playutils
|
import playutils
|
||||||
import playbackutils
|
import playbackutils
|
||||||
import embydb_functions as embydb
|
import embydb_functions as embydb
|
||||||
import read_embyserver as embyserver
|
import read_embyserver as embyserver
|
||||||
from utils import window, settings, language as lang, kodiSQL
|
from utils import window, kodiSQL, JSONRPC
|
||||||
|
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
|
@ -22,169 +20,141 @@ log = logging.getLogger("EMBY."+__name__)
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
|
|
||||||
class Playlist():
|
class Playlist(object):
|
||||||
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
self.userid = window('emby_currUser')
|
|
||||||
self.server = window('emby_server%s' % self.userid)
|
|
||||||
|
|
||||||
self.emby = embyserver.Read_EmbyServer()
|
self.emby = embyserver.Read_EmbyServer()
|
||||||
|
|
||||||
|
|
||||||
def playAll(self, itemids, startat):
|
def play_all(self, item_ids, start_at):
|
||||||
|
|
||||||
embyconn = kodiSQL('emby')
|
conn = kodiSQL('emby')
|
||||||
embycursor = embyconn.cursor()
|
cursor = conn.cursor()
|
||||||
emby_db = embydb.Embydb_Functions(embycursor)
|
emby_db = embydb.Embydb_Functions(cursor)
|
||||||
|
|
||||||
player = xbmc.Player()
|
player = xbmc.Player()
|
||||||
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
|
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
|
||||||
playlist.clear()
|
playlist.clear()
|
||||||
|
|
||||||
log.info("---*** PLAY ALL ***---")
|
log.info("---*** PLAY ALL ***---")
|
||||||
log.info("Items: %s and start at: %s" % (itemids, startat))
|
log.info("Items: %s and start at: %s", item_ids, start_at)
|
||||||
|
|
||||||
started = False
|
started = False
|
||||||
window('emby_customplaylist', value="true")
|
window('emby_customplaylist', value="true")
|
||||||
|
|
||||||
if startat != 0:
|
if start_at:
|
||||||
# Seek to the starting position
|
# Seek to the starting position
|
||||||
window('emby_customplaylist.seektime', str(startat))
|
window('emby_customplaylist.seektime', str(start_at))
|
||||||
|
|
||||||
for itemid in itemids:
|
for item_id in item_ids:
|
||||||
embydb_item = emby_db.getItem_byId(itemid)
|
|
||||||
|
log.info("Adding %s to playlist", item_id)
|
||||||
|
item = emby_db.getItem_byId(item_id)
|
||||||
try:
|
try:
|
||||||
dbid = embydb_item[0]
|
db_id = item[0]
|
||||||
mediatype = embydb_item[4]
|
media_type = item[4]
|
||||||
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# Item is not found in our database, add item manually
|
# Item is not found in our database, add item manually
|
||||||
log.info("Item was not found in the database, manually adding item.")
|
log.info("Item was not found in the database, manually adding item")
|
||||||
item = self.emby.getItem(itemid)
|
item = self.emby.getItem(item_id)
|
||||||
self.addtoPlaylist_xbmc(playlist, item)
|
self.add_to_xbmc_playlist(playlist, item)
|
||||||
else:
|
|
||||||
# Add to playlist
|
|
||||||
self.addtoPlaylist(dbid, mediatype)
|
|
||||||
|
|
||||||
log.info("Adding %s to playlist." % itemid)
|
else: # Add to playlist
|
||||||
|
self.add_to_playlist(db_id, media_type)
|
||||||
|
|
||||||
if not started:
|
if not started:
|
||||||
started = True
|
started = True
|
||||||
player.play(playlist)
|
player.play(playlist)
|
||||||
|
|
||||||
self.verifyPlaylist()
|
self.verify_playlist()
|
||||||
embycursor.close()
|
cursor.close()
|
||||||
|
|
||||||
def modifyPlaylist(self, itemids):
|
def modify_playlist(self, item_ids):
|
||||||
|
|
||||||
embyconn = kodiSQL('emby')
|
conn = kodiSQL('emby')
|
||||||
embycursor = embyconn.cursor()
|
cursor = conn.cursor()
|
||||||
emby_db = embydb.Embydb_Functions(embycursor)
|
emby_db = embydb.Embydb_Functions(cursor)
|
||||||
|
|
||||||
log.info("---*** ADD TO PLAYLIST ***---")
|
log.info("---*** ADD TO PLAYLIST ***---")
|
||||||
log.info("Items: %s" % itemids)
|
log.info("Items: %s", item_ids)
|
||||||
|
|
||||||
player = xbmc.Player()
|
|
||||||
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
|
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
|
||||||
|
|
||||||
for itemid in itemids:
|
for item_id in item_ids:
|
||||||
embydb_item = emby_db.getItem_byId(itemid)
|
|
||||||
|
log.info("Adding %s to playlist", item_id)
|
||||||
|
item = emby_db.getItem_byId(item_id)
|
||||||
try:
|
try:
|
||||||
dbid = embydb_item[0]
|
db_id = item[0]
|
||||||
mediatype = embydb_item[4]
|
media_type = item[4]
|
||||||
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# Item is not found in our database, add item manually
|
# Item is not found in our database, add item manually
|
||||||
item = self.emby.getItem(itemid)
|
item = self.emby.getItem(item_id)
|
||||||
self.addtoPlaylist_xbmc(playlist, item)
|
self.add_to_xbmc_playlist(playlist, item)
|
||||||
else:
|
|
||||||
# Add to playlist
|
|
||||||
self.addtoPlaylist(dbid, mediatype)
|
|
||||||
|
|
||||||
log.info("Adding %s to playlist." % itemid)
|
else: # Add to playlist
|
||||||
|
self.add_to_playlist(db_id, media_type)
|
||||||
|
|
||||||
self.verifyPlaylist()
|
self.verify_playlist()
|
||||||
embycursor.close()
|
cursor.close()
|
||||||
return playlist
|
return playlist
|
||||||
|
|
||||||
def addtoPlaylist(self, dbid=None, mediatype=None, url=None):
|
|
||||||
|
|
||||||
pl = {
|
@classmethod
|
||||||
|
def add_to_xbmc_playlist(cls, playlist, item):
|
||||||
'jsonrpc': "2.0",
|
|
||||||
'id': 1,
|
|
||||||
'method': "Playlist.Add",
|
|
||||||
'params': {
|
|
||||||
|
|
||||||
'playlistid': 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if dbid is not None:
|
|
||||||
pl['params']['item'] = {'%sid' % mediatype: int(dbid)}
|
|
||||||
else:
|
|
||||||
pl['params']['item'] = {'file': url}
|
|
||||||
|
|
||||||
log.debug(xbmc.executeJSONRPC(json.dumps(pl)))
|
|
||||||
|
|
||||||
def addtoPlaylist_xbmc(self, playlist, item):
|
|
||||||
|
|
||||||
playurl = playutils.PlayUtils(item).getPlayUrl()
|
playurl = playutils.PlayUtils(item).getPlayUrl()
|
||||||
if not playurl:
|
if not playurl:
|
||||||
# Playurl failed
|
log.info("Failed to retrieve playurl")
|
||||||
log.info("Failed to retrieve playurl.")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
log.info("Playurl: %s" % playurl)
|
log.info("Playurl: %s", playurl)
|
||||||
|
|
||||||
listitem = xbmcgui.ListItem()
|
listitem = xbmcgui.ListItem()
|
||||||
playbackutils.PlaybackUtils(item).setProperties(playurl, listitem)
|
playbackutils.PlaybackUtils(item).setProperties(playurl, listitem)
|
||||||
|
|
||||||
playlist.add(playurl, listitem)
|
playlist.add(playurl, listitem)
|
||||||
|
|
||||||
def insertintoPlaylist(self, position, dbid=None, mediatype=None, url=None):
|
@classmethod
|
||||||
|
def add_to_playlist(cls, db_id=None, media_type=None, url=None):
|
||||||
|
|
||||||
pl = {
|
params = {
|
||||||
|
|
||||||
'jsonrpc': "2.0",
|
'playlistid': 1
|
||||||
'id': 1,
|
|
||||||
'method': "Playlist.Insert",
|
|
||||||
'params': {
|
|
||||||
|
|
||||||
'playlistid': 1,
|
|
||||||
'position': position
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if dbid is not None:
|
if db_id is not None:
|
||||||
pl['params']['item'] = {'%sid' % mediatype: int(dbid)}
|
params['item'] = {'%sid' % media_type: int(db_id)}
|
||||||
else:
|
else:
|
||||||
pl['params']['item'] = {'file': url}
|
params['item'] = {'file': url}
|
||||||
|
|
||||||
log.debug(xbmc.executeJSONRPC(json.dumps(pl)))
|
log.debug(JSONRPC('Playlist.Add').execute(params))
|
||||||
|
|
||||||
def verifyPlaylist(self):
|
@classmethod
|
||||||
|
def insert_to_playlist(cls, position, db_id=None, media_type=None, url=None):
|
||||||
|
|
||||||
pl = {
|
params = {
|
||||||
|
|
||||||
'jsonrpc': "2.0",
|
'playlistid': 1,
|
||||||
'id': 1,
|
'position': position
|
||||||
'method': "Playlist.GetItems",
|
|
||||||
'params': {
|
|
||||||
|
|
||||||
'playlistid': 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
log.debug(xbmc.executeJSONRPC(json.dumps(pl)))
|
if db_id is not None:
|
||||||
|
params['item'] = {'%sid' % media_type: int(db_id)}
|
||||||
|
else:
|
||||||
|
params['item'] = {'file': url}
|
||||||
|
|
||||||
def removefromPlaylist(self, position):
|
log.debug(JSONRPC('Playlist.Insert').execute(params))
|
||||||
|
|
||||||
pl = {
|
@classmethod
|
||||||
|
def verify_playlist(cls):
|
||||||
|
log.debug(JSONRPC('Playlist.GetItems').execute({'playlistid': 1}))
|
||||||
|
|
||||||
'jsonrpc': "2.0",
|
@classmethod
|
||||||
'id': 1,
|
def remove_from_playlist(cls, position):
|
||||||
'method': "Playlist.Remove",
|
|
||||||
'params': {
|
|
||||||
|
|
||||||
'playlistid': 1,
|
params = {
|
||||||
'position': position
|
|
||||||
}
|
'playlistid': 1,
|
||||||
|
'position': position
|
||||||
}
|
}
|
||||||
log.debug(xbmc.executeJSONRPC(json.dumps(pl)))
|
log.debug(JSONRPC('Playlist.Remove').execute(params))
|
||||||
|
|
|
@ -57,12 +57,16 @@ def dialog(type_, **kwargs):
|
||||||
if "icon" in kwargs:
|
if "icon" in kwargs:
|
||||||
kwargs['icon'] = kwargs['icon'].replace("{emby}",
|
kwargs['icon'] = kwargs['icon'].replace("{emby}",
|
||||||
"special://home/addons/plugin.video.emby/icon.png")
|
"special://home/addons/plugin.video.emby/icon.png")
|
||||||
|
if "heading" in kwargs:
|
||||||
|
kwargs['heading'] = kwargs['heading'].replace("{emby}", language(29999))
|
||||||
|
|
||||||
types = {
|
types = {
|
||||||
'yesno': d.yesno,
|
'yesno': d.yesno,
|
||||||
'ok': d.ok,
|
'ok': d.ok,
|
||||||
'notification': d.notification,
|
'notification': d.notification,
|
||||||
'input': d.input
|
'input': d.input,
|
||||||
|
'select': d.select,
|
||||||
|
'numeric': d.numeric
|
||||||
}
|
}
|
||||||
return types[type_](**kwargs)
|
return types[type_](**kwargs)
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ log = logging.getLogger("EMBY."+__name__)
|
||||||
##################################################################################################
|
##################################################################################################
|
||||||
|
|
||||||
|
|
||||||
class WebSocket_Client(threading.Thread):
|
class WebSocketClient(threading.Thread):
|
||||||
|
|
||||||
_shared_state = {}
|
_shared_state = {}
|
||||||
|
|
||||||
|
@ -35,12 +35,12 @@ class WebSocket_Client(threading.Thread):
|
||||||
|
|
||||||
self.__dict__ = self._shared_state
|
self.__dict__ = self._shared_state
|
||||||
self.monitor = xbmc.Monitor()
|
self.monitor = xbmc.Monitor()
|
||||||
|
|
||||||
self.doutils = downloadutils.DownloadUtils()
|
self.doutils = downloadutils.DownloadUtils()
|
||||||
self.client_info = clientinfo.ClientInfo()
|
self.client_info = clientinfo.ClientInfo()
|
||||||
self.device_id = self.client_info.get_device_id()
|
self.device_id = self.client_info.get_device_id()
|
||||||
self.library_sync = librarysync.LibrarySync()
|
self.library_sync = librarysync.LibrarySync()
|
||||||
|
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,15 +66,15 @@ class WebSocket_Client(threading.Thread):
|
||||||
message_type = result['MessageType']
|
message_type = result['MessageType']
|
||||||
data = result['Data']
|
data = result['Data']
|
||||||
|
|
||||||
if message_type not in ('SessionEnded'):
|
if message_type not in ('NotificationAdded', 'SessionEnded'):
|
||||||
# Mute certain events
|
# Mute certain events
|
||||||
log.info("Message: %s" % message)
|
log.info("Message: %s", message)
|
||||||
|
|
||||||
if message_type == "Play":
|
if message_type == 'Play':
|
||||||
# A remote control play command has been sent from the server.
|
# A remote control play command has been sent from the server.
|
||||||
self._play_(data)
|
self._play_(data)
|
||||||
|
|
||||||
elif message_type == "Playstate":
|
elif message_type == 'Playstate':
|
||||||
# A remote control update playstate command has been sent from the server.
|
# A remote control update playstate command has been sent from the server.
|
||||||
self._playstate_(data)
|
self._playstate_(data)
|
||||||
|
|
||||||
|
@ -84,16 +84,7 @@ class WebSocket_Client(threading.Thread):
|
||||||
self.library_sync.triage_items("userdata", userdata_list)
|
self.library_sync.triage_items("userdata", userdata_list)
|
||||||
|
|
||||||
elif message_type == "LibraryChanged":
|
elif message_type == "LibraryChanged":
|
||||||
|
self._library_changed(data)
|
||||||
librarySync = self.library_sync
|
|
||||||
processlist = {
|
|
||||||
|
|
||||||
'added': data['ItemsAdded'],
|
|
||||||
'update': data['ItemsUpdated'],
|
|
||||||
'remove': data['ItemsRemoved']
|
|
||||||
}
|
|
||||||
for action in processlist:
|
|
||||||
librarySync.triage_items(action, processlist[action])
|
|
||||||
|
|
||||||
elif message_type == "GeneralCommand":
|
elif message_type == "GeneralCommand":
|
||||||
self._general_commands(data)
|
self._general_commands(data)
|
||||||
|
@ -118,26 +109,26 @@ class WebSocket_Client(threading.Thread):
|
||||||
|
|
||||||
playlist_ = playlist.Playlist()
|
playlist_ = playlist.Playlist()
|
||||||
|
|
||||||
if command == "PlayNow":
|
if command == 'PlayNow':
|
||||||
startat = data.get('StartPositionTicks', 0)
|
startat = data.get('StartPositionTicks', 0)
|
||||||
playlist_.playAll(item_ids, startat)
|
playlist_.play_all(item_ids, startat)
|
||||||
dialog(type_="notification",
|
dialog(type_="notification",
|
||||||
heading=lang(29999),
|
heading="{emby}",
|
||||||
message="%s %s" % (len(item_ids), lang(33004)),
|
message="%s %s" % (len(item_ids), lang(33004)),
|
||||||
icon="{emby}",
|
icon="{emby}",
|
||||||
sound=False)
|
sound=False)
|
||||||
|
|
||||||
elif command == "PlayNext":
|
elif command == 'PlayNext':
|
||||||
newplaylist = playlist_.modifyPlaylist(item_ids)
|
new_playlist = playlist_.modify_playlist(item_ids)
|
||||||
dialog(type_="notification",
|
dialog(type_="notification",
|
||||||
heading=lang(29999),
|
heading="{emby}",
|
||||||
message="%s %s" % (len(item_ids), lang(33005)),
|
message="%s %s" % (len(item_ids), lang(33005)),
|
||||||
icon="{emby}",
|
icon="{emby}",
|
||||||
sound=False)
|
sound=False)
|
||||||
player = xbmc.Player()
|
player = xbmc.Player()
|
||||||
if not player.isPlaying():
|
if not player.isPlaying():
|
||||||
# Only start the playlist if nothing is playing
|
# Only start the playlist if nothing is playing
|
||||||
player.play(newplaylist)
|
player.play(new_playlist)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _playstate_(cls, data):
|
def _playstate_(cls, data):
|
||||||
|
@ -151,21 +142,36 @@ class WebSocket_Client(threading.Thread):
|
||||||
'Unpause': player.pause,
|
'Unpause': player.pause,
|
||||||
'Pause': player.pause,
|
'Pause': player.pause,
|
||||||
'NextTrack': player.playnext,
|
'NextTrack': player.playnext,
|
||||||
'PreviousTrack': player.playprevious,
|
'PreviousTrack': player.playprevious
|
||||||
'Seek': player.seekTime
|
|
||||||
}
|
}
|
||||||
action = actions[command]
|
if command == 'Seek':
|
||||||
if command == "Seek":
|
|
||||||
seekto = data['SeekPositionTicks']
|
seek_to = data['SeekPositionTicks']
|
||||||
seektime = seekto / 10000000.0
|
seek_time = seek_to / 10000000.0
|
||||||
action(seektime)
|
player.seekTime(seek_time)
|
||||||
log.info("Seek to %s", seektime)
|
log.info("Seek to %s", seek_time)
|
||||||
else:
|
|
||||||
action()
|
elif command in actions:
|
||||||
|
actions[command]()
|
||||||
log.info("Command: %s completed", command)
|
log.info("Command: %s completed", command)
|
||||||
|
|
||||||
|
else:
|
||||||
|
log.info("Unknown command: %s", command)
|
||||||
|
return
|
||||||
|
|
||||||
window('emby_command', value="true")
|
window('emby_command', value="true")
|
||||||
|
|
||||||
|
def _library_changed(self, data):
|
||||||
|
|
||||||
|
process_list = {
|
||||||
|
|
||||||
|
'added': data['ItemsAdded'],
|
||||||
|
'update': data['ItemsUpdated'],
|
||||||
|
'remove': data['ItemsRemoved']
|
||||||
|
}
|
||||||
|
for action in process_list:
|
||||||
|
self.library_sync.triage_items(action, process_list[action])
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _general_commands(cls, data):
|
def _general_commands(cls, data):
|
||||||
|
|
||||||
|
@ -177,42 +183,46 @@ class WebSocket_Client(threading.Thread):
|
||||||
|
|
||||||
player = xbmc.Player()
|
player = xbmc.Player()
|
||||||
# These commands need to be reported back
|
# These commands need to be reported back
|
||||||
if command == "Mute":
|
if command == 'Mute':
|
||||||
xbmc.executebuiltin('Mute')
|
xbmc.executebuiltin('Mute')
|
||||||
elif command == "Unmute":
|
|
||||||
|
elif command == 'Unmute':
|
||||||
xbmc.executebuiltin('Mute')
|
xbmc.executebuiltin('Mute')
|
||||||
elif command == "SetVolume":
|
|
||||||
|
elif command == 'SetVolume':
|
||||||
volume = arguments['Volume']
|
volume = arguments['Volume']
|
||||||
xbmc.executebuiltin('SetVolume(%s[,showvolumebar])' % volume)
|
xbmc.executebuiltin('SetVolume(%s[,showvolumebar])' % volume)
|
||||||
elif command == "SetAudioStreamIndex":
|
|
||||||
|
elif command == 'SetAudioStreamIndex':
|
||||||
index = int(arguments['Index'])
|
index = int(arguments['Index'])
|
||||||
player.setAudioStream(index - 1)
|
player.setAudioStream(index - 1)
|
||||||
elif command == "SetSubtitleStreamIndex":
|
|
||||||
embyindex = int(arguments['Index'])
|
|
||||||
currentFile = player.getPlayingFile()
|
|
||||||
|
|
||||||
mapping = window('emby_%s.indexMapping' % currentFile)
|
elif command == 'SetSubtitleStreamIndex':
|
||||||
|
emby_index = int(arguments['Index'])
|
||||||
|
current_file = player.getPlayingFile()
|
||||||
|
|
||||||
|
mapping = window('emby_%s.indexMapping' % current_file)
|
||||||
if mapping:
|
if mapping:
|
||||||
externalIndex = json.loads(mapping)
|
external_index = json.loads(mapping)
|
||||||
# If there's external subtitles added via playbackutils
|
# If there's external subtitles added via playbackutils
|
||||||
for index in externalIndex:
|
for index in external_index:
|
||||||
if externalIndex[index] == embyindex:
|
if external_index[index] == emby_index:
|
||||||
player.setSubtitleStream(int(index))
|
player.setSubtitleStream(int(index))
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
# User selected internal subtitles
|
# User selected internal subtitles
|
||||||
external = len(externalIndex)
|
external = len(external_index)
|
||||||
audioTracks = len(player.getAvailableAudioStreams())
|
audio_tracks = len(player.getAvailableAudioStreams())
|
||||||
player.setSubtitleStream(external + embyindex - audioTracks - 1)
|
player.setSubtitleStream(external + emby_index - audio_tracks - 1)
|
||||||
else:
|
else:
|
||||||
# Emby merges audio and subtitle index together
|
# Emby merges audio and subtitle index together
|
||||||
audioTracks = len(player.getAvailableAudioStreams())
|
audio_tracks = len(player.getAvailableAudioStreams())
|
||||||
player.setSubtitleStream(index - audioTracks - 1)
|
player.setSubtitleStream(index - audio_tracks - 1)
|
||||||
|
|
||||||
# Let service know
|
# Let service know
|
||||||
window('emby_command', value="true")
|
window('emby_command', value="true")
|
||||||
|
|
||||||
elif command == "DisplayMessage":
|
elif command == 'DisplayMessage':
|
||||||
|
|
||||||
header = arguments['Header']
|
header = arguments['Header']
|
||||||
text = arguments['Text']
|
text = arguments['Text']
|
||||||
|
@ -222,26 +232,28 @@ class WebSocket_Client(threading.Thread):
|
||||||
icon="{emby}",
|
icon="{emby}",
|
||||||
time=4000)
|
time=4000)
|
||||||
|
|
||||||
elif command == "SendString":
|
elif command == 'SendString':
|
||||||
|
|
||||||
params = {
|
params = {
|
||||||
|
|
||||||
'text': arguments['String'],
|
'text': arguments['String'],
|
||||||
'done': False
|
'done': False
|
||||||
}
|
}
|
||||||
result = JSONRPC("Input.SendText").execute(params)
|
JSONRPC('Input.SendText').execute(params)
|
||||||
|
|
||||||
elif command in ("MoveUp", "MoveDown", "MoveRight", "MoveLeft"):
|
elif command in ('MoveUp', 'MoveDown', 'MoveRight', 'MoveLeft'):
|
||||||
# Commands that should wake up display
|
# Commands that should wake up display
|
||||||
actions = {
|
actions = {
|
||||||
|
|
||||||
'MoveUp': "Input.Up",
|
'MoveUp': "Input.Up",
|
||||||
'MoveDown': "Input.Down",
|
'MoveDown': "Input.Down",
|
||||||
'MoveRight': "Input.Right",
|
'MoveRight': "Input.Right",
|
||||||
'MoveLeft': "Input.Left"
|
'MoveLeft': "Input.Left"
|
||||||
}
|
}
|
||||||
result = JSONRPC(actions[command]).execute()
|
JSONRPC(actions[command]).execute()
|
||||||
|
|
||||||
elif command == "GoHome":
|
elif command == 'GoHome':
|
||||||
result = JSONRPC("GUI.ActivateWindow").execute({"window":"home"})
|
JSONRPC('GUI.ActivateWindow').execute({'window': "home"})
|
||||||
|
|
||||||
else:
|
else:
|
||||||
builtin = {
|
builtin = {
|
||||||
|
@ -262,16 +274,15 @@ class WebSocket_Client(threading.Thread):
|
||||||
'VolumeUp': 'Action(VolumeUp)',
|
'VolumeUp': 'Action(VolumeUp)',
|
||||||
'VolumeDown': 'Action(VolumeDown)',
|
'VolumeDown': 'Action(VolumeDown)',
|
||||||
}
|
}
|
||||||
action = builtin.get(command)
|
if command in builtin:
|
||||||
if action:
|
xbmc.executebuiltin(builtin[command])
|
||||||
xbmc.executebuiltin(action)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _server_restarting(cls):
|
def _server_restarting(cls):
|
||||||
|
|
||||||
if settings('supressRestartMsg') == "true":
|
if settings('supressRestartMsg') == "true":
|
||||||
dialog(type_="notification",
|
dialog(type_="notification",
|
||||||
heading=lang(29999),
|
heading="{emby}",
|
||||||
message=lang(33006),
|
message=lang(33006),
|
||||||
icon="{emby}")
|
icon="{emby}")
|
||||||
|
|
||||||
|
@ -282,6 +293,7 @@ class WebSocket_Client(threading.Thread):
|
||||||
self.doutils.postCapabilities(self.device_id)
|
self.doutils.postCapabilities(self.device_id)
|
||||||
|
|
||||||
def on_error(self, ws, error):
|
def on_error(self, ws, error):
|
||||||
|
|
||||||
if "10061" in str(error):
|
if "10061" in str(error):
|
||||||
# Server is offline
|
# Server is offline
|
||||||
pass
|
pass
|
||||||
|
@ -291,7 +303,6 @@ class WebSocket_Client(threading.Thread):
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
# websocket.enableTrace(True)
|
# websocket.enableTrace(True)
|
||||||
|
|
||||||
user_id = window('emby_currUser')
|
user_id = window('emby_currUser')
|
||||||
server = window('emby_server%s' % user_id)
|
server = window('emby_server%s' % user_id)
|
||||||
token = window('emby_accessToken%s' % user_id)
|
token = window('emby_accessToken%s' % user_id)
|
||||||
|
@ -305,9 +316,9 @@ class WebSocket_Client(threading.Thread):
|
||||||
log.info("websocket url: %s", websocket_url)
|
log.info("websocket url: %s", websocket_url)
|
||||||
|
|
||||||
self._client = websocket.WebSocketApp(websocket_url,
|
self._client = websocket.WebSocketApp(websocket_url,
|
||||||
on_message=self.on_message,
|
on_message=self.on_message,
|
||||||
on_error=self.on_error,
|
on_error=self.on_error,
|
||||||
on_close=self.on_close)
|
on_close=self.on_close)
|
||||||
self._client.on_open = self.on_open
|
self._client.on_open = self.on_open
|
||||||
log.warn("----===## Starting WebSocketClient ##===----")
|
log.warn("----===## Starting WebSocketClient ##===----")
|
||||||
|
|
||||||
|
|
31
service.py
31
service.py
|
@ -25,6 +25,7 @@ import clientinfo
|
||||||
import initialsetup
|
import initialsetup
|
||||||
import kodimonitor
|
import kodimonitor
|
||||||
import librarysync
|
import librarysync
|
||||||
|
import loghandler
|
||||||
import player
|
import player
|
||||||
import videonodes
|
import videonodes
|
||||||
import websocket_client as wsc
|
import websocket_client as wsc
|
||||||
|
@ -32,8 +33,6 @@ from utils import window, settings, dialog, language as lang
|
||||||
|
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
import loghandler
|
|
||||||
|
|
||||||
loghandler.config()
|
loghandler.config()
|
||||||
log = logging.getLogger("EMBY.service")
|
log = logging.getLogger("EMBY.service")
|
||||||
|
|
||||||
|
@ -101,7 +100,7 @@ class Service(object):
|
||||||
|
|
||||||
# Initialize important threads
|
# Initialize important threads
|
||||||
user = userclient.UserClient()
|
user = userclient.UserClient()
|
||||||
ws = wsc.WebSocket_Client()
|
ws = wsc.WebSocketClient()
|
||||||
library = librarysync.LibrarySync()
|
library = librarysync.LibrarySync()
|
||||||
kplayer = player.Player()
|
kplayer = player.Player()
|
||||||
# Sync and progress report
|
# Sync and progress report
|
||||||
|
@ -168,10 +167,10 @@ class Service(object):
|
||||||
else:
|
else:
|
||||||
add = ""
|
add = ""
|
||||||
dialog(type_="notification",
|
dialog(type_="notification",
|
||||||
heading=lang(29999),
|
heading="{emby}",
|
||||||
message=("%s %s%s!"
|
message=("%s %s%s!"
|
||||||
% (lang(33000), user.get_username().decode('utf-8'),
|
% (lang(33000), user.get_username().decode('utf-8'),
|
||||||
add.decode('utf-8'))),
|
add.decode('utf-8'))),
|
||||||
icon="{emby}",
|
icon="{emby}",
|
||||||
time=2000,
|
time=2000,
|
||||||
sound=False)
|
sound=False)
|
||||||
|
@ -236,7 +235,7 @@ class Service(object):
|
||||||
# device going to sleep
|
# device going to sleep
|
||||||
if self.websocket_running:
|
if self.websocket_running:
|
||||||
ws.stop_client()
|
ws.stop_client()
|
||||||
ws = wsc.WebSocket_Client()
|
ws = wsc.WebSocketClient()
|
||||||
self.websocket_running = False
|
self.websocket_running = False
|
||||||
|
|
||||||
if self.library_running:
|
if self.library_running:
|
||||||
|
@ -254,7 +253,7 @@ class Service(object):
|
||||||
break
|
break
|
||||||
# Alert the user that server is online.
|
# Alert the user that server is online.
|
||||||
dialog(type_="notification",
|
dialog(type_="notification",
|
||||||
heading=lang(29999),
|
heading="{emby}",
|
||||||
message=lang(33003),
|
message=lang(33003),
|
||||||
icon="{emby}",
|
icon="{emby}",
|
||||||
time=2000,
|
time=2000,
|
||||||
|
@ -292,12 +291,14 @@ class Service(object):
|
||||||
|
|
||||||
log.warn("======== STOP %s ========", self.addon_name)
|
log.warn("======== STOP %s ========", self.addon_name)
|
||||||
|
|
||||||
# Delay option
|
|
||||||
DELAY = int(settings('startupDelay'))
|
|
||||||
log.warn("Delaying emby startup by: %s sec...", DELAY)
|
|
||||||
|
|
||||||
if DELAY and xbmc.Monitor().waitForAbort(DELAY):
|
if __name__ == "__main__":
|
||||||
# Start the service
|
# Delay option
|
||||||
log.warn("Abort requested while waiting. Emby for kodi not started.")
|
DELAY = int(settings('startupDelay'))
|
||||||
else:
|
log.warn("Delaying emby startup by: %s sec...", DELAY)
|
||||||
Service().service_entry_point()
|
|
||||||
|
if DELAY and xbmc.Monitor().waitForAbort(DELAY):
|
||||||
|
# Start the service
|
||||||
|
log.warn("Abort requested while waiting. Emby for kodi not started.")
|
||||||
|
else:
|
||||||
|
Service().service_entry_point()
|
||||||
|
|
Loading…
Reference in a new issue