Merge conflicts

This commit is contained in:
tomkat83 2016-02-19 20:03:06 +01:00
parent 50d142ad0b
commit e7f7269a5b
14 changed files with 166 additions and 183 deletions

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
################################################################################################# ###############################################################################
import json import json
import requests import requests
@ -14,12 +14,11 @@ import xbmcvfs
import utils import utils
import image_cache_thread import image_cache_thread
################################################################################################# ###############################################################################
@utils.logging @utils.logging
class Artwork(): class Artwork():
xbmc_host = 'localhost' xbmc_host = 'localhost'
xbmc_port = None xbmc_port = None
xbmc_username = None xbmc_username = None

View file

@ -1,23 +1,20 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
################################################################################################# ###############################################################################
import os
from uuid import uuid4 from uuid import uuid4
import xbmc import xbmc
import xbmcaddon import xbmcaddon
import xbmcvfs
import utils import utils
################################################################################################# ###############################################################################
@utils.logging @utils.logging
class ClientInfo(): class ClientInfo():
def __init__(self): def __init__(self):
self.addon = xbmcaddon.Addon() self.addon = xbmcaddon.Addon()

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
################################################################################################## ###############################################################################
# import json # import json
import requests import requests
@ -18,19 +18,19 @@ try:
except ImportError: except ImportError:
import xml.etree.ElementTree as etree import xml.etree.ElementTree as etree
################################################################################################## ###############################################################################
# Disable requests logging # Disable requests logging
from requests.packages.urllib3.exceptions import InsecureRequestWarning from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning) requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
#logging.getLogger('requests').setLevel(logging.WARNING) # logging.getLogger('requests').setLevel(logging.WARNING)
################################################################################################## ###############################################################################
@utils.logging @utils.logging
class DownloadUtils(): class DownloadUtils():
# Borg - multiple instances, shared state # Borg - multiple instances, shared state
_shared_state = {} _shared_state = {}
clientInfo = clientinfo.ClientInfo() clientInfo = clientinfo.ClientInfo()

View file

@ -46,7 +46,6 @@ class Embydb_Functions():
rows = embycursor.fetchall() rows = embycursor.fetchall()
for row in rows: for row in rows:
views.append(row[0]) views.append(row[0])
return views return views
def getAllViewInfo(self): def getAllViewInfo(self):
@ -65,7 +64,6 @@ class Embydb_Functions():
views.append({'id': row[0], views.append({'id': row[0],
'name': row[1], 'name': row[1],
'itemtype': row[2]}) 'itemtype': row[2]})
return views return views
def getView_byId(self, viewid): def getView_byId(self, viewid):
@ -80,7 +78,6 @@ class Embydb_Functions():
)) ))
embycursor.execute(query, (viewid,)) embycursor.execute(query, (viewid,))
view = embycursor.fetchone() view = embycursor.fetchone()
return view return view
def getView_byType(self, mediatype): def getView_byType(self, mediatype):
@ -119,7 +116,6 @@ class Embydb_Functions():
embycursor.execute(query, (tagname,)) embycursor.execute(query, (tagname,))
try: try:
view = embycursor.fetchone()[0] view = embycursor.fetchone()[0]
except TypeError: except TypeError:
view = None view = None
@ -254,7 +250,6 @@ class Embydb_Functions():
embycursor.execute(query, (embyid,)) embycursor.execute(query, (embyid,))
try: try:
itemtype = embycursor.fetchone()[0] itemtype = embycursor.fetchone()[0]
except TypeError: except TypeError:
itemtype = None itemtype = None
@ -265,7 +260,6 @@ class Embydb_Functions():
sorted_items = {} sorted_items = {}
for itemid in itemids: for itemid in itemids:
mediatype = self.getMediaType_byId(itemid) mediatype = self.getMediaType_byId(itemid)
if mediatype: if mediatype:
sorted_items.setdefault(mediatype, []).append(itemid) sorted_items.setdefault(mediatype, []).append(itemid)
@ -322,4 +316,3 @@ class Embydb_Functions():
query = "DELETE FROM emby WHERE emby_id = ?" query = "DELETE FROM emby WHERE emby_id = ?"
self.embycursor.execute(query, (embyid,)) self.embycursor.execute(query, (embyid,))

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
################################################################################################# ###############################################################################
import json import json
import os import os
@ -27,7 +27,7 @@ import playlist
import PlexFunctions import PlexFunctions
################################################################################################# ###############################################################################
# For logging only # For logging only
addonName = clientinfo.ClientInfo().getAddonName() addonName = clientinfo.ClientInfo().getAddonName()

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
################################################################################################# ###############################################################################
import xbmc import xbmc
import xbmcgui import xbmcgui
@ -13,7 +13,7 @@ import userclient
import PlexAPI import PlexAPI
################################################################################################# ###############################################################################
@utils.logging @utils.logging
@ -36,12 +36,13 @@ class InitialSetup():
Check server, user, direct paths, music, direct stream if not direct Check server, user, direct paths, music, direct stream if not direct
path. path.
""" """
##### SERVER INFO ##### # SERVER INFO #####
self.logMsg("Initial setup called.", 0) self.logMsg("Initial setup called.", 0)
server = self.userClient.getServer() server = self.userClient.getServer()
clientId = self.clientInfo.getDeviceId() clientId = self.clientInfo.getDeviceId()
serverid = self.userClient.getServerId() serverid = utils.settings('plex_machineIdentifier')
myplexlogin, plexhome, plexLogin, plexToken = self.plx.GetPlexLoginFromSettings() myplexlogin, plexhome, plexLogin, plexToken = \
self.plx.GetPlexLoginFromSettings()
dialog = xbmcgui.Dialog() dialog = xbmcgui.Dialog()
# Optionally sign into plex.tv. Will not be called on very first run # Optionally sign into plex.tv. Will not be called on very first run
@ -167,7 +168,7 @@ class InitialSetup():
% (activeServer, server['ip'], server['port'], % (activeServer, server['ip'], server['port'],
server['scheme']), 0) server['scheme']), 0)
##### ADDITIONAL PROMPTS ##### # ADDITIONAL PROMPTS #####
directPaths = dialog.yesno( directPaths = dialog.yesno(
heading="%s: Playback Mode" % self.addonName, heading="%s: Playback Mode" % self.addonName,
line1=( line1=(

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
################################################################################################## ###############################################################################
import urllib import urllib
from ntpath import dirname from ntpath import dirname
@ -17,11 +17,11 @@ import utils
import embydb_functions as embydb import embydb_functions as embydb
import kodidb_functions as kodidb import kodidb_functions as kodidb
import read_embyserver as embyserver import read_embyserver as embyserver
import musicutils as musicutils
import PlexAPI import PlexAPI
from PlexFunctions import GetPlexMetadata from PlexFunctions import GetPlexMetadata
################################################################################################## ###############################################################################
@utils.logging @utils.logging
@ -922,7 +922,6 @@ class TVShows(Items):
# If the item doesn't exist, we'll add it to the database # If the item doesn't exist, we'll add it to the database
update_item = True update_item = True
force_episodes = False force_episodes = False
itemid = item['Id']
emby_dbitem = emby_db.getItem_byId(itemid) emby_dbitem = emby_db.getItem_byId(itemid)
try: try:
showid = emby_dbitem[0] showid = emby_dbitem[0]
@ -945,10 +944,9 @@ class TVShows(Items):
# Force re-add episodes after the show is re-created. # Force re-add episodes after the show is re-created.
force_episodes = True force_episodes = True
if viewtag is None or viewid is None: if viewtag is None or viewid is None:
# Get view tag from emby # Get view tag from emby
viewtag, viewid, mediatype = emby.getView_embyId(itemid) viewtag, viewid, mediatype = embyserver.getView_embyId(itemid)
self.logMsg("View tag found: %s" % viewtag, 2) self.logMsg("View tag found: %s" % viewtag, 2)
# fileId information # fileId information
@ -1084,11 +1082,9 @@ class TVShows(Items):
if force_episodes: if force_episodes:
# We needed to recreate the show entry. Re-add episodes now. # We needed to recreate the show entry. Re-add episodes now.
self.logMsg("Repairing episodes for showid: %s %s" % (showid, title), 1) self.logMsg("Repairing episodes for showid: %s %s" % (showid, title), 1)
all_episodes = emby.getEpisodesbyShow(itemid) all_episodes = embyserver.getEpisodesbyShow(itemid)
self.added_episode(all_episodes['Items'], None) self.added_episode(all_episodes['Items'], None)
def add_updateSeason(self, item, showid=None):
def add_updateSeason(self, item, viewid=None, viewtag=None): def add_updateSeason(self, item, viewid=None, viewtag=None):
API = PlexAPI.API(item) API = PlexAPI.API(item)
showid = viewid showid = viewid

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
################################################################################################# ###############################################################################
import json import json
@ -14,13 +14,12 @@ import utils
from urllib import urlencode from urllib import urlencode
################################################################################################# ###############################################################################
@utils.logging @utils.logging
class KodiMonitor(xbmc.Monitor): class KodiMonitor(xbmc.Monitor):
def __init__(self): def __init__(self):
self.doUtils = downloadutils.DownloadUtils() self.doUtils = downloadutils.DownloadUtils()
@ -31,7 +30,7 @@ class KodiMonitor(xbmc.Monitor):
self.logMsg("Kodi library scan %s running." % library, 2) self.logMsg("Kodi library scan %s running." % library, 2)
if library == "video": if library == "video":
utils.window('emby_kodiScan', value="true") utils.window('emby_kodiScan', value="true")
def onScanFinished(self, library): def onScanFinished(self, library):
self.logMsg("Kodi library scan %s finished." % library, 2) self.logMsg("Kodi library scan %s finished." % library, 2)
if library == "video": if library == "video":
@ -116,7 +115,6 @@ class KodiMonitor(xbmc.Monitor):
playback.setProperties(playurl, listItem) playback.setProperties(playurl, listItem)
finally: finally:
embycursor.close() embycursor.close()
elif method == "VideoLibrary.OnUpdate": elif method == "VideoLibrary.OnUpdate":
# Manually marking as watched/unwatched # Manually marking as watched/unwatched

View file

@ -391,7 +391,8 @@ class LibrarySync(Thread):
return False return False
else: else:
elapsedTime = datetime.now() - startTime elapsedTime = datetime.now() - startTime
% (itemtype, str(elapsedTime).split('.')[0]), 1) self.logMsg("SyncDatabase (finished %s in: %s)"
% (itemtype, str(elapsedTime).split('.')[0]), 1)
# Let kodi update the views in any case # Let kodi update the views in any case
xbmc.executebuiltin('UpdateLibrary(video)') xbmc.executebuiltin('UpdateLibrary(video)')
@ -508,11 +509,11 @@ class LibrarySync(Thread):
""" """
Compare the views to Plex Compare the views to Plex
""" """
doUtils = self.doUtils
vnodes = self.vnodes vnodes = self.vnodes
# Get views # Get views
result = doUtils.downloadUrl("{server}/library/sections") result = downloadutils.DownloadUtils().downloadUrl(
"{server}/library/sections")
if not result: if not result:
self.logMsg("Error download PMS views, abort maintainViews", -1) self.logMsg("Error download PMS views, abort maintainViews", -1)
return False return False
@ -733,7 +734,7 @@ class LibrarySync(Thread):
except ValueError: except ValueError:
self.allKodiElementsId = {} self.allKodiElementsId = {}
##### PROCESS MOVIES ##### # PROCESS MOVIES #####
self.updatelist = [] self.updatelist = []
for view in views: for view in views:
if self.threadStopped(): if self.threadStopped():
@ -759,7 +760,7 @@ class LibrarySync(Thread):
return False return False
self.PlexUpdateWatched(view['id'], itemType) self.PlexUpdateWatched(view['id'], itemType)
##### PROCESS DELETES ##### # PROCESS DELETES #####
if self.compare: if self.compare:
# Manual sync, process deletes # Manual sync, process deletes
with itemtypes.Movies() as Movie: with itemtypes.Movies() as Movie:
@ -793,16 +794,19 @@ class LibrarySync(Thread):
method.updateUserdata(xml) method.updateUserdata(xml)
def musicvideos(self, embycursor, kodicursor, pdialog): def musicvideos(self, embycursor, kodicursor, pdialog):
log = self.logMsg
# Get musicvideos from emby # Get musicvideos from emby
emby = self.emby emby = self.emby
emby_db = embydb.Embydb_Functions(embycursor) emby_db = embydb.Embydb_Functions(embycursor)
mvideos = itemtypes.MusicVideos(embycursor, kodicursor) mvideos = itemtypes.MusicVideos(embycursor, kodicursor)
views = emby_db.getView_byType('musicvideos') views = emby_db.getView_byType('musicvideos')
log("Media folders: %s" % views, 1)
for view in views: for view in views:
if self.threadStopped(): if self.shouldStop():
return False return False
# Get items per view # Get items per view
@ -812,6 +816,7 @@ class LibrarySync(Thread):
if pdialog: if pdialog:
pdialog.update( pdialog.update(
heading="Emby for Kodi", heading="Emby for Kodi",
message="%s %s..." % (utils.language(33019), viewName))
# Initial or repair sync # Initial or repair sync
all_embymvideos = emby.getMusicVideos(viewId, dialog=pdialog) all_embymvideos = emby.getMusicVideos(viewId, dialog=pdialog)
@ -824,7 +829,7 @@ class LibrarySync(Thread):
count = 0 count = 0
for embymvideo in embymvideos: for embymvideo in embymvideos:
# Process individual musicvideo # Process individual musicvideo
if self.threadStopped(): if self.shouldStop():
return False return False
title = embymvideo['Name'] title = embymvideo['Name']
@ -834,6 +839,7 @@ class LibrarySync(Thread):
count += 1 count += 1
mvideos.add_update(embymvideo, viewName, viewId) mvideos.add_update(embymvideo, viewName, viewId)
else: else:
log("MusicVideos finished.", 2)
return True return True
@ -857,7 +863,7 @@ class LibrarySync(Thread):
except ValueError: except ValueError:
pass pass
##### PROCESS TV Shows ##### # PROCESS TV Shows #####
self.updatelist = [] self.updatelist = []
for view in views: for view in views:
if self.threadStopped(): if self.threadStopped():
@ -881,7 +887,7 @@ class LibrarySync(Thread):
# COPY for later use # COPY for later use
allPlexTvShowsId = self.allPlexElementsId.copy() allPlexTvShowsId = self.allPlexElementsId.copy()
##### PROCESS TV Seasons ##### # PROCESS TV Seasons #####
# Cycle through tv shows # Cycle through tv shows
for tvShowId in allPlexTvShowsId: for tvShowId in allPlexTvShowsId:
if self.threadStopped(): if self.threadStopped():
@ -901,7 +907,7 @@ class LibrarySync(Thread):
self.logMsg("Analyzed all seasons of TV show with Plex Id %s" self.logMsg("Analyzed all seasons of TV show with Plex Id %s"
% tvShowId, 1) % tvShowId, 1)
##### PROCESS TV Episodes ##### # PROCESS TV Episodes #####
# Cycle through tv shows # Cycle through tv shows
for view in views: for view in views:
if self.threadStopped(): if self.threadStopped():
@ -1016,7 +1022,6 @@ class LibrarySync(Thread):
viewName, viewName,
viewId) viewId)
def compareDBVersion(self, current, minimum): def compareDBVersion(self, current, minimum):
# It returns True is database is up to date. False otherwise. # It returns True is database is up to date. False otherwise.
self.logMsg("current: %s minimum: %s" % (current, minimum), 1) self.logMsg("current: %s minimum: %s" % (current, minimum), 1)
@ -1046,6 +1051,9 @@ class LibrarySync(Thread):
raise raise
def run_internal(self): def run_internal(self):
window = utils.window
settings = utils.settings
log = self.logMsg
startupComplete = False startupComplete = False
self.views = [] self.views = []
@ -1059,25 +1067,27 @@ class LibrarySync(Thread):
# Set in service.py # Set in service.py
if self.threadStopped(): if self.threadStopped():
# Abort was requested while waiting. We should exit # Abort was requested while waiting. We should exit
self.logMsg("###===--- LibrarySync Stopped ---===###", 0) log("###===--- LibrarySync Stopped ---===###", 0)
return return
xbmc.sleep(1000) xbmc.sleep(1000)
if (utils.window('emby_dbCheck') != "true" and if (window('emby_dbCheck') != "true" and
self.installSyncDone): self.installSyncDone):
# Verify the validity of the database # Verify the validity of the database
currentVersion = settings('dbCreatedWithVersion')
minVersion = window('emby_minDBVersion')
uptoDate = self.compareDBVersion(currentVersion, minVersion) uptoDate = self.compareDBVersion(currentVersion, minVersion)
if not uptoDate: if not uptoDate:
% (currentVersion, minVersion), 0) log("Db version out of date: %s minimum version required: "
"%s" % (currentVersion, minVersion), 0)
resp = xbmcgui.Dialog().yesno( resp = xbmcgui.Dialog().yesno(
heading="Db Version", heading="Db Version",
line1=("Detected the database needs to be recreated " line1=("Detected the database needs to be recreated "
"for this version of " + self.addonName + "for this version of " + self.addonName +
"Proceed?")) "Proceed?"))
if not resp: if not resp:
self.logMsg("Db version out of date! USER IGNORED!", 0) log("Db version out of date! USER IGNORED!", 0)
xbmcgui.Dialog().ok( xbmcgui.Dialog().ok(
heading=self.addonName, heading=self.addonName,
line1=(self.addonName + " may not work correctly " line1=(self.addonName + " may not work correctly "
@ -1085,17 +1095,14 @@ class LibrarySync(Thread):
else: else:
utils.reset() utils.reset()
if not startupComplete: if not startupComplete:
# Also runs when installed first # Also runs when installed first
# Verify the video database can be found # Verify the video database can be found
videoDb = utils.getKodiVideoDBPath() videoDb = utils.getKodiVideoDBPath()
if not xbmcvfs.exists(videoDb): if not xbmcvfs.exists(videoDb):
# Database does not exists # Database does not exists
self.logMsg( log("The current Kodi version is incompatible "
"The current Kodi version is incompatible "
"to know which Kodi versions are supported.", 0) "to know which Kodi versions are supported.", 0)
xbmcgui.Dialog().ok( xbmcgui.Dialog().ok(
heading=self.addonName, heading=self.addonName,
line1=("Cancelling the database syncing process. " line1=("Cancelling the database syncing process. "
@ -1105,45 +1112,44 @@ class LibrarySync(Thread):
break break
# Run start up sync # Run start up sync
utils.window('emby_dbScan', value="true") window('emby_dbScan', value="true")
self.logMsg("Db version: %s" % utils.settings('dbCreatedWithVersion'), 0) log("Db version: %s" % settings('dbCreatedWithVersion'), 0)
self.logMsg("SyncDatabase (started)", 1) log("SyncDatabase (started)", 1)
startTime = datetime.now() startTime = datetime.now()
librarySync = self.fullSync(manualrun=True) librarySync = self.fullSync(manualrun=True)
elapsedTime = datetime.now() - startTime elapsedTime = datetime.now() - startTime
log("SyncDatabase (finished in: %s) %s"
% (str(elapsedTime).split('.')[0], librarySync), 1) % (str(elapsedTime).split('.')[0], librarySync), 1)
# Only try the initial sync once per kodi session regardless # Only try the initial sync once per kodi session regardless
# This will prevent an infinite loop in case something goes wrong. # This will prevent an infinite loop in case something goes wrong.
startupComplete = True startupComplete = True
utils.settings( settings('SyncInstallRunDone', value="true")
'SyncInstallRunDone', value="true") settings("dbCreatedWithVersion", self.clientInfo.getVersion())
utils.settings(
"dbCreatedWithVersion", self.clientInfo.getVersion())
self.installSyncDone = True self.installSyncDone = True
utils.window('emby_dbScan', clear=True) window('emby_dbScan', clear=True)
# Currently no db scan, so we can start a new scan # Currently no db scan, so we can start a new scan
elif utils.window('emby_dbScan') != "true": elif window('emby_dbScan') != "true":
# Full scan was requested from somewhere else, e.g. userclient # Full scan was requested from somewhere else, e.g. userclient
if utils.window('plex_runLibScan') == "true": if window('plex_runLibScan') == "true":
self.logMsg('Full library scan requested, starting', 0) log('Full library scan requested, starting', 0)
utils.window('emby_dbScan', value="true") window('emby_dbScan', value="true")
utils.window('plex_runLibScan', clear=True) window('plex_runLibScan', clear=True)
self.fullSync(manualrun=True) self.fullSync(manualrun=True)
utils.window('emby_dbScan', clear=True) window('emby_dbScan', clear=True)
count = 0 count = 0
else: else:
# Run full lib scan approx every 30min # Run full lib scan approx every 30min
if count >= 1800: if count >= 1800:
count = 0 count = 0
utils.window('emby_dbScan', value="true") window('emby_dbScan', value="true")
self.logMsg('Running automatic full lib scan', 0) log('Running automatic full lib scan', 0)
self.fullSync(manualrun=True) self.fullSync(manualrun=True)
utils.window('emby_dbScan', clear=True) window('emby_dbScan', clear=True)
# Update views / PMS libraries approx. every 5min # Update views / PMS libraries approx. every 5min
elif count % 300 == 0: elif count % 300 == 0:
self.logMsg('Running maintainViews() scan', 0) log('Running maintainViews() scan', 0)
utils.window('emby_dbScan', value="true") window('emby_dbScan', value="true")
self.maintainViews() self.maintainViews()
self.startSync() self.startSync()
# Run fast sync otherwise (ever 2 seconds or so) # Run fast sync otherwise (ever 2 seconds or so)
@ -1153,4 +1159,4 @@ class LibrarySync(Thread):
xbmc.sleep(2000) xbmc.sleep(2000)
count += 1 count += 1
self.logMsg("###===--- LibrarySync Stopped ---===###", 0) log("###===--- LibrarySync Stopped ---===###", 0)

View file

@ -25,8 +25,7 @@ import PlexFunctions as PF
@utils.logging @utils.logging
class PlaybackUtils(): class PlaybackUtils():
def __init__(self, item): def __init__(self, item):
self.item = item self.item = item
@ -34,7 +33,6 @@ class PlaybackUtils():
self.clientInfo = clientinfo.ClientInfo() self.clientInfo = clientinfo.ClientInfo()
self.addonName = self.clientInfo.getAddonName() self.addonName = self.clientInfo.getAddonName()
self.doUtils = downloadutils.DownloadUtils().downloadUrl
self.userid = utils.window('emby_currUser') self.userid = utils.window('emby_currUser')
self.server = utils.window('emby_server%s' % self.userid) self.server = utils.window('emby_server%s' % self.userid)
@ -64,12 +62,12 @@ class PlaybackUtils():
if dbid is None or dbid == '999999999': if dbid is None or dbid == '999999999':
# Item is not in Kodi database # Item is not in Kodi database
playmethod = utils.window('emby_%s.playmethod' % playurl) playmethod = window('emby_%s.playmethod' % playurl)
if playmethod == "Transcode": if playmethod == "Transcode":
utils.window('emby_%s.playmethod' % playurl, clear=True) window('emby_%s.playmethod' % playurl, clear=True)
playurl = playutils.audioSubsPref( playurl = playutils.audioSubsPref(
listitem, playurl) listitem, playurl)
utils.window('emby_%s.playmethod' % playurl, "Transcode") window('emby_%s.playmethod' % playurl, "Transcode")
listitem.setPath(playurl) listitem.setPath(playurl)
self.setArtwork(listitem) self.setArtwork(listitem)
self.setListItem(listitem) self.setListItem(listitem)
@ -88,9 +86,9 @@ class PlaybackUtils():
introsPlaylist = False introsPlaylist = False
dummyPlaylist = False dummyPlaylist = False
self.logMsg("Playlist start position: %s" % startPos, 1) log("Playlist start position: %s" % startPos, 1)
self.logMsg("Playlist plugin position: %s" % self.currentPosition, 1) log("Playlist plugin position: %s" % self.currentPosition, 1)
self.logMsg("Playlist size: %s" % sizePlaylist, 1) log("Playlist size: %s" % sizePlaylist, 1)
############### RESUME POINT ################ ############### RESUME POINT ################
@ -103,9 +101,8 @@ class PlaybackUtils():
window('emby_playbackProps', value="true") window('emby_playbackProps', value="true")
log("Setting up properties in playlist.", 1) log("Setting up properties in playlist.", 1)
if (not homeScreen and not seektime and if (not homeScreen and not seektime and
window('emby_customPlaylist') != "true"): window('emby_customPlaylist') != "true"):
log("Adding dummy file to playlist.", 2) log("Adding dummy file to playlist.", 2)
dummyPlaylist = True dummyPlaylist = True
playlist.add(playurl, listitem, index=startPos) playlist.add(playurl, listitem, index=startPos)
@ -267,16 +264,13 @@ class PlaybackUtils():
window('%s.itemid' % embyitem, value=itemid) window('%s.itemid' % embyitem, value=itemid)
# We need to keep track of playQueueItemIDs for Plex Companion # We need to keep track of playQueueItemIDs for Plex Companion
window( window('plex_%s.playQueueItemID'
'plex_%s.playQueueItemID' % playurl, self.API.GetPlayQueueItemID())
% playurl, self.API.GetPlayQueueItemID()) window('plex_%s.guid' % playurl, self.API.getGuid())
window(
'plex_%s.guid'
% playurl, self.API.getGuid())
if itemtype == "episode": if itemtype == "episode":
window('%s.refreshid' % embyitem, window('%s.refreshid' % embyitem,
value=self.API.getParentRatingKey()) value=self.API.getParentRatingKey())
else: else:
window('%s.refreshid' % embyitem, value=itemid) window('%s.refreshid' % embyitem, value=itemid)

View file

@ -73,40 +73,43 @@ class Player(xbmc.Player):
break break
else: count += 1 else: count += 1
if currentFile: if currentFile:
self.currentFile = currentFile self.currentFile = currentFile
# Save currentFile for cleanup later # Save currentFile for cleanup later
utils.window('plex_lastPlayedFiled', value=currentFile) window('plex_lastPlayedFiled', value=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) itemId = window("emby_%s.itemid" % currentFile)
tryCount = 0 tryCount = 0
while not itemId: while not itemId:
xbmc.sleep(200) xbmc.sleep(200)
itemId = window("emby_%s.itemid" % currentFile) itemId = window("emby_%s.itemid" % currentFile)
if tryCount == 20: # try 20 times or about 10 seconds if tryCount == 20: # try 20 times or about 10 seconds
log("Could not find itemId, cancelling playback report...", 1) log("Could not find itemId, cancelling playback report...", 1)
break break
else: tryCount += 1 else: tryCount += 1
else: else:
window('Plex_currently_playing_itemid', value=itemId) window('Plex_currently_playing_itemid', value=itemId)
log("ONPLAYBACK_STARTED: %s itemid: %s" % (currentFile, itemId), 0) log("ONPLAYBACK_STARTED: %s itemid: %s" % (currentFile, itemId), 0)
# Only proceed if an itemId was found. # Only proceed if an itemId was found.
embyitem = "emby_%s" % currentFile 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')
# Suspend library sync thread while movie is playing
log("Playing itemtype is: %s" % itemType, 1) log("Playing itemtype is: %s" % itemType, 1)
# Suspend library sync thread while movie is playing
if itemType in ['movie', 'audio']: if itemType in ['movie', 'audio']:
log("Suspending library sync while playing", 1) log("Suspending library sync while playing", 1)
window('suspend_LibraryThread', value='true') window('suspend_LibraryThread', value='true')
if (window('emby_customPlaylist') == "true" and customseek = window('emby_customPlaylist.seektime')
customseek)): if (window('emby_customPlaylist') == "true" and customseek):
# Start at, when using custom playlist (play to Kodi from webclient) # Start at, when using custom playlist (play to Kodi from webclient)
log("Seeking to: %s" % customseek, 1) log("Seeking to: %s" % customseek, 1)
xbmcplayer.seekTime(int(customseek)) xbmcplayer.seekTime(int(customseek))
@ -268,8 +271,9 @@ class Player(xbmc.Player):
if not self.doNotify: if not self.doNotify:
return return
log = self.logMsg
log("reportPlayback Called", 2) log("reportPlayback Called", 2)
xbmcplayer = self.xbmcplayer
# Get current file # Get current file
currentFile = self.currentFile currentFile = self.currentFile

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
################################################################################################# ###############################################################################
import json import json
from urllib import urlencode from urllib import urlencode
@ -15,7 +15,7 @@ import utils
import PlexFunctions import PlexFunctions
import PlexAPI import PlexAPI
################################################################################################# ###############################################################################
@utils.logging @utils.logging
@ -28,8 +28,8 @@ class Playlist():
self.emby = embyserver.Read_EmbyServer() self.emby = embyserver.Read_EmbyServer()
def playAll(self, itemids, startat): def playAll(self, itemids, startat):
log = self.logMsg log = self.logMsg
window = utils.window window = utils.window
embyconn = utils.kodiSQL('emby') embyconn = utils.kodiSQL('emby')
embycursor = embyconn.cursor() embycursor = embyconn.cursor()
@ -57,14 +57,14 @@ class Playlist():
mediatype = embydb_item[4] mediatype = embydb_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
self.logMsg("Item was not found in the database, manually adding item.", 1) log("Item was not found in the database, manually adding item.", 1)
item = PlexFunctions.GetPlexMetadata(itemid) item = PlexFunctions.GetPlexMetadata(itemid)
self.addtoPlaylist_xbmc(playlist, item) self.addtoPlaylist_xbmc(playlist, item)
else: else:
# Add to playlist # Add to playlist
self.addtoPlaylist(dbid, mediatype) self.addtoPlaylist(dbid, mediatype)
self.logMsg("Adding %s to playlist." % itemid, 1) log("Adding %s to playlist." % itemid, 1)
if not started: if not started:
started = True started = True
@ -83,7 +83,7 @@ class Playlist():
log("---*** ADD TO PLAYLIST ***---", 1) log("---*** ADD TO PLAYLIST ***---", 1)
log("Items: %s" % itemids, 1) log("Items: %s" % itemids, 1)
player = xbmc.Player() # player = xbmc.Player()
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
for itemid in itemids: for itemid in itemids:

View file

@ -1,10 +1,9 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
################################################################################################# ###############################################################################
from urllib import urlencode from urllib import urlencode
import xbmc
import xbmcgui import xbmcgui
import xbmcvfs import xbmcvfs
@ -12,15 +11,14 @@ import clientinfo
import utils import utils
import PlexAPI import PlexAPI
import PlexFunctions
#################################################################################################
###############################################################################
@utils.logging @utils.logging
class PlayUtils(): class PlayUtils():
def __init__(self, item): def __init__(self, item):
self.item = item self.item = item
@ -48,7 +46,7 @@ class PlayUtils():
playurl = self.API.getTranscodeVideoPath('DirectPlay') playurl = self.API.getTranscodeVideoPath('DirectPlay')
playurl = playurl.encode('utf-8') playurl = playurl.encode('utf-8')
# Set playmethod property # Set playmethod property
utils.window('emby_%s.playmethod' % playurl, "DirectPlay") window('emby_%s.playmethod' % playurl, "DirectPlay")
# Currently no direct streaming possible - needs investigation # Currently no direct streaming possible - needs investigation
# elif self.isDirectStream(): # elif self.isDirectStream():
@ -69,7 +67,7 @@ class PlayUtils():
# Set playmethod property # Set playmethod property
window('emby_%s.playmethod' % playurl, value="Transcode") window('emby_%s.playmethod' % playurl, value="Transcode")
self.logMsg("The playurl is: %s" % playurl, 1) log("The playurl is: %s" % playurl, 1)
return playurl return playurl
def httpPlay(self): def httpPlay(self):
@ -191,7 +189,8 @@ class PlayUtils():
# Verify the bitrate # Verify the bitrate
if not self.isNetworkSufficient(): if not self.isNetworkSufficient():
log("The network speed is insufficient to direct stream file.", 1) self.logMsg(
"The network speed is insufficient to direct stream file.", 1)
return False return False
return True return True
@ -303,7 +302,6 @@ class PlayUtils():
return res[chosen] return res[chosen]
def audioSubsPref(self, listitem, url, part=None): def audioSubsPref(self, listitem, url, part=None):
log = self.logMsg
lang = utils.language lang = utils.language
dialog = xbmcgui.Dialog() dialog = xbmcgui.Dialog()
# For transcoding only # For transcoding only

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
################################################################################################## ###############################################################################
import threading import threading
@ -14,7 +14,7 @@ import downloadutils
import PlexAPI import PlexAPI
################################################################################################## ###############################################################################
@utils.logging @utils.logging
@ -48,7 +48,7 @@ class UserClient(threading.Thread):
def getAdditionalUsers(self): def getAdditionalUsers(self):
additionalUsers = utils.settings('additionalUsers') additionalUsers = utils.settings('additionalUsers')
if additionalUsers: if additionalUsers:
self.AdditionalUser = additionalUsers.split(',') self.AdditionalUser = additionalUsers.split(',')
@ -68,7 +68,7 @@ class UserClient(threading.Thread):
logLevel = int(utils.settings('logLevel')) logLevel = int(utils.settings('logLevel'))
except ValueError: except ValueError:
logLevel = 0 logLevel = 0
return logLevel return logLevel
def getUserId(self): def getUserId(self):
@ -115,7 +115,7 @@ class UserClient(threading.Thread):
port = settings('port') port = settings('port')
server = host + ":" + port server = host + ":" + port
if not host: if not host:
self.logMsg("No server information saved.", 2) self.logMsg("No server information saved.", 2)
return False return False
@ -132,10 +132,6 @@ class UserClient(threading.Thread):
elif not prefix: elif not prefix:
return server return server
def getServerId(self):
serverId = utils.settings('plex_machineIdentifier')
return serverId
def getToken(self): def getToken(self):
log = self.logMsg log = self.logMsg
@ -146,7 +142,7 @@ class UserClient(threading.Thread):
userId = self.getUserId() userId = self.getUserId()
w_token = window('emby_accessToken%s' % userId) w_token = window('emby_accessToken%s' % userId)
s_token = settings('accessToken') s_token = settings('accessToken')
# Verify the window property # Verify the window property
if w_token: if w_token:
if not s_token: if not s_token:
@ -209,7 +205,7 @@ class UserClient(threading.Thread):
# Get public Users # Get public Users
url = "%s/emby/Users/Public?format=json" % server url = "%s/emby/Users/Public?format=json" % server
result = self.doUtils.downloadUrl(url, authenticate=False) result = self.doUtils.downloadUrl(url, authenticate=False)
if result != "": if result != "":
return result return result
else: else:
@ -217,19 +213,20 @@ class UserClient(threading.Thread):
return False return False
def hasAccess(self): def hasAccess(self):
return True # Plex: always return True for now
return True
# hasAccess is verified in service.py # hasAccess is verified in service.py
log = self.logMsg log = self.logMsg
window = utils.window window = utils.window
url = "{server}/emby/Users?format=json" url = "{server}/emby/Users?format=json"
result = self.doUtils.downloadUrl(url) result = self.doUtils.downloadUrl(url)
if result == False: if result == False:
# Access is restricted, set in downloadutils.py via exception # Access is restricted, set in downloadutils.py via exception
log("Access is restricted.", 1) log("Access is restricted.", 1)
self.HasAccess = False self.HasAccess = False
elif window('emby_online') != "true": elif window('emby_online') != "true":
# Server connection failed # Server connection failed
pass pass
@ -247,21 +244,21 @@ class UserClient(threading.Thread):
doUtils = self.doUtils doUtils = self.doUtils
username = self.getUsername() username = self.getUsername()
userId = self.getUserId() userId = self.getUserId()
# Only to be used if token exists # Only to be used if token exists
self.currUserId = userId self.currUserId = userId
self.currServer = self.getServer() self.currServer = self.getServer()
self.currToken = self.getToken() self.currToken = self.getToken()
self.machineIdentifier = self.getServerId() self.machineIdentifier = utils.settings('plex_machineIdentifier')
self.ssl = self.getSSLverify() self.ssl = self.getSSLverify()
self.sslcert = self.getSSL() self.sslcert = self.getSSL()
# Test the validity of current token # Test the validity of current token
if authenticated == False: if authenticated is False:
url = "%s/clients" % (self.currServer) url = "%s/clients" % (self.currServer)
utils.window('emby_currUser', value=userId) window('emby_currUser', value=userId)
utils.window('plex_username', value=username) window('plex_username', value=username)
utils.window('emby_accessToken%s' % userId, value=self.currToken) window('emby_accessToken%s' % userId, value=self.currToken)
result = doUtils.downloadUrl(url) result = doUtils.downloadUrl(url)
if result == 401: if result == 401:
@ -270,12 +267,12 @@ class UserClient(threading.Thread):
return False return False
# Set to windows property # Set to windows property
utils.window('emby_currUser', value=userId) window('emby_currUser', value=userId)
utils.window('plex_username', value=username) window('plex_username', value=username)
utils.window('emby_accessToken%s' % userId, value=self.currToken) window('emby_accessToken%s' % userId, value=self.currToken)
utils.window('emby_server%s' % userId, value=self.currServer) window('emby_server%s' % userId, value=self.currServer)
utils.window('emby_server_%s' % userId, value=self.getServer(prefix=False)) window('emby_server_%s' % userId, value=self.getServer(prefix=False))
utils.window('plex_machineIdentifier', value=self.machineIdentifier) window('plex_machineIdentifier', value=self.machineIdentifier)
# Set DownloadUtils values # Set DownloadUtils values
doUtils.setUsername(username) doUtils.setUsername(username)
@ -295,7 +292,7 @@ class UserClient(threading.Thread):
return True return True
def authenticate(self): def authenticate(self):
log = self.logMsg log = self.logMsg
lang = utils.language lang = utils.language
window = utils.window window = utils.window
@ -308,7 +305,7 @@ class UserClient(threading.Thread):
hasSettings = xbmcvfs.exists("%ssettings.xml" % addondir) hasSettings = xbmcvfs.exists("%ssettings.xml" % addondir)
username = self.getUsername() username = self.getUsername()
userId = utils.settings('userId%s' % username) userId = settings('userId%s' % username)
server = self.getServer() server = self.getServer()
# If there's no settings.xml # If there's no settings.xml
@ -318,33 +315,33 @@ class UserClient(threading.Thread):
return return
# If no user information # If no user information
elif not server: elif not server:
self.logMsg("Missing server information.", 0) log("Missing server information.", 0)
self.auth = False self.auth = False
return return
# If there's a token, load the user # If there's a token, load the user
elif self.getToken(): elif self.getToken():
result = self.loadCurrUser() result = self.loadCurrUser()
if result == False: if result is False:
pass pass
else: else:
self.logMsg("Current user: %s" % self.currUser, 1) log("Current user: %s" % self.currUser, 1)
self.logMsg("Current userId: %s" % self.currUserId, 1) log("Current userId: %s" % self.currUserId, 1)
self.logMsg("Current accessToken: xxxx", 1) log("Current accessToken: xxxx", 1)
utils.window('suspend_LibraryThread', value='false') window('suspend_LibraryThread', clear=True)
return return
##### AUTHENTICATE USER ##### # AUTHENTICATE USER #####
# Choose Plex user login # Choose Plex user login
myplexlogin, plexhome, plexLogin, dont_use_accessToken = \ myplexlogin, plexhome, plexLogin, dont_use_accessToken = \
plx.GetPlexLoginFromSettings() plx.GetPlexLoginFromSettings()
self.logMsg("myplexlogin: %s, plexhome: %s, plexLogin: %s" log("myplexlogin: %s, plexhome: %s, plexLogin: %s"
% (myplexlogin, plexhome, plexLogin), 2) % (myplexlogin, plexhome, plexLogin), 2)
if myplexlogin == "true" and plexhome == 'true': if myplexlogin == "true" and plexhome == 'true':
username, userId, accessToken = plx.ChoosePlexHomeUser() username, userId, accessToken = plx.ChoosePlexHomeUser()
else: else:
self.logMsg("Trying to connect to PMS without a token", 0) log("Trying to connect to PMS without a token", 0)
accessToken = '' accessToken = ''
# Check connection # Check connection
if plx.CheckConnection(server, accessToken) == 200: if plx.CheckConnection(server, accessToken) == 200:
@ -360,35 +357,35 @@ class UserClient(threading.Thread):
"Welcome", "Welcome",
"special://home/addons/plugin.video." "special://home/addons/plugin.video."
"plexkodiconnect/icon.png") "plexkodiconnect/icon.png")
utils.settings('accessToken', value=accessToken) settings('accessToken', value=accessToken)
utils.settings('userId%s' % username, value=userId) settings('userId%s' % username, value=userId)
self.logMsg("User authenticated with an access token", 1) log("User authenticated with an access token", 1)
self.loadCurrUser(authenticated=True) self.loadCurrUser(authenticated=True)
utils.window('emby_serverStatus', clear=True) window('emby_serverStatus', clear=True)
# Write plex_machineIdentifier to window # Write plex_machineIdentifier to window
plex_machineIdentifier = utils.settings('plex_machineIdentifier') plex_machineIdentifier = settings('plex_machineIdentifier')
utils.window('plex_machineIdentifier', plex_machineIdentifier) window('plex_machineIdentifier', plex_machineIdentifier)
self.retry = 0 self.retry = 0
# Make sure that lib sync thread is not paused # Make sure that lib sync thread is not paused
utils.window('suspend_LibraryThread', value='false') utils.window('suspend_LibraryThread', value='false')
else: else:
self.logMsg("Error: user authentication failed.", -1) self.logMsg("Error: user authentication failed.", -1)
utils.settings('accessToken', value="") settings('accessToken', value="")
utils.settings('userId%s' % username, value="") settings('userId%s' % username, value="")
log("Too many retries. "
"You can retry by resetting attempts in the addon settings.", 1)
window('emby_serverStatus', value="Stop")
dialog.ok(lang(33001), lang(33010))
# Give 3 attempts at entering password / selecting user # Give 3 attempts at entering password / selecting user
if self.retry == 3: if self.retry == 3:
log("Too many retries. You can retry by resetting attempts in "
"the addon settings.", 1)
window('emby_serverStatus', value="Stop")
dialog.ok(lang(33001), lang(33010))
self.retry += 1 self.retry += 1
self.auth = False self.auth = False
def resetClient(self): def resetClient(self):
self.logMsg("Reset UserClient authentication.", 1)
log = self.logMsg username = self.getUsername()
utils.settings('accessToken', value="") utils.settings('accessToken', value="")
utils.window('emby_accessToken%s' % username, clear=True) utils.window('emby_accessToken%s' % username, clear=True)
@ -399,9 +396,10 @@ class UserClient(threading.Thread):
self.currUser = None self.currUser = None
def run(self): def run(self):
log = self.logMsg
window = utils.window
log("----===## Starting UserClient ##===----", 0) log("----===## Starting UserClient ##===----", 0)
while not self.threadStopped(): while not self.threadStopped():
while self.threadSuspended(): while self.threadSuspended():
if self.threadStopped(): if self.threadStopped():
@ -428,14 +426,13 @@ class UserClient(threading.Thread):
# to authenticate the user # to authenticate the user
self.auth = False self.auth = False
self.authenticate() self.authenticate()
if not self.auth and (self.currUser is None): if not self.auth and (self.currUser is None):
# If authenticate failed. # If authenticate failed.
server = self.getServer() server = self.getServer()
username = self.getUsername() username = self.getUsername()
status = window('emby_serverStatus') status = window('emby_serverStatus')
# The status Stop is for when user cancelled password dialog. # The status Stop is for when user cancelled password dialog.
if server and username and status != "Stop": if server and username and status != "Stop":
# Only if there's information found to login # Only if there's information found to login
@ -444,4 +441,4 @@ class UserClient(threading.Thread):
self.auth = True self.auth = True
self.doUtils.stopSession() self.doUtils.stopSession()
self.logMsg("##===---- UserClient Stopped ----===##", 0) log("##===---- UserClient Stopped ----===##", 0)