Centralize Direct Play and Direct Paths

This commit is contained in:
tomkat83 2016-04-12 17:18:32 +02:00
parent e4aefaaa5e
commit 9d06225228
6 changed files with 180 additions and 147 deletions

View file

@ -2,7 +2,7 @@
<strings> <strings>
<!-- Add-on settings --> <!-- Add-on settings -->
<string id="30000">Server Address (IP)</string><!-- Verified --> <string id="30000">Server Address (IP)</string><!-- Verified -->
<string id="30002">Deactivate Direct Play and enforce Transcoding</string><!-- Verified --> <string id="30002">Prefered playback method</string><!-- Verified -->
<string id="30004">Log level</string><!-- Verified --> <string id="30004">Log level</string><!-- Verified -->
<string id="30005">Username: </string> <string id="30005">Username: </string>
<string id="30006">Password: </string> <string id="30006">Password: </string>
@ -130,7 +130,7 @@
<string id="30157">Enable Enhanced Images (eg CoverArt)</string><!-- Verified --> <string id="30157">Enable Enhanced Images (eg CoverArt)</string><!-- Verified -->
<string id="30158">Metadata</string> <string id="30158">Metadata</string>
<string id="30159">Artwork</string> <string id="30159">Artwork</string>
<string id="30160">Video Quality</string><!-- Verified --> <string id="30160">Video Quality for Transcoding</string><!-- Verified -->
<string id="30161">Enable Suggested Loader (Requires Restart)</string> <string id="30161">Enable Suggested Loader (Requires Restart)</string>
<string id="30162">Add Season Number</string> <string id="30162">Add Season Number</string>
@ -298,7 +298,7 @@
<string id="30533">Duration of the music library pop up (in seconds)</string> <string id="30533">Duration of the music library pop up (in seconds)</string>
<string id="30534">Server messages</string> <string id="30534">Server messages</string>
<string id="30535">[COLOR yellow]Generate a new unique device Id (e.g. when cloning Kodi)[/COLOR]</string> <string id="30535">[COLOR yellow]Generate a new unique device Id (e.g. when cloning Kodi)[/COLOR]</string>
<string id="30536">Users must log in every time when Kodi restarts</string> <string id="30536">Users must log in every time Kodi restarts</string>
<string id="30537">RESTART KODI IF YOU MAKE ANY CHANGES</string> <string id="30537">RESTART KODI IF YOU MAKE ANY CHANGES</string>
<string id="30538">Complete Re-Sync necessary</string> <string id="30538">Complete Re-Sync necessary</string>
@ -384,7 +384,7 @@
<string id="39040">Replace Plex TV SHOWS with:</string> <string id="39040">Replace Plex TV SHOWS with:</string>
<string id="39041">Original Plex MUSIC path to replace:</string> <string id="39041">Original Plex MUSIC path to replace:</string>
<string id="39042">Replace Plex MUSIC with:</string> <string id="39042">Replace Plex MUSIC with:</string>
<string id="39043">Go a step further and complete replace all original Plex library paths (/volume1/media) with custom SMB paths (smb://NAS/MyStuff)?</string> <string id="39043">Go a step further and completely replace all original Plex library paths (/volume1/media) with custom SMB paths (smb://NAS/MyStuff)?</string>
<string id="39044">Please enter your custom smb paths in the settings under "Sync Options" and then restart Kodi</string> <string id="39044">Please enter your custom smb paths in the settings under "Sync Options" and then restart Kodi</string>
<string id="39045">Appearance Tweaks</string> <string id="39045">Appearance Tweaks</string>
@ -398,8 +398,8 @@
<string id="39053">Do a full library sync every x minutes</string> <string id="39053">Do a full library sync every x minutes</string>
<string id="39054">remote</string> <string id="39054">remote</string>
<string id="39055">Searching for Plex Server</string> <string id="39055">Searching for Plex Server</string>
<string id="39056">Used by Sync and when attempting to Direct Play</string>
<string id="39057">Customize Paths</string>
<!-- Plex Entrypoint.py --> <!-- Plex Entrypoint.py -->
<string id="39200">Log-out Plex Home User </string> <string id="39200">Log-out Plex Home User </string>

View file

@ -2,7 +2,7 @@
<strings> <strings>
<string id="30000">IP-Adresse des Servers</string> <string id="30000">IP-Adresse des Servers</string>
<string id="30001">Automatisches Öffnen von Ordnern mit einem Eintrag</string> <string id="30001">Automatisches Öffnen von Ordnern mit einem Eintrag</string>
<string id="30002">Direct Play deaktivieren and Transkodieren erzwingen</string> <string id="30002">Gewünschte Wiedergabe-Methode</string>
<string id="30004">Log Level:</string> <string id="30004">Log Level:</string>
<string id="30005">Benutzername: </string> <string id="30005">Benutzername: </string>
<string id="30006">Passwort: </string> <string id="30006">Passwort: </string>
@ -163,7 +163,7 @@
<string id="30157">Deaktiviere erweiterte Bilder (z.B. CoverArt)</string> <string id="30157">Deaktiviere erweiterte Bilder (z.B. CoverArt)</string>
<string id="30158">Metadaten</string> <string id="30158">Metadaten</string>
<string id="30159">Grafiken</string> <string id="30159">Grafiken</string>
<string id="30160">Videoqualität</string> <string id="30160">Videoqualität für Transkodierung</string>
<string id="30161">'Empfohlen'-Loader aktivieren (Erfordert Neustart)</string> <string id="30161">'Empfohlen'-Loader aktivieren (Erfordert Neustart)</string>
<string id="30162">Staffelnummer hinzufügen</string> <string id="30162">Staffelnummer hinzufügen</string>
@ -336,6 +336,9 @@
<string id="39053">Kompletten Scan aller Bibliotheken alle x Minuten durchführen</string> <string id="39053">Kompletten Scan aller Bibliotheken alle x Minuten durchführen</string>
<string id="39054">remote</string> <string id="39054">remote</string>
<string id="39055">Suche Plex Server</string> <string id="39055">Suche Plex Server</string>
<string id="39056">Verwendet für Synchronisierung sowie beim Versuch, Direct Play zu nutzen</string>
<string id="39057">Pfade ändern</string>
<!-- Plex Entrypoint.py --> <!-- Plex Entrypoint.py -->

View file

@ -394,7 +394,7 @@ class PlexAPI():
name, scheme, ip, port, type, owned, token name, scheme, ip, port, type, owned, token
""" """
address = ip + ':' + port address = ip + ':' + port
baseURL = scheme+'://'+ip+':'+port baseURL = scheme + '://' + ip + ':' + port
self.g_PMS[uuid] = { self.g_PMS[uuid] = {
'name': name, 'name': name,
'scheme': scheme, 'scheme': scheme,
@ -485,7 +485,8 @@ class PlexAPI():
elif "Resource-Identifier:" in each: elif "Resource-Identifier:" in each:
update['uuid'] = each.split(':')[1].strip() update['uuid'] = each.split(':')[1].strip()
elif "Name:" in each: elif "Name:" in each:
update['serverName'] = each.split(':')[1].strip().decode('utf-8', 'replace') update['serverName'] = each.split(
':')[1].strip().decode('utf-8', 'replace')
elif "Port:" in each: elif "Port:" in each:
update['port'] = each.split(':')[1].strip() update['port'] = each.split(':')[1].strip()
elif "Updated-At:" in each: elif "Updated-At:" in each:
@ -582,8 +583,8 @@ class PlexAPI():
PMS = {} PMS = {}
PMS['name'] = Dir.get('name') PMS['name'] = Dir.get('name')
infoAge = time.time() - int(Dir.get('lastSeenAt')) infoAge = time.time() - int(Dir.get('lastSeenAt'))
oneDayInSec = 60*60*24 oneDayInSec = 60 * 60 * 24
if infoAge > 2*oneDayInSec: if infoAge > 2 * oneDayInSec:
self.logMsg("Server %s not seen for 2 days - " self.logMsg("Server %s not seen for 2 days - "
"skipping." % PMS['name'], 0) "skipping." % PMS['name'], 0)
continue continue
@ -708,9 +709,10 @@ class PlexAPI():
""" """
# provide credentials # provide credentials
### optional... when 'realm' is unknown # optional... when 'realm' is unknown
##passmanager = urllib2.HTTPPasswordMgrWithDefaultRealm() ##passmanager = urllib2.HTTPPasswordMgrWithDefaultRealm()
##passmanager.add_password(None, address, username, password) # None: default "realm" # passmanager.add_password(None, address, username, password) # None:
# default "realm"
passmanager = urllib2.HTTPPasswordMgr() passmanager = urllib2.HTTPPasswordMgr()
passmanager.add_password(MyPlexHost, MyPlexURL, username, password) passmanager.add_password(MyPlexHost, MyPlexURL, username, password)
authhandler = urllib2.HTTPBasicAuthHandler(passmanager) authhandler = urllib2.HTTPBasicAuthHandler(passmanager)
@ -746,9 +748,11 @@ class PlexAPI():
MyPlexURL = 'http://' + MyPlexHost + MyPlexSignOutPath MyPlexURL = 'http://' + MyPlexHost + MyPlexSignOutPath
# create POST request # create POST request
xargs = { 'X-Plex-Token': authtoken } xargs = {'X-Plex-Token': authtoken}
request = urllib2.Request(MyPlexURL, None, xargs) request = urllib2.Request(MyPlexURL, None, xargs)
request.get_method = lambda: 'POST' # turn into 'POST' - done automatically with data!=None. But we don't have data. # turn into 'POST' - done automatically with data!=None. But we don't
# have data.
request.get_method = lambda: 'POST'
response = urllib2.urlopen(request).read() response = urllib2.urlopen(request).read()
@ -1005,12 +1009,12 @@ class PlexAPI():
if key.startswith('http://') or key.startswith('https://'): # external address - keep if key.startswith('http://') or key.startswith('https://'): # external address - keep
path = key path = key
else: else:
if AuthToken=='': if AuthToken == '':
path = key path = key
else: else:
xargs = dict() xargs = dict()
xargs['X-Plex-Token'] = AuthToken xargs['X-Plex-Token'] = AuthToken
if key.find('?')==-1: if key.find('?') == -1:
path = key + '?' + urlencode(xargs) path = key + '?' + urlencode(xargs)
else: else:
path = key + '&' + urlencode(xargs) path = key + '&' + urlencode(xargs)
@ -1040,14 +1044,15 @@ class PlexAPI():
# This is bogus (note the extra path component) but ATV is stupid when it comes to caching images, it doesn't use querystrings. # This is bogus (note the extra path component) but ATV is stupid when it comes to caching images, it doesn't use querystrings.
# Fortunately PMS is lenient... # Fortunately PMS is lenient...
transcodePath = '/photo/:/transcode/' +str(width)+'x'+str(height)+ '/' + quote_plus(path) transcodePath = '/photo/:/transcode/' + \
str(width) + 'x' + str(height) + '/' + quote_plus(path)
args = dict() args = dict()
args['width'] = width args['width'] = width
args['height'] = height args['height'] = height
args['url'] = path args['url'] = path
if not AuthToken=='': if not AuthToken == '':
args['X-Plex-Token'] = AuthToken args['X-Plex-Token'] = AuthToken
return transcodePath + '?' + urlencode(args) return transcodePath + '?' + urlencode(args)
@ -1062,10 +1067,10 @@ class PlexAPI():
result: result:
final path to image file final path to image file
""" """
if not AuthToken=='': if not AuthToken == '':
xargs = dict() xargs = dict()
xargs['X-Plex-Token'] = AuthToken xargs['X-Plex-Token'] = AuthToken
if path.find('?')==-1: if path.find('?') == -1:
path = path + '?' + urlencode(xargs) path = path + '?' + urlencode(xargs)
else: else:
path = path + '&' + urlencode(xargs) path = path + '&' + urlencode(xargs)
@ -1095,7 +1100,7 @@ class PlexAPI():
args['maxAudioBitrate'] = maxAudioBitrate args['maxAudioBitrate'] = maxAudioBitrate
xargs = clientinfo.ClientInfo().getXArgsDeviceInfo(options) xargs = clientinfo.ClientInfo().getXArgsDeviceInfo(options)
if not AuthToken=='': if not AuthToken == '':
xargs['X-Plex-Token'] = AuthToken xargs['X-Plex-Token'] = AuthToken
return transcodePath + urlencode(args) + '&' + urlencode(xargs) return transcodePath + urlencode(args) + '&' + urlencode(xargs)
@ -1110,10 +1115,10 @@ class PlexAPI():
result: result:
final path to audio file final path to audio file
""" """
if not AuthToken=='': if not AuthToken == '':
xargs = dict() xargs = dict()
xargs['X-Plex-Token'] = AuthToken xargs['X-Plex-Token'] = AuthToken
if path.find('?')==-1: if path.find('?') == -1:
path = path + '?' + urlencode(xargs) path = path + '?' + urlencode(xargs)
else: else:
path = path + '&' + urlencode(xargs) path = path + '&' + urlencode(xargs)
@ -1229,7 +1234,7 @@ class API():
res = self.item[0][self.part].attrib.get('file') res = self.item[0][self.part].attrib.get('file')
except: except:
res = None res = None
if res: if res is not None:
res = unquote(res).decode('utf-8') res = unquote(res).decode('utf-8')
return res return res
@ -1946,7 +1951,8 @@ class API():
kodiindex = 0 kodiindex = 0
for stream in mediastreams: for stream in mediastreams:
index = stream.attrib['id'] index = stream.attrib['id']
# Since Emby returns all possible tracks together, have to pull only external subtitles. # Since Emby returns all possible tracks together, have to pull
# only external subtitles.
key = stream.attrib.get('key') key = stream.attrib.get('key')
# IsTextSubtitleStream if true, is available to download from emby. # IsTextSubtitleStream if true, is available to download from emby.
if stream.attrib.get('streamType') == "3" and key: if stream.attrib.get('streamType') == "3" and key:
@ -2031,27 +2037,61 @@ class API():
listItem.addStreamInfo( listItem.addStreamInfo(
"video", {'duration': self.getRuntime()[1]}) "video", {'duration': self.getRuntime()[1]})
def validatePlayurl(self, playurl, typus): def validatePlayurl(self, path, typus, forceCheck=False):
""" """
Returns a valid url for Kodi, e.g. with substituted path Returns a valid path for Kodi, e.g. with '\' substituted to '\\' in
Unicode. Returns None if this is not possible
path : Unicode
typus : Plex type from PMS xml
forceCheck : Will always try to check validity of path
Will also skip confirmation dialog if path not found
""" """
if path is None:
return None
types = {
'movie': 'movie',
'show': 'tv',
'season': 'tv',
'episode': 'tv',
'artist': 'music',
'album': 'music',
'song': 'music',
'track': 'music',
}
typus = types[typus]
if utils.window('remapSMB') == 'true': if utils.window('remapSMB') == 'true':
playurl = playurl.replace(utils.window('remapSMB%sOrg' % typus), path = path.replace(utils.window('remapSMB%sOrg' % typus),
utils.window('remapSMB%sNew' % typus)) utils.window('remapSMB%sNew' % typus))
# There might be backslashes left over: # There might be backslashes left over:
playurl = playurl.replace('\\', '/') path = path.replace('\\', '/')
elif utils.window('replaceSMB') == 'true': elif utils.window('replaceSMB') == 'true':
if playurl.startswith('\\\\'): if path.startswith('\\\\'):
playurl = 'smb:' + playurl.replace('\\', '/') path = 'smb:' + path.replace('\\', '/')
if (utils.window('emby_pathverified') != "true" and if utils.window('emby_pathverified') == 'true' and forceCheck is False:
not xbmcvfs.exists(playurl.encode('utf-8'))): return path
check = xbmcvfs.exists(path.encode('utf-8'))
# exists() NEEDS either a '/' or '\\' at the end of a DIR name
if check is False:
check = xbmcvfs.exists((path + '/').encode('utf-8'))
if check is False:
check = xbmcvfs.exists((path + '\\').encode('utf-8'))
if check is False:
if forceCheck is False:
# Validate the path is correct with user intervention # Validate the path is correct with user intervention
if self.askToValidate(playurl): if self.askToValidate(path):
utils.window('emby_shouldStop', value="true") utils.window('emby_shouldStop', value="true")
playurl = False path = None
utils.window('emby_pathverified', value='true') utils.window('emby_pathverified', value='true')
utils.settings('emby_pathverified', value='true') utils.settings('emby_pathverified', value='true')
return playurl else:
path = None
elif forceCheck is False:
if utils.window('emby_pathverified') != 'true':
utils.window('emby_pathverified', value='true')
utils.settings('emby_pathverified', value='true')
return path
def askToValidate(self, url): def askToValidate(self, url):
""" """

View file

@ -440,8 +440,8 @@ class Movies(Items):
# Something went wrong, trying to use non-direct paths # Something went wrong, trying to use non-direct paths
doIndirect = True doIndirect = True
else: else:
playurl = API.validatePlayurl(playurl, 'movie') playurl = API.validatePlayurl(playurl, API.getType())
if playurl is False: if playurl is None:
return False return False
if "\\" in playurl: if "\\" in playurl:
# Local path # Local path
@ -450,7 +450,6 @@ class Movies(Items):
# Network share # Network share
filename = playurl.rsplit("/", 1)[1] filename = playurl.rsplit("/", 1)[1]
path = playurl.replace(filename, "") path = playurl.replace(filename, "")
utils.window('emby_pathverified', value="true")
if doIndirect: if doIndirect:
# Set plugin path and media flags using real filename # Set plugin path and media flags using real filename
path = "plugin://plugin.video.plexkodiconnect.movies/" path = "plugin://plugin.video.plexkodiconnect.movies/"
@ -1041,8 +1040,8 @@ class TVShows(Items):
# Something went wrong, trying to use non-direct paths # Something went wrong, trying to use non-direct paths
doIndirect = True doIndirect = True
else: else:
playurl = API.validatePlayurl(playurl, 'tv') playurl = API.validatePlayurl(playurl, API.getType())
if playurl is False: if playurl is None:
return False return False
if "\\" in playurl: if "\\" in playurl:
# Local path # Local path
@ -1052,12 +1051,6 @@ class TVShows(Items):
# Network path # Network path
path = "%s/" % playurl path = "%s/" % playurl
toplevelpath = "%s/" % dirname(dirname(path)) toplevelpath = "%s/" % dirname(dirname(path))
if (utils.window('emby_pathverified') != "true" and
not xbmcvfs.exists(path.encode('utf-8'))):
# Validate the path is correct with user intervention
if self.askToValidate(playurl):
return False
utils.window('emby_pathverified', value="true")
if doIndirect: if doIndirect:
# Set plugin path # Set plugin path
toplevelpath = "plugin://plugin.video.plexkodiconnect.tvshows/" toplevelpath = "plugin://plugin.video.plexkodiconnect.tvshows/"
@ -1331,13 +1324,8 @@ class TVShows(Items):
# Something went wrong, trying to use non-direct paths # Something went wrong, trying to use non-direct paths
doIndirect = True doIndirect = True
else: else:
playurl = API.validatePlayurl(playurl, 'tv') playurl = API.validatePlayurl(playurl, API.getType())
if playurl is False: if playurl is None:
return False
if (utils.window('emby_pathverified') != "true" and
not xbmcvfs.exists(playurl.encode('utf-8'))):
# Validate the path is correct with user intervention
if self.askToValidate(playurl):
return False return False
if "\\" in playurl: if "\\" in playurl:
# Local path # Local path
@ -1346,7 +1334,6 @@ class TVShows(Items):
# Network share # Network share
filename = playurl.rsplit("/", 1)[1] filename = playurl.rsplit("/", 1)[1]
path = playurl.replace(filename, "") path = playurl.replace(filename, "")
utils.window('emby_pathverified', value="true")
if doIndirect: if doIndirect:
# Set plugin path and media flags using real filename # Set plugin path and media flags using real filename
path = "plugin://plugin.video.plexkodiconnect.movies/" path = "plugin://plugin.video.plexkodiconnect.movies/"
@ -2085,13 +2072,8 @@ class Music(Items):
# Something went wrong, trying to use non-direct paths # Something went wrong, trying to use non-direct paths
doIndirect = True doIndirect = True
else: else:
playurl = API.validatePlayurl(playurl, 'music') playurl = API.validatePlayurl(playurl, API.getType())
if playurl is False: if playurl is None:
return False
if (utils.window('emby_pathverified') != "true" and
not xbmcvfs.exists(playurl.encode('utf-8'))):
# Validate the path is correct with user intervention
if self.askToValidate(playurl):
return False return False
if "\\" in playurl: if "\\" in playurl:
# Local path # Local path
@ -2100,7 +2082,6 @@ class Music(Items):
# Network share # Network share
filename = playurl.rsplit("/", 1)[1] filename = playurl.rsplit("/", 1)[1]
path = playurl.replace(filename, "") path = playurl.replace(filename, "")
utils.window('emby_pathverified', value="true")
if doIndirect: if doIndirect:
# Plex works a bit differently # Plex works a bit differently
path = "%s%s" % (self.server, item[0][0].attrib.get('key')) path = "%s%s" % (self.server, item[0][0].attrib.get('key'))

View file

@ -91,34 +91,25 @@ class PlayUtils():
Returns the path/playurl if successful, False otherwise Returns the path/playurl if successful, False otherwise
""" """
# Requirement: Filesystem, Accessible path # set to either 'Direct Stream=1' or 'Transcode=2'
if utils.settings('playFromStream') == "true": if utils.settings('playType') != "0":
# User forcing to play via HTTP # User forcing to play via HTTP
self.logMsg("Can't direct play, user enabled play from HTTP.", 1) self.logMsg("User chose to not direct play", 1)
return False return False
if self.h265enabled(): if self.h265enabled():
return False return False
path = self.API.getFilePath() path = self.API.validatePlayurl(self.API.getFilePath(),
self.API.getType(),
forceCheck=True)
if path is None: if path is None:
self.logMsg('PMS item does not have a filepath', 2)
return False
# Assign network protocol
if path.startswith('\\\\'):
path = path.replace('\\\\', 'smb://')
path = path.replace('\\', '/')
# Plex returns Windows paths as e.g. 'c:\slfkjelf\slfje\file.mkv'
elif '\\' in path:
path = path.replace('\\', '\\\\')
if xbmcvfs.exists(path):
self.logMsg('Kodi can access file %s - direct playing' % path, 2)
return path
else:
self.logMsg('Kodi cannot access file %s - no direct play' self.logMsg('Kodi cannot access file %s - no direct play'
% path, 2) % path, 1)
return False return False
else:
self.logMsg('Kodi can access file %s - direct playing' % path, 1)
return path
def directPlay(self): def directPlay(self):
@ -198,13 +189,17 @@ class PlayUtils():
return False return False
def isDirectStream(self): def isDirectStream(self):
if not self.h265enabled(): # set to 'Transcode=2'
if utils.settings('playType') == "2":
# User forcing to play via HTTP
self.logMsg("User chose to transcode", 1)
return False
if self.h265enabled():
return False return False
# Verify the bitrate # Verify the bitrate
if not self.isNetworkSufficient(): if not self.isNetworkSufficient():
self.logMsg( self.logMsg("The network speed is insufficient to direct stream "
"The network speed is insufficient to direct stream file.", 1) "file. Transcoding", 1)
return False return False
return True return True
@ -228,11 +223,18 @@ class PlayUtils():
return playurl return playurl
def isNetworkSufficient(self): def isNetworkSufficient(self):
"""
settings = self.getBitrate() Returns True if the network is sufficient (set in file settings)
"""
try:
sourceBitrate = int(self.API.getDataFromPartOrMedia('bitrate')) sourceBitrate = int(self.API.getDataFromPartOrMedia('bitrate'))
self.logMsg("The add-on settings bitrate is: %s, the video bitrate required is: %s" % (settings, sourceBitrate), 1) except:
self.logMsg('Could not detect source bitrate. It is assumed to be'
'sufficient', 1)
return True
settings = self.getBitrate()
self.logMsg("The add-on settings bitrate is: %s, the video bitrate"
"required is: %s" % (settings, sourceBitrate), 1)
if settings < sourceBitrate: if settings < sourceBitrate:
return False return False
return True return True

View file

@ -37,13 +37,7 @@
<setting id="plexToken" label="plexToken" type="text" default="" visible="false" /> <setting id="plexToken" label="plexToken" type="text" default="" visible="false" />
<setting id="plexHomeSize" type="number" default="1" visible="false" /> <setting id="plexHomeSize" type="number" default="1" visible="false" />
</category> </category>
<category label="Plex Companion">
<setting type="lsep" label="39008" />
<setting id="plexCompanion" label="39004" type="bool" default="true" />
<setting id="deviceNameOpt" label="30504" type="bool" default="false" />
<setting id="deviceName" label="30016" type="text" visible="eq(-1,true)" default="Kodi" />
<setting id="companionPort" label="39005" type="number" default="3005" option="int" visible="eq(-3,true)"/>
</category>
<category label="30506"><!-- Sync Options --> <category label="30506"><!-- Sync Options -->
<setting type="lsep" label="30537" /><!-- Restart if you make changes --> <setting type="lsep" label="30537" /><!-- Restart if you make changes -->
<setting id="syncEmptyShows" type="bool" label="30508" default="false" visible="false"/> <setting id="syncEmptyShows" type="bool" label="30508" default="false" visible="false"/>
@ -63,14 +57,7 @@
<setting type="lsep" label="30538" /><!-- Complete Re-Sync necessary --> <setting type="lsep" label="30538" /><!-- Complete Re-Sync necessary -->
<setting id="enableMusic" type="bool" label="30509" default="true" /> <setting id="enableMusic" type="bool" label="30509" default="true" />
<setting id="useDirectPaths" type="enum" label="30511" values="Addon(Default)|Native(Direct paths)" default="0" visible="true"/> <!-- Playback mode --> <setting id="useDirectPaths" type="enum" label="30511" values="Addon(Default)|Native(Direct paths)" default="0" visible="true"/> <!-- Playback mode -->
<setting id="replaceSMB" type="bool" label="39034" default="true" visible="eq(-1,1)"/> <!-- replace all Plex paths with SMB paths -->
<setting id="remapSMB" type="bool" label="39035" default="false" visible="eq(-2,1)"/> <!-- replace Plex paths /volume1/media or \\myserver\media with a custom SMB path smb://NAS/mystuff -->
<setting id="remapSMBmovieOrg" type="text" label="39037" default="" visible="eq(-1,true)"/> <!-- Original Plex MOVIE path to replace -->
<setting id="remapSMBmovieNew" type="text" label="39038" default="smb://" visible="eq(-2,true)"/> <!-- Replace Plex MOVIE with: -->
<setting id="remapSMBtvOrg" type="text" label="39039" default="" visible="eq(-3,true)"/> <!-- Original Plex TV SHOWS path to replace: -->
<setting id="remapSMBtvNew" type="text" label="39040" default="smb://" visible="eq(-4,true)"/> <!-- Replace Plex TV SHOWS with: -->
<setting id="remapSMBmusicOrg" type="text" label="39041" default="" visible="eq(-5,true)"/> <!-- Original Plex MUSIC path to replace: -->
<setting id="remapSMBmusicNew" type="text" label="39042" default="smb://" visible="eq(-6,true)"/> <!-- Replace Plex MUSIC with: -->
<setting id="streamMusic" type="bool" label="30510" default="false" visible="false" subsetting="true"/> <!-- Direct stream Music library --> <setting id="streamMusic" type="bool" label="30510" default="false" visible="false" subsetting="true"/> <!-- Direct stream Music library -->
<setting type="lsep" label="30523" visible="false"/> <!-- Music metadata options --> <setting type="lsep" label="30523" visible="false"/> <!-- Music metadata options -->
@ -81,6 +68,18 @@
<setting id="emby_pathverified" type="bool" default="false" visible="false" /> <!-- If 'false': one single warning message pops up if PKC cannot verify direct paths --> <setting id="emby_pathverified" type="bool" default="false" visible="false" /> <!-- If 'false': one single warning message pops up if PKC cannot verify direct paths -->
</category> </category>
<category label="39057"><!-- Customize Paths -->
<setting type="lsep" label="39056" /><!-- Used by Sync and to attempt to direct play -->
<setting id="replaceSMB" type="bool" label="39034" default="true" /> <!-- replace all Plex paths with SMB paths -->
<setting id="remapSMB" type="bool" label="39035" default="false" /> <!-- replace Plex paths /volume1/media or \\myserver\media with a custom SMB path smb://NAS/mystuff -->
<setting id="remapSMBmovieOrg" type="text" label="39037" default="" visible="eq(-1,true)"/> <!-- Original Plex MOVIE path to replace -->
<setting id="remapSMBmovieNew" type="text" label="39038" default="smb://" visible="eq(-2,true)"/> <!-- Replace Plex MOVIE with: -->
<setting id="remapSMBtvOrg" type="text" label="39039" default="" visible="eq(-3,true)"/> <!-- Original Plex TV SHOWS path to replace: -->
<setting id="remapSMBtvNew" type="text" label="39040" default="smb://" visible="eq(-4,true)"/> <!-- Replace Plex TV SHOWS with: -->
<setting id="remapSMBmusicOrg" type="text" label="39041" default="" visible="eq(-5,true)"/> <!-- Original Plex MUSIC path to replace: -->
<setting id="remapSMBmusicNew" type="text" label="39042" default="smb://" visible="eq(-6,true)"/> <!-- Replace Plex MUSIC with: -->
</category>
<category label="30516"><!-- Playback --> <category label="30516"><!-- Playback -->
<setting type="sep" /> <setting type="sep" />
<setting id="enableCinema" type="bool" label="30518" default="true" /> <setting id="enableCinema" type="bool" label="30518" default="true" />
@ -92,15 +91,16 @@
<setting id="deleteMovies" type="bool" label="30116" visible="eq(-2,true)" default="false" subsetting="true" /> <setting id="deleteMovies" type="bool" label="30116" visible="eq(-2,true)" default="false" subsetting="true" />
<setting id="resumeJumpBack" type="slider" label="30521" default="10" range="0,1,120" option="int" /> <setting id="resumeJumpBack" type="slider" label="30521" default="10" range="0,1,120" option="int" />
<setting type="sep" /> <setting type="sep" />
<setting id="playFromStream" type="bool" label="30002" default="false" /> <setting id="playType" type="enum" label="30002" values="Direct Play (default)|Direct Stream|Force Transcode" default="0" />
<setting id="transcoderVideoQualities" type="enum" label="30160" values="420x420, 320Kbps|576x320, 720Kbps|720x480, 1.5Mbps|1024x768, 2Mbps|1280x720, 3Mbps|1280x720, 4Mbps|1920x1080, 8Mbps|1920x1080, 10Mbps|1920x1080, 12Mbps|1920x1080, 20Mbps|1920x1080, 40Mbps" visible="eq(-1,true)" default="11" /> <setting id="transcoderVideoQualities" type="enum" label="30160" values="420x420, 320Kbps|576x320, 720Kbps|720x480, 1.5Mbps|1024x768, 2Mbps|1280x720, 3Mbps|1280x720, 4Mbps|1920x1080, 8Mbps|1920x1080, 10Mbps|1920x1080, 12Mbps|1920x1080, 20Mbps|1920x1080, 40Mbps" default="11" />
<setting id="audioBoost" type="slider" label="39001" default="0" range="0,10,100" option="int"/>
<setting id="transcodeH265" type="enum" label="30522" default="0" values="Disabled (default)|480p (and higher)|720p (and higher)|1080p" /> <setting id="transcodeH265" type="enum" label="30522" default="0" values="Disabled (default)|480p (and higher)|720p (and higher)|1080p" />
<setting id="audioBoost" type="slider" label="39001" default="0" range="0,10,100" option="int"/>
<setting id="subtitleSize" label="39002" type="slider" option="int" range="0,30,300" default="100" /> <setting id="subtitleSize" label="39002" type="slider" option="int" range="0,30,300" default="100" />
<setting id="markPlayed" type="number" visible="false" default="95" /> <setting id="markPlayed" type="number" visible="false" default="95" />
<setting id="failedCount" type="number" visible="false" default="0" /> <setting id="failedCount" type="number" visible="false" default="0" />
<setting id="networkCreds" type="text" visible="false" default="" /> <setting id="networkCreds" type="text" visible="false" default="" />
</category> </category>
<!-- <!--
<category label="30235" visible="false"> <category label="30235" visible="false">
<setting id="enableCoverArt" type="bool" label="30157" default="true" visible="false"/> <setting id="enableCoverArt" type="bool" label="30157" default="true" visible="false"/>
@ -113,8 +113,16 @@
<setting id="newmusictime" type="number" label="30533" visible="false" default="2" option="int" subsetting="true" /> <setting id="newmusictime" type="number" label="30533" visible="false" default="2" option="int" subsetting="true" />
</category> </category>
--> -->
<category label="Plex Companion">
<setting type="lsep" label="39008" />
<setting id="plexCompanion" label="39004" type="bool" default="true" />
<setting id="deviceNameOpt" label="30504" type="bool" default="false" />
<setting id="deviceName" label="30016" type="text" visible="eq(-1,true)" default="Kodi" />
<setting id="companionPort" label="39005" type="number" default="3005" option="int" visible="eq(-3,true)"/>
</category>
<category label="39045"><!-- Appearance Tweaks --> <category label="39045"><!-- Appearance Tweaks -->
<setting id="connectMsg" type="bool" label="30249" default="true" />
<setting type="lsep" label="39046" /> <setting type="lsep" label="39046" />
<setting id="OnDeckTvAppendShow" type="bool" label="39047" default="false" /><!--On Deck view: Append show title to episode--> <setting id="OnDeckTvAppendShow" type="bool" label="39047" default="false" /><!--On Deck view: Append show title to episode-->
<setting id="OnDeckTvAppendSeason" type="bool" label="39048" default="false" /><!--On Deck view: Append season number to episode--> <setting id="OnDeckTvAppendSeason" type="bool" label="39048" default="false" /><!--On Deck view: Append season number to episode-->
@ -123,7 +131,6 @@
<category label="30022"><!-- Advanced --> <category label="30022"><!-- Advanced -->
<setting id="logLevel" type="enum" label="30004" values="Disabled|Info|Debug" default="1" /> <setting id="logLevel" type="enum" label="30004" values="Disabled|Info|Debug" default="1" />
<setting id="startupDelay" type="number" label="30529" default="0" option="int" /> <setting id="startupDelay" type="number" label="30529" default="0" option="int" />
<setting id="connectMsg" type="bool" label="30249" default="true" />
<setting label="39018" type="action" action="RunPlugin(plugin://plugin.video.plexkodiconnect/?mode=repair)" option="close" /> <!-- Repair local database (force update all content) --> <setting label="39018" type="action" action="RunPlugin(plugin://plugin.video.plexkodiconnect/?mode=repair)" option="close" /> <!-- Repair local database (force update all content) -->
<setting label="39020" type="action" action="RunPlugin(plugin://plugin.video.plexkodiconnect/?mode=texturecache)" option="close" /> <!-- Cache all images to Kodi texture cache --> <setting label="39020" type="action" action="RunPlugin(plugin://plugin.video.plexkodiconnect/?mode=texturecache)" option="close" /> <!-- Cache all images to Kodi texture cache -->
<setting label="30535" type="action" action="RunPlugin(plugin://plugin.video.plexkodiconnect?mode=deviceid)" /><!-- Reset device id uuid --> <setting label="30535" type="action" action="RunPlugin(plugin://plugin.video.plexkodiconnect?mode=deviceid)" /><!-- Reset device id uuid -->