Merge branch 'beta-version'

This commit is contained in:
croneter 2018-06-24 10:52:03 +02:00
commit b646f89970
6 changed files with 96 additions and 73 deletions

View file

@ -1,5 +1,5 @@
[![stable version](https://img.shields.io/badge/stable_version-2.1.1-blue.svg?maxAge=60&style=flat) ](https://github.com/croneter/binary_repo/raw/master/stable/repository.plexkodiconnect/repository.plexkodiconnect-1.0.2.zip) [![stable version](https://img.shields.io/badge/stable_version-2.1.2-blue.svg?maxAge=60&style=flat) ](https://github.com/croneter/binary_repo/raw/master/stable/repository.plexkodiconnect/repository.plexkodiconnect-1.0.2.zip)
[![beta version](https://img.shields.io/badge/beta_version-2.2.2-red.svg?maxAge=60&style=flat) ](https://github.com/croneter/binary_repo/raw/master/beta/repository.plexkodiconnectbeta/repository.plexkodiconnectbeta-1.0.2.zip) [![beta version](https://img.shields.io/badge/beta_version-2.2.3-red.svg?maxAge=60&style=flat) ](https://github.com/croneter/binary_repo/raw/master/beta/repository.plexkodiconnectbeta/repository.plexkodiconnectbeta-1.0.2.zip)
[![Installation](https://img.shields.io/badge/wiki-installation-brightgreen.svg?maxAge=60&style=flat)](https://github.com/croneter/PlexKodiConnect/wiki/Installation) [![Installation](https://img.shields.io/badge/wiki-installation-brightgreen.svg?maxAge=60&style=flat)](https://github.com/croneter/PlexKodiConnect/wiki/Installation)
[![FAQ](https://img.shields.io/badge/wiki-FAQ-brightgreen.svg?maxAge=60&style=flat)](https://github.com/croneter/PlexKodiConnect/wiki/faq) [![FAQ](https://img.shields.io/badge/wiki-FAQ-brightgreen.svg?maxAge=60&style=flat)](https://github.com/croneter/PlexKodiConnect/wiki/faq)
@ -53,7 +53,7 @@ Some people argue that PKC is 'hacky' because of the way it directly accesses th
### PKC Features ### PKC Features
- Support for Kodi 18 Leia Alpha 1 (nightly versions are NOT supported!) - Support for Kodi 18 Leia Alpha 2 (nightly versions are NOT supported!)
- Support for Kodi 17 Krypton - Support for Kodi 17 Krypton
- [Amazon Alexa voice recognition](https://www.plex.tv/apps/streaming-devices/amazon-alexa) - [Amazon Alexa voice recognition](https://www.plex.tv/apps/streaming-devices/amazon-alexa)
- [Cinema Trailers & Extras](https://support.plex.tv/articles/202934883-cinema-trailers-extras/) - [Cinema Trailers & Extras](https://support.plex.tv/articles/202934883-cinema-trailers-extras/)

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="plugin.video.plexkodiconnect" name="PlexKodiConnect" version="2.2.2" provider-name="croneter"> <addon id="plugin.video.plexkodiconnect" name="PlexKodiConnect" version="2.2.3" provider-name="croneter">
<requires> <requires>
<import addon="xbmc.python" version="2.1.0"/> <import addon="xbmc.python" version="2.1.0"/>
<import addon="script.module.requests" version="2.9.1" /> <import addon="script.module.requests" version="2.9.1" />
@ -67,7 +67,11 @@
<summary lang="ru_RU">Нативная интеграция сервера Plex в Kodi</summary> <summary lang="ru_RU">Нативная интеграция сервера Plex в Kodi</summary>
<description lang="ru_RU">Подключите Kodi к своему серверу Plex. Плагин предполагает что вы управляете своими видео с помощью Plex (а не в Kodi). Вы можете потерять текущие базы данных музыки и видео в Kodi (так как плагин напрямую их изменяет). Используйте на свой страх и риск</description> <description lang="ru_RU">Подключите Kodi к своему серверу Plex. Плагин предполагает что вы управляете своими видео с помощью Plex (а не в Kodi). Вы можете потерять текущие базы данных музыки и видео в Kodi (так как плагин напрямую их изменяет). Используйте на свой страх и риск</description>
<disclaimer lang="ru_RU">Используйте на свой страх и риск</disclaimer> <disclaimer lang="ru_RU">Используйте на свой страх и риск</disclaimer>
<news>version 2.2.2 (beta only): <news>version 2.2.3 (beta only):
- Compatibility with Kodi Krypton Alpha 2
- Append tv show and SxxExx to episode playlist entries
version 2.2.2 (beta only):
- Fixes to locking mechanisms which resulted in weird behavior in some cases - Fixes to locking mechanisms which resulted in weird behavior in some cases
- Switch to Python __future__ unicode_literals and absolute paths - Switch to Python __future__ unicode_literals and absolute paths
- Fix UnboundLocalError for playlists - Fix UnboundLocalError for playlists

View file

@ -1,3 +1,7 @@
version 2.2.3 (beta only):
- Compatibility with Kodi Krypton Alpha 2
- Append tv show and SxxExx to episode playlist entries
version 2.2.2 (beta only): version 2.2.2 (beta only):
- Fixes to locking mechanisms which resulted in weird behavior in some cases - Fixes to locking mechanisms which resulted in weird behavior in some cases
- Switch to Python __future__ unicode_literals and absolute paths - Switch to Python __future__ unicode_literals and absolute paths

View file

@ -22,11 +22,6 @@ from . import variables as v
############################################################################### ###############################################################################
LOG = getLogger('PLEX.entrypoint') LOG = getLogger('PLEX.entrypoint')
try:
HANDLE = int(argv[1])
ARGV_0 = path_ops.decode_path(argv[0])
except IndexError:
pass
############################################################################### ###############################################################################
@ -119,7 +114,7 @@ def directory_item(label, path, folder=True):
{"fanart": "special://home/addons/plugin.video.plexkodiconnect/fanart.jpg"}) {"fanart": "special://home/addons/plugin.video.plexkodiconnect/fanart.jpg"})
listitem.setArt( listitem.setArt(
{"landscape":"special://home/addons/plugin.video.plexkodiconnect/fanart.jpg"}) {"landscape":"special://home/addons/plugin.video.plexkodiconnect/fanart.jpg"})
xbmcplugin.addDirectoryItem(handle=HANDLE, xbmcplugin.addDirectoryItem(handle=int(argv[1]),
url=path, url=path,
listitem=listitem, listitem=listitem,
isFolder=folder) isFolder=folder)
@ -130,7 +125,7 @@ def show_main_menu(content_type=None):
Shows the main PKC menu listing with all libraries, Channel, settings, etc. Shows the main PKC menu listing with all libraries, Channel, settings, etc.
""" """
LOG.debug('Do main listing with content_type: %s', content_type) LOG.debug('Do main listing with content_type: %s', content_type)
xbmcplugin.setContent(HANDLE, 'files') xbmcplugin.setContent(int(argv[1]), 'files')
# Get emby nodes from the window props # Get emby nodes from the window props
plexprops = utils.window('Plex.nodes.total') plexprops = utils.window('Plex.nodes.total')
if plexprops: if plexprops:
@ -169,7 +164,7 @@ def show_main_menu(content_type=None):
"plugin://%s?mode=refreshplaylist" % v.ADDON_ID) "plugin://%s?mode=refreshplaylist" % v.ADDON_ID)
directory_item(utils.lang(39204), directory_item(utils.lang(39204),
"plugin://%s?mode=manualsync" % v.ADDON_ID) "plugin://%s?mode=manualsync" % v.ADDON_ID)
xbmcplugin.endOfDirectory(HANDLE) xbmcplugin.endOfDirectory(int(argv[1]))
def switch_plex_user(): def switch_plex_user():
@ -268,7 +263,7 @@ def next_up_episodes(tagname, limit):
count = 0 count = 0
# if the addon is called with nextup parameter, # if the addon is called with nextup parameter,
# we return the nextepisodes list of the given tagname # we return the nextepisodes list of the given tagname
xbmcplugin.setContent(HANDLE, 'episodes') xbmcplugin.setContent(int(argv[1]), 'episodes')
# First we get a list of all the TV shows - filtered by tag # First we get a list of all the TV shows - filtered by tag
params = { params = {
'sort': {'order': "descending", 'method': "lastplayed"}, 'sort': {'order': "descending", 'method': "lastplayed"},
@ -317,13 +312,13 @@ def next_up_episodes(tagname, limit):
'limits': {"end": 1} 'limits': {"end": 1}
} }
for episode in js.get_episodes(params): for episode in js.get_episodes(params):
xbmcplugin.addDirectoryItem(handle=HANDLE, xbmcplugin.addDirectoryItem(handle=int(argv[1]),
url=episode['file'], url=episode['file'],
listitem=create_listitem(episode)) listitem=create_listitem(episode))
count += 1 count += 1
if count == limit: if count == limit:
break break
xbmcplugin.endOfDirectory(handle=HANDLE) xbmcplugin.endOfDirectory(handle=int(argv[1]))
def in_progress_episodes(tagname, limit): def in_progress_episodes(tagname, limit):
@ -333,7 +328,7 @@ def in_progress_episodes(tagname, limit):
count = 0 count = 0
# if the addon is called with inprogressepisodes parameter, # if the addon is called with inprogressepisodes parameter,
# we return the inprogressepisodes list of the given tagname # we return the inprogressepisodes list of the given tagname
xbmcplugin.setContent(HANDLE, 'episodes') xbmcplugin.setContent(int(argv[1]), 'episodes')
# First we get a list of all the in-progress TV shows - filtered by tag # First we get a list of all the in-progress TV shows - filtered by tag
params = { params = {
'sort': {'order': "descending", 'method': "lastplayed"}, 'sort': {'order': "descending", 'method': "lastplayed"},
@ -359,13 +354,13 @@ def in_progress_episodes(tagname, limit):
"lastplayed"] "lastplayed"]
} }
for episode in js.get_episodes(params): for episode in js.get_episodes(params):
xbmcplugin.addDirectoryItem(handle=HANDLE, xbmcplugin.addDirectoryItem(handle=int(argv[1]),
url=episode['file'], url=episode['file'],
listitem=create_listitem(episode)) listitem=create_listitem(episode))
count += 1 count += 1
if count == limit: if count == limit:
break break
xbmcplugin.endOfDirectory(handle=HANDLE) xbmcplugin.endOfDirectory(handle=int(argv[1]))
def recent_episodes(mediatype, tagname, limit): def recent_episodes(mediatype, tagname, limit):
@ -375,7 +370,7 @@ def recent_episodes(mediatype, tagname, limit):
count = 0 count = 0
# if the addon is called with recentepisodes parameter, # if the addon is called with recentepisodes parameter,
# we return the recentepisodes list of the given tagname # we return the recentepisodes list of the given tagname
xbmcplugin.setContent(HANDLE, 'episodes') xbmcplugin.setContent(int(argv[1]), 'episodes')
append_show_title = utils.settings('RecentTvAppendShow') == 'true' append_show_title = utils.settings('RecentTvAppendShow') == 'true'
append_sxxexx = utils.settings('RecentTvAppendSeason') == 'true' append_sxxexx = utils.settings('RecentTvAppendSeason') == 'true'
# First we get a list of all the TV shows - filtered by tag # First we get a list of all the TV shows - filtered by tag
@ -405,13 +400,13 @@ def recent_episodes(mediatype, tagname, limit):
listitem = create_listitem(episode, listitem = create_listitem(episode,
append_show_title=append_show_title, append_show_title=append_show_title,
append_sxxexx=append_sxxexx) append_sxxexx=append_sxxexx)
xbmcplugin.addDirectoryItem(handle=HANDLE, xbmcplugin.addDirectoryItem(handle=int(argv[1]),
url=episode['file'], url=episode['file'],
listitem=listitem) listitem=listitem)
count += 1 count += 1
if count == limit: if count == limit:
break break
xbmcplugin.endOfDirectory(handle=HANDLE) xbmcplugin.endOfDirectory(handle=int(argv[1]))
def get_video_files(plex_id, params): def get_video_files(plex_id, params):
@ -435,14 +430,14 @@ def get_video_files(plex_id, params):
if plex_id is None: if plex_id is None:
LOG.info('No Plex ID found, abort getting Extras') LOG.info('No Plex ID found, abort getting Extras')
return xbmcplugin.endOfDirectory(HANDLE) return xbmcplugin.endOfDirectory(int(argv[1]))
item = PF.GetPlexMetadata(plex_id) item = PF.GetPlexMetadata(plex_id)
try: try:
path = utils.try_decode(item[0][0][0].attrib['file']) path = utils.try_decode(item[0][0][0].attrib['file'])
except (TypeError, IndexError, AttributeError, KeyError): except (TypeError, IndexError, AttributeError, KeyError):
LOG.error('Could not get file path for item %s', plex_id) LOG.error('Could not get file path for item %s', plex_id)
return xbmcplugin.endOfDirectory(HANDLE) return xbmcplugin.endOfDirectory(int(argv[1]))
# Assign network protocol # Assign network protocol
if path.startswith('\\\\'): if path.startswith('\\\\'):
path = path.replace('\\\\', 'smb://') path = path.replace('\\\\', 'smb://')
@ -458,20 +453,20 @@ def get_video_files(plex_id, params):
item_path = utils.try_encode(path_ops.path.join(root, item_path = utils.try_encode(path_ops.path.join(root,
directory)) directory))
listitem = ListItem(item_path, path=item_path) listitem = ListItem(item_path, path=item_path)
xbmcplugin.addDirectoryItem(handle=HANDLE, xbmcplugin.addDirectoryItem(handle=int(argv[1]),
url=item_path, url=item_path,
listitem=listitem, listitem=listitem,
isFolder=True) isFolder=True)
for file in files: for file in files:
item_path = utils.try_encode(path_ops.path.join(root, file)) item_path = utils.try_encode(path_ops.path.join(root, file))
listitem = ListItem(item_path, path=item_path) listitem = ListItem(item_path, path=item_path)
xbmcplugin.addDirectoryItem(handle=HANDLE, xbmcplugin.addDirectoryItem(handle=int(argv[1]),
url=file, url=file,
listitem=listitem) listitem=listitem)
break break
else: else:
LOG.error('Kodi cannot access folder %s', path) LOG.error('Kodi cannot access folder %s', path)
xbmcplugin.endOfDirectory(HANDLE) xbmcplugin.endOfDirectory(int(argv[1]))
@utils.catch_exceptions(warnuser=False) @utils.catch_exceptions(warnuser=False)
@ -487,7 +482,7 @@ def extra_fanart(plex_id, plex_path):
plex_id = plex_path.split("/")[-2] plex_id = plex_path.split("/")[-2]
if not plex_id: if not plex_id:
LOG.error('Could not get a plex_id, aborting') LOG.error('Could not get a plex_id, aborting')
return xbmcplugin.endOfDirectory(HANDLE) return xbmcplugin.endOfDirectory(int(argv[1]))
# We need to store the images locally for this to work # We need to store the images locally for this to work
# because of the caching system in xbmc # because of the caching system in xbmc
@ -499,7 +494,7 @@ def extra_fanart(plex_id, plex_path):
xml = PF.GetPlexMetadata(plex_id) xml = PF.GetPlexMetadata(plex_id)
if xml is None: if xml is None:
LOG.error('Could not download metadata for %s', plex_id) LOG.error('Could not download metadata for %s', plex_id)
return xbmcplugin.endOfDirectory(HANDLE) return xbmcplugin.endOfDirectory(int(argv[1]))
api = API(xml[0]) api = API(xml[0])
backdrops = api.artwork()['Backdrop'] backdrops = api.artwork()['Backdrop']
@ -509,7 +504,7 @@ def extra_fanart(plex_id, plex_path):
fanart_dir, "fanart%.3d.jpg" % count)) fanart_dir, "fanart%.3d.jpg" % count))
listitem = ListItem("%.3d" % count, path=art_file) listitem = ListItem("%.3d" % count, path=art_file)
xbmcplugin.addDirectoryItem( xbmcplugin.addDirectoryItem(
handle=HANDLE, handle=int(argv[1]),
url=art_file, url=art_file,
listitem=listitem) listitem=listitem)
path_ops.copyfile(backdrop, utils.try_decode(art_file)) path_ops.copyfile(backdrop, utils.try_decode(art_file))
@ -523,10 +518,10 @@ def extra_fanart(plex_id, plex_path):
file = utils.decode_path(file) file = utils.decode_path(file)
art_file = utils.try_encode(path_ops.path.join(root, file)) art_file = utils.try_encode(path_ops.path.join(root, file))
listitem = ListItem(file, path=art_file) listitem = ListItem(file, path=art_file)
xbmcplugin.addDirectoryItem(handle=HANDLE, xbmcplugin.addDirectoryItem(handle=int(argv[1]),
url=art_file, url=art_file,
listitem=listitem) listitem=listitem)
xbmcplugin.endOfDirectory(HANDLE) xbmcplugin.endOfDirectory(int(argv[1]))
def on_deck_episodes(viewid, tagname, limit): def on_deck_episodes(viewid, tagname, limit):
@ -538,7 +533,7 @@ def on_deck_episodes(viewid, tagname, limit):
tagname: Name of the Plex library, e.g. "My Movies" tagname: Name of the Plex library, e.g. "My Movies"
limit: Max. number of items to retrieve, e.g. 50 limit: Max. number of items to retrieve, e.g. 50
""" """
xbmcplugin.setContent(HANDLE, 'episodes') xbmcplugin.setContent(int(argv[1]), 'episodes')
append_show_title = utils.settings('OnDeckTvAppendShow') == 'true' append_show_title = utils.settings('OnDeckTvAppendShow') == 'true'
append_sxxexx = utils.settings('OnDeckTvAppendSeason') == 'true' append_sxxexx = utils.settings('OnDeckTvAppendSeason') == 'true'
if utils.settings('OnDeckTVextended') == 'false': if utils.settings('OnDeckTVextended') == 'false':
@ -550,13 +545,13 @@ def on_deck_episodes(viewid, tagname, limit):
if counter == 300: if counter == 300:
LOG.error('Aborting On Deck view, we were not authenticated ' LOG.error('Aborting On Deck view, we were not authenticated '
'for the PMS') 'for the PMS')
xbmcplugin.endOfDirectory(HANDLE, False) xbmcplugin.endOfDirectory(int(argv[1]), False)
return return
sleep(100) sleep(100)
xml = DU().downloadUrl('{server}/library/sections/%s/onDeck' % viewid) xml = DU().downloadUrl('{server}/library/sections/%s/onDeck' % viewid)
if xml in (None, 401): if xml in (None, 401):
LOG.error('Could not download PMS xml for view %s', viewid) LOG.error('Could not download PMS xml for view %s', viewid)
xbmcplugin.endOfDirectory(HANDLE, False) xbmcplugin.endOfDirectory(int(argv[1]), False)
return return
direct_paths = utils.settings('useDirectPaths') == '1' direct_paths = utils.settings('useDirectPaths') == '1'
counter = 0 counter = 0
@ -569,14 +564,14 @@ def on_deck_episodes(viewid, tagname, limit):
listitem.setProperty('resumetime', str(api.resume_point())) listitem.setProperty('resumetime', str(api.resume_point()))
path = api.path(force_first_media=False, direct_paths=direct_paths) path = api.path(force_first_media=False, direct_paths=direct_paths)
xbmcplugin.addDirectoryItem( xbmcplugin.addDirectoryItem(
handle=HANDLE, handle=int(argv[1]),
url=path, url=path,
listitem=listitem) listitem=listitem)
counter += 1 counter += 1
if counter == limit: if counter == limit:
break break
xbmcplugin.endOfDirectory( xbmcplugin.endOfDirectory(
handle=HANDLE, handle=int(argv[1]),
cacheToDisc=utils.settings('enableTextureCache') == 'true') cacheToDisc=utils.settings('enableTextureCache') == 'true')
return return
@ -594,7 +589,7 @@ def on_deck_episodes(viewid, tagname, limit):
items = js.get_tv_shows(params) items = js.get_tv_shows(params)
if not items: if not items:
# Now items retrieved - empty directory # Now items retrieved - empty directory
xbmcplugin.endOfDirectory(handle=HANDLE) xbmcplugin.endOfDirectory(handle=int(argv[1]))
return return
params = { params = {
@ -646,14 +641,14 @@ def on_deck_episodes(viewid, tagname, limit):
listitem = create_listitem(episode, listitem = create_listitem(episode,
append_show_title=append_show_title, append_show_title=append_show_title,
append_sxxexx=append_sxxexx) append_sxxexx=append_sxxexx)
xbmcplugin.addDirectoryItem(handle=HANDLE, xbmcplugin.addDirectoryItem(handle=int(argv[1]),
url=episode['file'], url=episode['file'],
listitem=listitem, listitem=listitem,
isFolder=False) isFolder=False)
count += 1 count += 1
if count >= limit: if count >= limit:
break break
xbmcplugin.endOfDirectory(handle=HANDLE) xbmcplugin.endOfDirectory(handle=int(argv[1]))
def watchlater(): def watchlater():
@ -662,24 +657,25 @@ def watchlater():
""" """
if utils.window('plex_token') == '': if utils.window('plex_token') == '':
LOG.error('No watch later - not signed in to plex.tv') LOG.error('No watch later - not signed in to plex.tv')
return xbmcplugin.endOfDirectory(HANDLE, False) return xbmcplugin.endOfDirectory(int(argv[1]), False)
if utils.window('plex_restricteduser') == 'true': if utils.window('plex_restricteduser') == 'true':
LOG.error('No watch later - restricted user') LOG.error('No watch later - restricted user')
return xbmcplugin.endOfDirectory(HANDLE, False) return xbmcplugin.endOfDirectory(int(argv[1]), False)
xml = DU().downloadUrl('https://plex.tv/pms/playlists/queue/all', xml = DU().downloadUrl('https://plex.tv/pms/playlists/queue/all',
authenticate=False, authenticate=False,
headerOptions={'X-Plex-Token': utils.window('plex_token')}) headerOptions={'X-Plex-Token': utils.window('plex_token')})
if xml in (None, 401): if xml in (None, 401):
LOG.error('Could not download watch later list from plex.tv') LOG.error('Could not download watch later list from plex.tv')
return xbmcplugin.endOfDirectory(HANDLE, False) return xbmcplugin.endOfDirectory(int(argv[1]), False)
LOG.info('Displaying watch later plex.tv items') LOG.info('Displaying watch later plex.tv items')
xbmcplugin.setContent(HANDLE, 'movies') xbmcplugin.setContent(int(argv[1]), 'movies')
direct_paths = utils.settings('useDirectPaths') == '1' direct_paths = utils.settings('useDirectPaths') == '1'
for item in xml: for item in xml:
__build_item(item, direct_paths) __build_item(item, direct_paths)
xbmcplugin.endOfDirectory( xbmcplugin.endOfDirectory(
handle=HANDLE, handle=int(argv[1]),
cacheToDisc=utils.settings('enableTextureCache') == 'true') cacheToDisc=utils.settings('enableTextureCache') == 'true')
@ -692,16 +688,16 @@ def channels():
xml[0].attrib xml[0].attrib
except (ValueError, AttributeError, IndexError, TypeError): except (ValueError, AttributeError, IndexError, TypeError):
LOG.error('Could not download Plex Channels') LOG.error('Could not download Plex Channels')
return xbmcplugin.endOfDirectory(HANDLE, False) return xbmcplugin.endOfDirectory(int(argv[1]), False)
LOG.info('Displaying Plex Channels') LOG.info('Displaying Plex Channels')
xbmcplugin.setContent(HANDLE, 'files') xbmcplugin.setContent(int(argv[1]), 'files')
for method in v.SORT_METHODS_DIRECTORY: for method in v.SORT_METHODS_DIRECTORY:
xbmcplugin.addSortMethod(HANDLE, getattr(xbmcplugin, method)) xbmcplugin.addSortMethod(int(argv[1]), getattr(xbmcplugin, method))
for item in xml: for item in xml:
__build_folder(item) __build_folder(item)
xbmcplugin.endOfDirectory( xbmcplugin.endOfDirectory(
handle=HANDLE, handle=int(argv[1]),
cacheToDisc=utils.settings('enableTextureCache') == 'true') cacheToDisc=utils.settings('enableTextureCache') == 'true')
@ -718,7 +714,7 @@ def browse_plex(key=None, plex_section_id=None):
xml[0].attrib xml[0].attrib
except (ValueError, AttributeError, IndexError, TypeError): except (ValueError, AttributeError, IndexError, TypeError):
LOG.error('Could not browse to %s', key) LOG.error('Could not browse to %s', key)
return xbmcplugin.endOfDirectory(HANDLE, False) return xbmcplugin.endOfDirectory(int(argv[1]), False)
photos = False photos = False
movies = False movies = False
@ -757,45 +753,45 @@ def browse_plex(key=None, plex_section_id=None):
# Set the correct content type # Set the correct content type
if movies is True: if movies is True:
xbmcplugin.setContent(HANDLE, 'movies') xbmcplugin.setContent(int(argv[1]), 'movies')
sort_methods = v.SORT_METHODS_MOVIES sort_methods = v.SORT_METHODS_MOVIES
elif clips is True: elif clips is True:
xbmcplugin.setContent(HANDLE, 'movies') xbmcplugin.setContent(int(argv[1]), 'movies')
sort_methods = v.SORT_METHODS_CLIPS sort_methods = v.SORT_METHODS_CLIPS
elif photos is True: elif photos is True:
xbmcplugin.setContent(HANDLE, 'images') xbmcplugin.setContent(int(argv[1]), 'images')
sort_methods = v.SORT_METHODS_PHOTOS sort_methods = v.SORT_METHODS_PHOTOS
elif tvshows is True: elif tvshows is True:
xbmcplugin.setContent(HANDLE, 'tvshows') xbmcplugin.setContent(int(argv[1]), 'tvshows')
sort_methods = v.SORT_METHOD_TVSHOWS sort_methods = v.SORT_METHOD_TVSHOWS
elif episodes is True: elif episodes is True:
xbmcplugin.setContent(HANDLE, 'episodes') xbmcplugin.setContent(int(argv[1]), 'episodes')
sort_methods = v.SORT_METHODS_EPISODES sort_methods = v.SORT_METHODS_EPISODES
elif songs is True: elif songs is True:
xbmcplugin.setContent(HANDLE, 'songs') xbmcplugin.setContent(int(argv[1]), 'songs')
sort_methods = v.SORT_METHODS_SONGS sort_methods = v.SORT_METHODS_SONGS
elif artists is True: elif artists is True:
xbmcplugin.setContent(HANDLE, 'artists') xbmcplugin.setContent(int(argv[1]), 'artists')
sort_methods = v.SORT_METHODS_ARTISTS sort_methods = v.SORT_METHODS_ARTISTS
elif albums is True: elif albums is True:
xbmcplugin.setContent(HANDLE, 'albums') xbmcplugin.setContent(int(argv[1]), 'albums')
sort_methods = v.SORT_METHODS_ALBUMS sort_methods = v.SORT_METHODS_ALBUMS
elif musicvideos is True: elif musicvideos is True:
xbmcplugin.setContent(HANDLE, 'musicvideos') xbmcplugin.setContent(int(argv[1]), 'musicvideos')
sort_methods = v.SORT_METHODS_MOVIES sort_methods = v.SORT_METHODS_MOVIES
else: else:
xbmcplugin.setContent(HANDLE, 'files') xbmcplugin.setContent(int(argv[1]), 'files')
sort_methods = v.SORT_METHODS_DIRECTORY sort_methods = v.SORT_METHODS_DIRECTORY
for method in sort_methods: for method in sort_methods:
xbmcplugin.addSortMethod(HANDLE, getattr(xbmcplugin, method)) xbmcplugin.addSortMethod(int(argv[1]), getattr(xbmcplugin, method))
# Set the Kodi title for this view # Set the Kodi title for this view
title = xml.attrib.get('librarySectionTitle', xml.attrib.get('title1')) title = xml.attrib.get('librarySectionTitle', xml.attrib.get('title1'))
xbmcplugin.setPluginCategory(HANDLE, title) xbmcplugin.setPluginCategory(int(argv[1]), title)
xbmcplugin.endOfDirectory( xbmcplugin.endOfDirectory(
handle=HANDLE, handle=int(argv[1]),
cacheToDisc=utils.settings('enableTextureCache') == 'true') cacheToDisc=utils.settings('enableTextureCache') == 'true')
@ -812,7 +808,7 @@ def __build_folder(xml_element, plex_section_id=None):
listitem = ListItem(xml_element.attrib.get('title')) listitem = ListItem(xml_element.attrib.get('title'))
listitem.setArt({'thumb': xml_element.attrib.get('thumb'), listitem.setArt({'thumb': xml_element.attrib.get('thumb'),
'poster': xml_element.attrib.get('art')}) 'poster': xml_element.attrib.get('art')})
xbmcplugin.addDirectoryItem(handle=HANDLE, xbmcplugin.addDirectoryItem(handle=int(argv[1]),
url="%s?%s" % (url, urlencode(params)), url="%s?%s" % (url, urlencode(params)),
isFolder=True, isFolder=True,
listitem=listitem) listitem=listitem)
@ -838,7 +834,7 @@ def __build_item(xml_element, direct_paths):
url = api.path(direct_paths=direct_paths) url = api.path(direct_paths=direct_paths)
if api.resume_point(): if api.resume_point():
listitem.setProperty('resumetime', str(api.resume_point())) listitem.setProperty('resumetime', str(api.resume_point()))
xbmcplugin.addDirectoryItem(handle=HANDLE, xbmcplugin.addDirectoryItem(handle=int(argv[1]),
url=url, url=url,
listitem=listitem) listitem=listitem)
@ -847,20 +843,20 @@ def extras(plex_id):
""" """
Lists all extras for plex_id Lists all extras for plex_id
""" """
xbmcplugin.setContent(HANDLE, 'movies') xbmcplugin.setContent(int(argv[1]), 'movies')
xml = PF.GetPlexMetadata(plex_id) xml = PF.GetPlexMetadata(plex_id)
try: try:
xml[0].attrib xml[0].attrib
except (TypeError, IndexError, KeyError): except (TypeError, IndexError, KeyError):
xbmcplugin.endOfDirectory(HANDLE) xbmcplugin.endOfDirectory(int(argv[1]))
return return
for item in API(xml[0]).extras(): for item in API(xml[0]).extras():
api = API(item) api = API(item)
listitem = api.create_listitem() listitem = api.create_listitem()
xbmcplugin.addDirectoryItem(handle=HANDLE, xbmcplugin.addDirectoryItem(handle=int(argv[1]),
url=api.path(), url=api.path(),
listitem=listitem) listitem=listitem)
xbmcplugin.endOfDirectory(HANDLE) xbmcplugin.endOfDirectory(int(argv[1]))
def create_new_pms(): def create_new_pms():

View file

@ -206,8 +206,27 @@ def _write_playlist_to_file(playlist, xml):
text = '#EXTCPlayListM3U::M3U\n' text = '#EXTCPlayListM3U::M3U\n'
for element in xml: for element in xml:
api = API(element) api = API(element)
text += ('#EXTINF:%s,%s\n%s\n' append_season_episode = False
% (api.runtime(), api.title(), api.path())) if api.plex_type() == v.PLEX_TYPE_EPISODE:
_, show, season_id, episode_id = api.episode_data()
try:
season_id = int(season_id)
episode_id = int(episode_id)
except ValueError:
pass
else:
append_season_episode = True
if append_season_episode:
text += ('#EXTINF:%s,%s S%.2dE%.2d - %s\n%s\n'
% (api.runtime(), show, season_id, episode_id,
api.title(), api.path()))
else:
# Only append the TV show name
text += ('#EXTINF:%s,%s - %s\n%s\n'
% (api.runtime(), show, api.title(), api.path()))
else:
text += ('#EXTINF:%s,%s\n%s\n'
% (api.runtime(), api.title(), api.path()))
text += '\n' text += '\n'
text = text.encode(v.M3U_ENCODING, 'strict') text = text.encode(v.M3U_ENCODING, 'strict')
try: try:

View file

@ -85,14 +85,14 @@ MIN_DB_VERSION = '2.0.27'
# Database paths # Database paths
_DB_VIDEO_VERSION = { _DB_VIDEO_VERSION = {
17: 107, # Krypton 17: 107, # Krypton
18: 109 # Leia 18: 110 # Leia
} }
DB_VIDEO_PATH = try_decode(xbmc.translatePath( DB_VIDEO_PATH = try_decode(xbmc.translatePath(
"special://database/MyVideos%s.db" % _DB_VIDEO_VERSION[KODIVERSION])) "special://database/MyVideos%s.db" % _DB_VIDEO_VERSION[KODIVERSION]))
_DB_MUSIC_VERSION = { _DB_MUSIC_VERSION = {
17: 60, # Krypton 17: 60, # Krypton
18: 70 # Leia 18: 72 # Leia
} }
DB_MUSIC_PATH = try_decode(xbmc.translatePath( DB_MUSIC_PATH = try_decode(xbmc.translatePath(
"special://database/MyMusic%s.db" % _DB_MUSIC_VERSION[KODIVERSION])) "special://database/MyMusic%s.db" % _DB_MUSIC_VERSION[KODIVERSION]))