Merge branch 'hotfixes' into translations

This commit is contained in:
croneter 2018-05-13 16:16:27 +02:00
commit a2867d2806
17 changed files with 313 additions and 101 deletions

View file

@ -1,5 +1,5 @@
[![stable version](https://img.shields.io/badge/stable_version-1.8.18-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-1.8.18-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.0.20-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.0.22-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)
@ -55,6 +55,7 @@ Some people argue that PKC is 'hacky' because of the way it directly accesses th
- Support of Kodi 18 Leia (and Kodi 17 Krypton) - Support of Kodi 18 Leia (and 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/)
- [Plex Watch Later / Plex It!](https://support.plex.tv/hc/en-us/sections/200211783-Plex-It-) - [Plex Watch Later / Plex It!](https://support.plex.tv/hc/en-us/sections/200211783-Plex-It-)
- [Plex Companion](https://support.plex.tv/hc/en-us/sections/200276908-Plex-Companion): fling Plex media (or anything else) from other Plex devices to PlexKodiConnect - [Plex Companion](https://support.plex.tv/hc/en-us/sections/200276908-Plex-Companion): fling Plex media (or anything else) from other Plex devices to PlexKodiConnect
- [Plex Transcoding](https://support.plex.tv/hc/en-us/articles/200250377-Transcoding-Media) - [Plex Transcoding](https://support.plex.tv/hc/en-us/articles/200250377-Transcoding-Media)

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.0.20" provider-name="croneter"> <addon id="plugin.video.plexkodiconnect" name="PlexKodiConnect" version="2.0.22" 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,18 @@
<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.0.20 (beta only): <news>version 2.0.22 (beta only):
- Fix Recently Added for tv shows not working
- Fix PKC crashing on startup
version 2.0.21 (beta only):
- Fix TV show artwork Kodi native library (reset Kodi DB!)
- Cache missing posters and backgrounds/fanart on Kodi startup
- Add toggle to deactivate image caching during playback
- Increase timeout between syncing images
- Fix music database if new music is added in the background
version 2.0.20 (beta only):
- Fix missing episode poster in certain views. You will have to manually reset your Kodi database to benefit - Fix missing episode poster in certain views. You will have to manually reset your Kodi database to benefit
- Fix episode artwork sometimes not being complete - Fix episode artwork sometimes not being complete
- Fix IndexError for certain Plex channels - Fix IndexError for certain Plex channels

View file

@ -1,3 +1,14 @@
version 2.0.22 (beta only):
- Fix Recently Added for tv shows not working
- Fix PKC crashing on startup
version 2.0.21 (beta only):
- Fix TV show artwork Kodi native library (reset Kodi DB!)
- Cache missing posters and backgrounds/fanart on Kodi startup
- Add toggle to deactivate image caching during playback
- Increase timeout between syncing images
- Fix music database if new music is added in the background
version 2.0.20 (beta only): version 2.0.20 (beta only):
- Fix missing episode poster in certain views. You will have to manually reset your Kodi database to benefit - Fix missing episode poster in certain views. You will have to manually reset your Kodi database to benefit
- Fix episode artwork sometimes not being complete - Fix episode artwork sometimes not being complete

View file

@ -99,6 +99,9 @@ class Main():
elif mode == 'channels': elif mode == 'channels':
entrypoint.channels() entrypoint.channels()
elif mode == 'extras':
entrypoint.extras(plex_id=params.get('plex_id'))
elif mode == 'settings': elif mode == 'settings':
executebuiltin('Addon.OpenSettings(%s)' % v.ADDON_ID) executebuiltin('Addon.OpenSettings(%s)' % v.ADDON_ID)

View file

@ -43,12 +43,12 @@ msgstr ""
# Sync notification displayed if there is still artwork to be cached to Kodi # Sync notification displayed if there is still artwork to be cached to Kodi
msgctxt "#30006" msgctxt "#30006"
msgid "Caching %s images" msgid "Caching %s Plex images"
msgstr "" msgstr ""
# Sync notification displayed if syncing of major artwork is done # Sync notification displayed if syncing of major artwork is done
msgctxt "#30007" msgctxt "#30007"
msgid "Major image caching done" msgid "Plex image caching done"
msgstr "" msgstr ""
# PKC settings artwork: Enable notifications for artwork image sync # PKC settings artwork: Enable notifications for artwork image sync
@ -61,6 +61,16 @@ msgctxt "#30009"
msgid "Enable image caching during Kodi playback (restart Kodi!)" msgid "Enable image caching during Kodi playback (restart Kodi!)"
msgstr "" msgstr ""
# PKC settings - Artwork
msgctxt "#30010"
msgid "Approximate progress"
msgstr ""
# PKC settings - Artwork
msgctxt "#30011"
msgid "Plex artwork (posters and backgrounds) left to cache:"
msgstr ""
# Button text # Button text
msgctxt "#30012" msgctxt "#30012"
msgid "OK" msgid "OK"
@ -75,6 +85,11 @@ msgctxt "#30014"
msgid "Connection" msgid "Connection"
msgstr "" msgstr ""
# PKC settings - Artwork
msgctxt "#30015"
msgid "Movie and show FanartTV lookups left to do:"
msgstr ""
msgctxt "#30016" msgctxt "#30016"
msgid "Device Name" msgid "Device Name"
msgstr "" msgstr ""
@ -84,6 +99,16 @@ msgctxt "#30017"
msgid "Unauthorized for PMS" msgid "Unauthorized for PMS"
msgstr "" msgstr ""
# Sync notification displayed for the number of fanart.tv lookups left
msgctxt "#30018"
msgid "Checking FanartTV for %s items"
msgstr ""
# Sync notification displayed when FanartTV lookup is completed
msgctxt "#30019"
msgid "FanartTV lookup completed"
msgstr ""
# PKC settings category # PKC settings category
msgctxt "#30022" msgctxt "#30022"
msgid "Advanced" msgid "Advanced"
@ -407,7 +432,7 @@ msgstr ""
# PKC Settings - Artwork # PKC Settings - Artwork
msgctxt "#30512" msgctxt "#30512"
msgid "Force artwork caching" msgid "Cache all artwork for a smooth Kodi experience"
msgstr "" msgstr ""
# PKC Settings - Artwork # PKC Settings - Artwork
@ -487,7 +512,7 @@ msgstr ""
# PKC Settings - Advanced # PKC Settings - Advanced
msgctxt "#30535" msgctxt "#30535"
msgid "[COLOR yellow]Generate a new unique device Id (e.g. when cloning Kodi)[/COLOR]" msgid "Generate a new unique Plex device Id (e.g. to clone Kodi)"
msgstr "" msgstr ""
# PKC Settings - Connection # PKC Settings - Connection
@ -502,7 +527,7 @@ msgstr ""
# PKC Settings warning # PKC Settings warning
msgctxt "#30538" msgctxt "#30538"
msgid "Complete Re-Sync necessary" msgid "Manual complete reset of Kodi database necessary, see \"Advanced\""
msgstr "" msgstr ""
# PKC Settings - Artwork # PKC Settings - Artwork
@ -610,7 +635,7 @@ msgstr ""
# PKC Settings - Sync # PKC Settings - Sync
msgctxt "#39003" msgctxt "#39003"
msgid "Limit download sync threads (rec. for rpi: 1)" msgid "Number of simultaneous download threads"
msgstr "" msgstr ""
# PKC Settings - Plex # PKC Settings - Plex
@ -675,12 +700,12 @@ msgstr ""
# PKC Settings - Advanced # PKC Settings - Advanced
msgctxt "#39018" msgctxt "#39018"
msgid "[COLOR yellow]Repair local database (force update all content)[/COLOR]" msgid "Repair the Kodi database (force update all content)"
msgstr "" msgstr ""
# PKC Settings - Advanced # PKC Settings - Advanced
msgctxt "#39019" msgctxt "#39019"
msgid "[COLOR red]Partial or full reset of Database and PKC[/COLOR]" msgid "Reset the Kodi database and optionally reset PlexKodiConnect"
msgstr "" msgstr ""
# PKC Settings - Artwork # PKC Settings - Artwork

View file

@ -99,6 +99,35 @@ class API(object):
""" """
return self.item.get('ratingKey') return self.item.get('ratingKey')
def path(self, force_first_media=True):
"""
Returns a "fully qualified path": add-on paths or direct paths
depending on the current settings. Will NOT valide the playurl
Returns unicode or None if something went wrong.
"""
filename = self.file_path(force_first_media=force_first_media)
if not state.DIRECT_PATHS or self.plex_type() == v.PLEX_TYPE_CLIP:
if filename and '/' in filename:
filename = filename.rsplit('/', 1)
elif filename:
filename = filename.rsplit('\\', 1)
try:
filename = filename[1]
except (TypeError, IndexError):
filename = None
# Set plugin path and media flags using real filename
path = ('plugin://%s/?plex_id=%s&plex_type=%s&mode=play&filename=%s'
% (v.ADDON_TYPE[self.plex_type()],
self.plex_id(),
self.plex_type(),
filename))
else:
# Direct paths is set the Kodi way
path = self.validate_playurl(filename,
self.plex_type(),
omit_check=True)
return path
def path_and_plex_id(self): def path_and_plex_id(self):
""" """
Returns the Plex key such as '/library/metadata/246922' or None Returns the Plex key such as '/library/metadata/246922' or None
@ -655,6 +684,16 @@ class API(object):
answ['bitDepth'] = None answ['bitDepth'] = None
return answ return answ
def extras(self):
"""
Returns a list of XML etree elements for each extra, e.g. a trailer.
"""
answ = []
for extras in self.item.iterfind('Extras'):
for extra in extras:
answ.append(extra)
return answ
def trailer_id(self): def trailer_id(self):
""" """
Returns the ratingKey (plex_id) of the trailer or None Returns the ratingKey (plex_id) of the trailer or None

View file

@ -12,8 +12,8 @@ import requests
from xbmc import sleep, translatePath from xbmc import sleep, translatePath
from xbmcvfs import exists from xbmcvfs import exists
from utils import window, settings, language as lang, kodi_sql, try_encode, \ from utils import settings, language as lang, kodi_sql, try_encode, try_decode,\
thread_methods, dialog, exists_dir, try_decode thread_methods, dialog, exists_dir
import state import state
############################################################################### ###############################################################################
@ -69,7 +69,15 @@ class Image_Cache_Thread(Thread):
sleep(1000) sleep(1000)
continue continue
if isinstance(url, ArtworkSyncMessage): if isinstance(url, ArtworkSyncMessage):
if state.IMAGE_SYNC_NOTIFICATIONS: if url.artwork_counter is not None:
if url.artwork_counter == 0:
# Done caching, show this in the PKC settings, too
settings('caching_major_artwork', value=lang(30069))
LOG.info('Done caching major images!')
else:
settings('caching_major_artwork',
value=str(url.artwork_counter))
if url.message and state.IMAGE_SYNC_NOTIFICATIONS:
dialog('notification', dialog('notification',
heading=lang(29999), heading=lang(29999),
message=url.message, message=url.message,
@ -107,12 +115,12 @@ class Image_Cache_Thread(Thread):
'over-loaded. Sleep %s seconds before trying ' 'over-loaded. Sleep %s seconds before trying '
'again to download %s', 'again to download %s',
2**sleeptime, double_urldecode(url)) 2**sleeptime, double_urldecode(url))
sleep((2**sleeptime)*1000) sleep((2**sleeptime) * 1000)
sleeptime += 1 sleeptime += 1
continue continue
except Exception as e: except Exception as err:
LOG.error('Unknown exception for url %s: %s'. LOG.error('Unknown exception for url %s: %s'.
double_urldecode(url), e) double_urldecode(url), err)
import traceback import traceback
LOG.error("Traceback:\n%s", traceback.format_exc()) LOG.error("Traceback:\n%s", traceback.format_exc())
break break
@ -159,13 +167,25 @@ class Artwork():
connection.close() connection.close()
if not artworks_to_cache: if not artworks_to_cache:
LOG.info('Caching of major images to Kodi texture cache done') LOG.info('Caching of major images to Kodi texture cache done')
# Set to "None"
settings('caching_major_artwork', value=lang(30069))
return return
length = len(artworks_to_cache)
LOG.info('Caching has not been completed - caching %s major images', LOG.info('Caching has not been completed - caching %s major images',
len(artworks_to_cache)) length)
self.queue.put(ArtworkSyncMessage(lang(30006) % len(artworks_to_cache))) settings('caching_major_artwork', value=str(length))
for url in artworks_to_cache: # Caching %s Plex images
self.queue.put(ArtworkSyncMessage(message=lang(30006) % length,
artwork_counter=length))
for i, url in enumerate(artworks_to_cache):
self.queue.put(url[0]) self.queue.put(url[0])
self.queue.put(ArtworkSyncMessage(lang(30007))) if (length - i) % 10 == 0:
# Update the PKC settings for artwork caching progress
msg = ArtworkSyncMessage(artwork_counter=length - i)
self.queue.put(msg)
# Plex image caching done
self.queue.put(ArtworkSyncMessage(message=lang(30007),
artwork_counter=0))
def fullTextureCacheSync(self): def fullTextureCacheSync(self):
""" """
@ -323,5 +343,6 @@ class ArtworkSyncMessage(object):
""" """
Put in artwork queue to display the message as a Kodi notification Put in artwork queue to display the message as a Kodi notification
""" """
def __init__(self, message): def __init__(self, message=None, artwork_counter=None):
self.message = message self.message = message
self.artwork_counter = artwork_counter

View file

@ -2,13 +2,16 @@
############################################################################### ###############################################################################
from logging import getLogger from logging import getLogger
from xbmc import getInfoLabel, sleep, executebuiltin
from xbmcaddon import Addon from xbmcaddon import Addon
import xbmc
import xbmcplugin
import xbmcgui
import plexdb_functions as plexdb import plexdb_functions as plexdb
from utils import window, settings, dialog, language as lang from utils import window, settings, dialog, language as lang
from dialogs import context from dialogs import context
from PlexFunctions import delete_item_from_pms import PlexFunctions as PF
from PlexAPI import API
import playqueue as PQ import playqueue as PQ
import variables as v import variables as v
import state import state
@ -25,7 +28,8 @@ OPTIONS = {
# 'RemoveFav': lang(30406), # 'RemoveFav': lang(30406),
# 'RateSong': lang(30407), # 'RateSong': lang(30407),
'Transcode': lang(30412), 'Transcode': lang(30412),
'PMS_Play': lang(30415) # Use PMS to start playback 'PMS_Play': lang(30415), # Use PMS to start playback
'Extras': lang(30235)
} }
############################################################################### ###############################################################################
@ -53,17 +57,24 @@ class ContextMenu(object):
self.plex_id, self.plex_type) self.plex_id, self.plex_type)
if not self.plex_id: if not self.plex_id:
return return
xml = PF.GetPlexMetadata(self.plex_id)
try:
xml[0].attrib
except (TypeError, IndexError, KeyError):
self.api = None
else:
self.api = API(xml[0])
if self._select_menu(): if self._select_menu():
self._action_menu() self._action_menu()
if self._selected_option in (OPTIONS['Delete'], if self._selected_option in (OPTIONS['Delete'],
OPTIONS['Refresh']): OPTIONS['Refresh']):
LOG.info("refreshing container") LOG.info("refreshing container")
sleep(500) xbmc.sleep(500)
executebuiltin('Container.Refresh') xbmc.executebuiltin('Container.Refresh')
@staticmethod @staticmethod
def _get_plex_id(kodi_id, kodi_type): def _get_plex_id(kodi_id, kodi_type):
plex_id = getInfoLabel('ListItem.Property(plexid)') or None plex_id = xbmc.getInfoLabel('ListItem.Property(plexid)') or None
if not plex_id and kodi_id and kodi_type: if not plex_id and kodi_id and kodi_type:
with plexdb.Get_Plex_DB() as plexcursor: with plexdb.Get_Plex_DB() as plexcursor:
item = plexcursor.getItem_byKodiId(kodi_id, kodi_type) item = plexcursor.getItem_byKodiId(kodi_id, kodi_type)
@ -79,6 +90,8 @@ class ContextMenu(object):
""" """
options = [] options = []
# if user uses direct paths, give option to initiate playback via PMS # if user uses direct paths, give option to initiate playback via PMS
if self.api and self.api.extras():
options.append(OPTIONS['Extras'])
if state.DIRECT_PATHS and self.kodi_type in v.KODI_VIDEOTYPES: if state.DIRECT_PATHS and self.kodi_type in v.KODI_VIDEOTYPES:
options.append(OPTIONS['PMS_Play']) options.append(OPTIONS['PMS_Play'])
if self.kodi_type in v.KODI_VIDEOTYPES: if self.kodi_type in v.KODI_VIDEOTYPES:
@ -122,6 +135,8 @@ class ContextMenu(object):
self._PMS_play() self._PMS_play()
elif selected == OPTIONS['PMS_Play']: elif selected == OPTIONS['PMS_Play']:
self._PMS_play() self._PMS_play()
elif selected == OPTIONS['Extras']:
self._extras()
# elif selected == OPTIONS['Refresh']: # elif selected == OPTIONS['Refresh']:
# self.emby.refreshItem(self.item_id) # self.emby.refreshItem(self.item_id)
# elif selected == OPTIONS['AddFav']: # elif selected == OPTIONS['AddFav']:
@ -131,7 +146,8 @@ class ContextMenu(object):
# elif selected == OPTIONS['RateSong']: # elif selected == OPTIONS['RateSong']:
# self._rate_song() # self._rate_song()
elif selected == OPTIONS['Addon']: elif selected == OPTIONS['Addon']:
executebuiltin('Addon.OpenSettings(plugin.video.plexkodiconnect)') xbmc.executebuiltin(
'Addon.OpenSettings(plugin.video.plexkodiconnect)')
elif selected == OPTIONS['Delete']: elif selected == OPTIONS['Delete']:
self._delete_item() self._delete_item()
@ -146,7 +162,7 @@ class ContextMenu(object):
delete = False delete = False
if delete: if delete:
LOG.info("Deleting Plex item with id %s", self.plex_id) LOG.info("Deleting Plex item with id %s", self.plex_id)
if delete_item_from_pms(self.plex_id) is False: if PF.delete_item_from_pms(self.plex_id) is False:
dialog("ok", heading="{plex}", line1=lang(30414)) dialog("ok", heading="{plex}", line1=lang(30414))
def _PMS_play(self): def _PMS_play(self):
@ -161,4 +177,16 @@ class ContextMenu(object):
% (v.ADDON_TYPE[self.plex_type], % (v.ADDON_TYPE[self.plex_type],
self.plex_id, self.plex_id,
self.plex_type)) self.plex_type))
executebuiltin('RunPlugin(%s)' % handle) xbmc.executebuiltin('RunPlugin(%s)' % handle)
def _extras(self):
"""
Displays a list of elements for all the extras of the Plex element
"""
handle = ('plugin://plugin.video.plexkodiconnect?mode=extras&plex_id=%s'
% self.plex_id)
if xbmcgui.getCurrentWindowId() == 10025:
# Video Window
xbmc.executebuiltin('Container.Update(\"%s\")' % handle)
else:
xbmc.executebuiltin('ActivateWindow(videos, \"%s\")' % handle)

View file

@ -369,7 +369,7 @@ def getRecentEpisodes(viewid, mediatype, tagname, limit):
append_show_title = settings('RecentTvAppendShow') == 'true' append_show_title = settings('RecentTvAppendShow') == 'true'
append_sxxexx = settings('RecentTvAppendSeason') == 'true' append_sxxexx = 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
allshowsIds = list() allshowsIds = set()
params = { params = {
'sort': {'order': "descending", 'method': "dateadded"}, 'sort': {'order': "descending", 'method': "dateadded"},
'filter': {'operator': "is", 'field': "tag", 'value': "%s" % tagname}, 'filter': {'operator': "is", 'field': "tag", 'value': "%s" % tagname},
@ -841,6 +841,26 @@ def __build_item(xml_element):
listitem=listitem) listitem=listitem)
def extras(plex_id):
"""
Lists all extras for plex_id
"""
xbmcplugin.setContent(HANDLE, 'movies')
xml = GetPlexMetadata(plex_id)
try:
xml[0].attrib
except (TypeError, IndexError, KeyError):
xbmcplugin.endOfDirectory(HANDLE)
return
for item in API(xml[0]).extras():
api = API(item)
listitem = api.create_listitem()
xbmcplugin.addDirectoryItem(handle=HANDLE,
url=api.path(),
listitem=listitem)
xbmcplugin.endOfDirectory(HANDLE)
def enterPMS(): def enterPMS():
""" """
Opens dialogs for the user the plug in the PMS details Opens dialogs for the user the plug in the PMS details

View file

@ -852,7 +852,7 @@ class TVShows(Items):
# Set plugin path - do NOT use "intermediate" paths for the show # Set plugin path - do NOT use "intermediate" paths for the show
# as with direct paths! # as with direct paths!
filename = api.file_name(force_first_media=True) filename = api.file_name(force_first_media=True)
path = 'plugin://%s.tvshows/' % v.ADDON_ID path = 'plugin://%s.tvshows/%s/' % (v.ADDON_ID, series_id)
filename = ('%s?plex_id=%s&plex_type=%s&mode=play&filename=%s' filename = ('%s?plex_id=%s&plex_type=%s&mode=play&filename=%s'
% (path, itemid, v.PLEX_TYPE_EPISODE, filename)) % (path, itemid, v.PLEX_TYPE_EPISODE, filename))
playurl = filename playurl = filename

View file

@ -303,7 +303,11 @@ class KodiDBMethods(object):
# Add all new entries that haven't already been added # Add all new entries that haven't already been added
query = 'INSERT INTO %s VALUES (?, ?, ?)' % link_table query = 'INSERT INTO %s VALUES (?, ?, ?)' % link_table
for entry_id in entry_ids: for entry_id in entry_ids:
try:
self.cursor.execute(query, (entry_id, kodi_id, kodi_type)) self.cursor.execute(query, (entry_id, kodi_id, kodi_type))
except IntegrityError:
LOG.info('IntegrityError: skipping entry %s for table %s',
entry_id, link_table)
# Delete all outdated references in the link table. Also check whether # Delete all outdated references in the link table. Also check whether
# we need to delete orphaned entries in the master table # we need to delete orphaned entries in the master table
query = ''' query = '''

View file

@ -5,10 +5,12 @@ from Queue import Empty
from xbmc import sleep from xbmc import sleep
from utils import thread_methods from utils import thread_methods, settings, language as lang, dialog
import plexdb_functions as plexdb import plexdb_functions as plexdb
import itemtypes import itemtypes
from artwork import ArtworkSyncMessage
import variables as v import variables as v
import state
############################################################################### ###############################################################################
@ -63,6 +65,24 @@ class ThreadedProcessFanart(Thread):
sleep(200) sleep(200)
continue continue
if isinstance(item, ArtworkSyncMessage):
if item.artwork_counter is not None:
if item.artwork_counter == 0:
# Done caching, show this in the PKC settings, too
settings('fanarttv_lookups', value=lang(30069))
LOG.info('Done caching major images!')
else:
settings('fanarttv_lookups',
value=str(item.artwork_counter))
if item.message and state.IMAGE_SYNC_NOTIFICATIONS:
dialog('notification',
heading=lang(29999),
message=item.message,
icon='{plex}',
sound=False)
queue.task_done()
continue
LOG.debug('Get additional fanart for Plex id %s', item['plex_id']) LOG.debug('Get additional fanart for Plex id %s', item['plex_id'])
with getattr(itemtypes, with getattr(itemtypes,
v.ITEMTYPE_FROM_PLEXTYPE[item['plex_type']])() as item_type: v.ITEMTYPE_FROM_PLEXTYPE[item['plex_type']])() as item_type:

View file

@ -640,7 +640,6 @@ class LibrarySync(Thread):
self.updatelist self.updatelist
""" """
# Some logging, just in case. # Some logging, just in case.
LOG.debug("self.updatelist: %s", self.updatelist)
item_number = len(self.updatelist) item_number = len(self.updatelist)
if item_number == 0: if item_number == 0:
return return
@ -1376,6 +1375,8 @@ class LibrarySync(Thread):
missing_only=True False will start look-up for EVERY item missing_only=True False will start look-up for EVERY item
refresh=False True will force refresh all external fanart refresh=False True will force refresh all external fanart
""" """
if settings('FanartTV') == 'false':
return
with plexdb.Get_Plex_DB() as plex_db: with plexdb.Get_Plex_DB() as plex_db:
if missing_only: if missing_only:
with plexdb.Get_Plex_DB() as plex_db: with plexdb.Get_Plex_DB() as plex_db:
@ -1387,14 +1388,26 @@ class LibrarySync(Thread):
items.extend(plex_db.itemsByType(plex_type)) items.extend(plex_db.itemsByType(plex_type))
LOG.info('Trying to get ALL additional fanart for %s items', LOG.info('Trying to get ALL additional fanart for %s items',
len(items)) len(items))
if not items:
return
# Shuffle the list to not always start out identically # Shuffle the list to not always start out identically
shuffle(items) shuffle(items)
for item in items: # Checking FanartTV for %s items
self.fanartqueue.put(artwork.ArtworkSyncMessage(
message=lang(30018) % len(items), artwork_counter=len(items)))
for i, item in enumerate(items):
self.fanartqueue.put({ self.fanartqueue.put({
'plex_id': item['plex_id'], 'plex_id': item['plex_id'],
'plex_type': item['plex_type'], 'plex_type': item['plex_type'],
'refresh': refresh 'refresh': refresh
}) })
if (len(items) - i) % 10 == 0:
# Update the PKC settings for fanart.tv lookup
msg = artwork.ArtworkSyncMessage(artwork_counter=len(items) - i)
self.fanartqueue.put(msg)
# FanartTV lookup completed
self.fanartqueue.put(artwork.ArtworkSyncMessage(message=lang(30019),
artwork_counter=0))
def triage_lib_scans(self): def triage_lib_scans(self):
""" """
@ -1542,14 +1555,13 @@ class LibrarySync(Thread):
initial_sync_done = True initial_sync_done = True
kodi_db_version_checked = True kodi_db_version_checked = True
last_sync = utils.unix_timestamp() last_sync = utils.unix_timestamp()
self.sync_fanart()
self.fanartthread.start() self.fanartthread.start()
else: else:
LOG.error('Initial start-up full sync unsuccessful') LOG.error('Initial start-up full sync unsuccessful')
xbmc.executebuiltin('InhibitIdleShutdown(false)') xbmc.executebuiltin('InhibitIdleShutdown(false)')
window('plex_dbScan', clear=True) window('plex_dbScan', clear=True)
state.DB_SCAN = False state.DB_SCAN = False
if settings('FanartTV') == 'true':
self.sync_fanart()
elif not kodi_db_version_checked: elif not kodi_db_version_checked:
# Install sync was already done, don't force-show dialogs # Install sync was already done, don't force-show dialogs
@ -1583,10 +1595,9 @@ class LibrarySync(Thread):
if self.full_sync(): if self.full_sync():
initial_sync_done = True initial_sync_done = True
last_sync = utils.unix_timestamp() last_sync = utils.unix_timestamp()
if settings('FanartTV') == 'true':
self.sync_fanart()
LOG.info('Done initial sync on Kodi startup') LOG.info('Done initial sync on Kodi startup')
artwork.Artwork().cache_major_artwork() artwork.Artwork().cache_major_artwork()
self.sync_fanart()
self.fanartthread.start() self.fanartthread.start()
else: else:
LOG.info('Startup sync has not yet been successful') LOG.info('Startup sync has not yet been successful')

View file

@ -24,7 +24,13 @@ class PlaybackStarter(Thread):
""" """
@staticmethod @staticmethod
def _triage(item): def _triage(item):
try:
_, params = item.split('?', 1) _, params = item.split('?', 1)
except ValueError:
# E.g. other add-ons scanning for Extras folder
LOG.debug('Detected 3rd party add-on call - ignoring')
pickle_me(Playback_Successful())
return
params = dict(parse_qsl(params)) params = dict(parse_qsl(params))
mode = params.get('mode') mode = params.get('mode')
resolve = False if params.get('handle') == '-1' else True resolve = False if params.get('handle') == '-1' else True

View file

@ -119,7 +119,7 @@ class SubscriptionMgr(object):
self.server = "" self.server = ""
self.protocol = "http" self.protocol = "http"
self.port = "" self.port = ""
self.isplaying = False self.location = 'navigation'
# In order to be able to signal a stop at the end # In order to be able to signal a stop at the end
self.last_params = {} self.last_params = {}
self.lastplayers = {} self.lastplayers = {}
@ -144,7 +144,7 @@ class SubscriptionMgr(object):
Returns a timeline xml as str Returns a timeline xml as str
(xml containing video, audio, photo player state) (xml containing video, audio, photo player state)
""" """
self.isplaying = False self.location = 'navigation'
answ = str(XML) answ = str(XML)
timelines = { timelines = {
v.PLEX_PLAYLIST_TYPE_VIDEO: None, v.PLEX_PLAYLIST_TYPE_VIDEO: None,
@ -163,8 +163,8 @@ class SubscriptionMgr(object):
v.KODI_PLAYLIST_TYPE_FROM_PLEX_PLAYLIST_TYPE[typus]], v.KODI_PLAYLIST_TYPE_FROM_PLEX_PLAYLIST_TYPE[typus]],
typus) typus)
timelines[typus] = self._dict_to_xml(timeline) timelines[typus] = self._dict_to_xml(timeline)
location = 'fullScreenVideo' if self.isplaying else 'navigation' timelines.update({'command_id': '{command_id}',
timelines.update({'command_id': '{command_id}', 'location': location}) 'location': self.location})
return answ.format(**timelines) return answ.format(**timelines)
@staticmethod @staticmethod
@ -191,7 +191,8 @@ class SubscriptionMgr(object):
'type': ptype, 'type': ptype,
'state': 'stopped' 'state': 'stopped'
} }
self.isplaying = True if ptype in (v.PLEX_PLAYLIST_TYPE_VIDEO, v.PLEX_PLAYLIST_TYPE_PHOTO):
self.location = 'fullScreenVideo'
self.stop_sent_to_web = False self.stop_sent_to_web = False
pbmc_server = window('pms_server') pbmc_server = window('pms_server')
if pbmc_server: if pbmc_server:
@ -202,7 +203,6 @@ class SubscriptionMgr(object):
shuffle = '1' if info['shuffled'] else '0' shuffle = '1' if info['shuffled'] else '0'
mute = '1' if info['muted'] is True else '0' mute = '1' if info['muted'] is True else '0'
answ = { answ = {
'location': 'fullScreenVideo',
'controllable': CONTROLLABLE[ptype], 'controllable': CONTROLLABLE[ptype],
'protocol': self.protocol, 'protocol': self.protocol,
'address': self.server, 'address': self.server,

View file

@ -435,7 +435,9 @@ def wipe_database():
cursor.execute("DELETE FROM %s" % table_name) cursor.execute("DELETE FROM %s" % table_name)
connection.commit() connection.commit()
cursor.close() cursor.close()
# Reset the artwork sync status in the PKC settings
settings('caching_major_artwork', value=language(39310))
settings('fanarttv_lookups', value=language(39310))
# reset the install run flag # reset the install run flag
settings('SyncInstallRunDone', value="false") settings('SyncInstallRunDone', value="false")

View file

@ -29,17 +29,16 @@
<setting id="plexhome" label="Plex home in use" type="bool" default="" visible="false" /> <setting id="plexhome" label="Plex home in use" type="bool" default="" visible="false" />
<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" />
<setting type="sep" text=""/>
<setting type="lsep" label="39008" /> <setting type="lsep" label="39008" />
<setting id="plexCompanion" label="39004" type="bool" default="true" /> <setting id="plexCompanion" label="39004" type="bool" default="true" />
<setting id="deviceName" label="30016" type="text" visible="eq(-1,true)" default="PlexKodiConnect" subsetting="true" /> <setting id="deviceName" label="30016" type="text" visible="eq(-1,true)" default="PlexKodiConnect" subsetting="true" />
<setting id="companionPort" label="39005" type="number" default="3005" option="int" visible="eq(-2,true)" subsetting="true" /> <setting id="companionPort" label="39005" type="number" default="3005" option="int" visible="eq(-2,true)" subsetting="true" />
<setting id="companionUpdatePort" label="39078" type="number" default="32412" option="int" visible="eq(-3,true)" subsetting="true" /> <setting id="companionUpdatePort" label="39078" type="number" default="32412" option="int" visible="eq(-3,true)" subsetting="true" />
<setting type="sep" text=""/>
<setting type="lsep" label="39700" /> <setting type="lsep" label="39700" />
<setting id="enable_alexa" label="39701" type="bool" default="true"/> <setting id="enable_alexa" label="39701" type="bool" default="true"/>
<setting type="lsep" label="" />
<!-- Different settings that are not visible - to avoid warnings in the log --> <!-- Different settings that are not visible - to avoid warnings in the log -->
<setting id="skipContextMenu" type="bool" label="30520" default="false"/>
<setting id="plex_restricteduser" type="bool" default="false" visible="false"/> <setting id="plex_restricteduser" type="bool" default="false" visible="false"/>
<setting id="plex_allows_mediaDeletion" type="bool" default="true" visible="false"/> <setting id="plex_allows_mediaDeletion" type="bool" default="true" visible="false"/>
<setting id="companion_show_gdm_port_warning" type="bool" default="true" visible="false"/> <setting id="companion_show_gdm_port_warning" type="bool" default="true" visible="false"/>
@ -57,18 +56,18 @@
<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="dbSyncIndicator" label="30507" type="bool" default="true" /><!-- show syncing progress -->
<setting type="sep" /> <setting type="sep" />
<setting id="syncThreadNumber" type="slider" label="39003" default="10" option="int" range="1,1,20"/><!-- Limit download sync threads (recommended for rpi: 1) --> <setting id="fullSyncInterval" type="number" label="39053" default="60" option="int" />
<setting id="dbSyncScreensaver" type="bool" label="39062" default="false" /><!--Sync when screensaver is deactivated-->
<setting id="dbSyncIndicator" label="30507" type="bool" default="true" /><!-- show syncing progress -->
<setting id="syncThreadNumber" type="slider" label="39003" default="10" option="int" range="1,1,20"/><!-- Number of simultaneous download threads -->
<setting id="limitindex" type="number" label="30515" default="200" option="int" /><!-- Maximum items to request from the server at once --> <setting id="limitindex" type="number" label="30515" default="200" option="int" /><!-- Maximum items to request from the server at once -->
<setting type="sep" />
<setting type="lsep" label="39052" /><!-- Background Sync --> <setting type="lsep" label="39052" /><!-- Background Sync -->
<setting id="enableBackgroundSync" type="bool" label="39026" default="true" visible="true"/> <setting id="enableBackgroundSync" type="bool" label="39026" default="true" visible="true"/>
<setting id="backgroundsync_saftyMargin" type="slider" label="39051" default="5" option="int" range="5,1,300" visible="eq(-1,true)" subsetting="true" /> <setting id="backgroundsync_saftyMargin" type="slider" label="39051" default="5" option="int" range="5,1,300" visible="eq(-1,true)" subsetting="true" />
<setting id="fullSyncInterval" type="number" label="39053" default="60" option="int" /> <setting type="sep" />
<setting id="dbSyncScreensaver" type="bool" label="39062" default="false" /><!--Sync when screensaver is deactivated--> <setting type="lsep" label="30538" /><!-- Manual complete reset of Kodi database necessary, see "Advanced" -->
<setting type="lsep" label="30538" /><!-- Complete Re-Sync necessary -->
<setting id="indicate_media_versions" type="bool" label="39719" default="false" /><!-- Replace user ratings with number of versions --> <setting id="indicate_media_versions" type="bool" label="39719" default="false" /><!-- Replace user ratings with number of versions -->
<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 -->
@ -77,6 +76,7 @@
<setting id="kodiplextimeoffset" type="number" label="Time difference in seconds (Koditime - Plextime)" default="0" visible="false" option="int" /> <setting id="kodiplextimeoffset" type="number" label="Time difference in seconds (Koditime - Plextime)" default="0" visible="false" option="int" />
<setting id="themoviedbAPIKey" type="text" default="19c90103adb9e98f2172c6a6a3d85dc4" visible="false"/> <setting id="themoviedbAPIKey" type="text" default="19c90103adb9e98f2172c6a6a3d85dc4" visible="false"/>
<setting id="FanArtTVAPIKey" type="text" default="639191cb0774661597f28a47e7e2bad5" visible="false"/> <setting id="FanArtTVAPIKey" type="text" default="639191cb0774661597f28a47e7e2bad5" visible="false"/>
<setting id="syncEmptyShows" type="bool" label="30508" default="false" visible="false"/>
</category> </category>
<category label="39057"><!-- Customize Paths --> <category label="39057"><!-- Customize Paths -->
@ -94,15 +94,11 @@
</category> </category>
<category label="30516"><!-- Playback --> <category label="30516"><!-- Playback -->
<setting type="sep" />
<setting id="enableCinema" type="bool" label="30518" default="false" /> <setting id="enableCinema" type="bool" label="30518" default="false" />
<setting id="askCinema" type="bool" label="30519" default="false" visible="eq(-1,true)" subsetting="true" /> <setting id="askCinema" type="bool" label="30519" default="false" visible="eq(-1,true)" subsetting="true" />
<setting id="trailerNumber" type="slider" label="39000" default="3" visible="eq(-2,true)" range="1,1,15" option="int" /> <setting id="trailerNumber" type="slider" label="39000" default="3" visible="eq(-2,true)" range="1,1,15" option="int" />
<setting id="pickPlexSubtitles" type="bool" label="39075" default="true" /> <setting id="pickPlexSubtitles" type="bool" label="39075" default="true" />
<setting id="ignoreSpecialsNextEpisodes" type="bool" label="30527" default="false" /> <setting id="ignoreSpecialsNextEpisodes" type="bool" label="30527" default="false" />
<setting id="offerDelete" type="bool" label="30114" default="false" visible="false"/>
<setting id="deleteTV" type="bool" label="30115" visible="eq(-1,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" visible="false"/> <setting id="resumeJumpBack" type="slider" label="30521" default="10" range="0,1,120" option="int" visible="false"/>
<setting type="sep" /> <setting type="sep" />
<setting id="playType" type="enum" label="30002" values="Direct Play (default)|Direct Stream|Force Transcode" default="0" /> <setting id="playType" type="enum" label="30002" values="Direct Play (default)|Direct Stream|Force Transcode" default="0" />
@ -112,22 +108,31 @@
<setting id="transcodeHi10P" type="bool" label="39063" default="false"/> <setting id="transcodeHi10P" type="bool" label="39063" default="false"/>
<setting id="audioBoost" type="slider" label="39001" default="0" range="0,10,100" option="int"/> <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="failedCount" type="number" visible="false" default="0" /> <setting id="force_transcode_pix" type="bool" label="30545" default="false" />
<setting id="networkCreds" type="text" visible="false" default="" />
<setting id="bestQuality" type="bool" label="30541" default="false" /> <setting id="bestQuality" type="bool" label="30541" default="false" />
<setting id="bestTrailer" type="bool" label="30542" default="true" /> <setting id="bestTrailer" type="bool" label="30542" default="true" />
<setting id="force_transcode_pix" type="bool" label="30545" default="false" /> <setting type="sep" />
<setting id="offerDelete" type="bool" label="30114" default="false" visible="false"/>
<setting id="deleteTV" type="bool" label="30115" visible="eq(-1,true)" default="false" subsetting="true" />
<setting id="deleteMovies" type="bool" label="30116" visible="eq(-2,true)" default="false" subsetting="true" />
<setting id="skipContextMenu" type="bool" label="30520" default="false"/>
<setting id="kodi_video_cache" type="number" visible="false" default="20971520" /> <setting id="kodi_video_cache" type="number" visible="false" default="20971520" />
<setting id="warned_setting_videoplayer.autoplaynextitem" type="bool" visible="false" default="false" /> <setting id="warned_setting_videoplayer.autoplaynextitem" type="bool" visible="false" default="false" />
<setting id="failedCount" type="number" visible="false" default="0" />
<setting id="networkCreds" type="text" visible="false" default="" />
</category> </category>
<category label="30544"><!-- artwork --> <category label="30544"><!-- artwork -->
<setting id="enableTextureCache" label="30512" type="bool" default="true" /> <!-- Force Artwork Caching --> <setting id="enableTextureCache" label="30512" type="bool" default="true" /> <!-- Cache all artwork for a smooth Kodi experience -->
<setting id="FanartTV" label="30539" type="bool" default="false" /><!-- Download additional art from FanArtTV --> <setting id="FanartTV" label="30539" type="bool" default="false" /><!-- Download additional art from FanArtTV -->
<setting label="39222" type="action" action="RunPlugin(plugin://plugin.video.plexkodiconnect/?mode=fanart)" option="close" visible="eq(-1,true)" subsetting="true" /> <!-- Look for missing fanart on FanartTV now --> <setting label="39222" type="action" action="RunPlugin(plugin://plugin.video.plexkodiconnect/?mode=fanart)" option="close" visible="eq(-1,true)" subsetting="true" /> <!-- Look for missing fanart on FanartTV now -->
<setting id="imageSyncNotifications" label="30008" type="bool" default="true" /><!-- Enable notifications for image caching --> <setting id="imageSyncNotifications" label="30008" type="bool" default="true" /><!-- Enable notifications for image caching -->
<setting id="imageSyncDuringPlayback" label="30009" type="bool" default="true" /><!-- Enable image caching during Kodi playback (restart Kodi!) --> <setting id="imageSyncDuringPlayback" label="30009" type="bool" default="true" /><!-- Enable image caching during Kodi playback (restart Kodi!) -->
<setting label="39020" type="action" action="RunPlugin(plugin://plugin.video.plexkodiconnect/?mode=texturecache)" option="close" /> <!-- Cache all images to Kodi texture cache now --> <setting label="39020" type="action" action="RunPlugin(plugin://plugin.video.plexkodiconnect/?mode=texturecache)" option="close" /> <!-- Cache all images to Kodi texture cache now -->
<setting type="sep" />
<setting type="lsep" label="30010" /><!-- Approximate progress -->
<setting id="caching_major_artwork" label="30011" type="text" default="$ADDON[plugin.video.plexkodiconnect 39310]" enable="false" visible="eq(-8,true)"/><!-- Plex artwork (posters and backgrounds) left to cache: -->
<setting id="fanarttv_lookups" label="30015" type="text" default="$ADDON[plugin.video.plexkodiconnect 39310]" enable="false" visible="eq(-8,true)"/><!-- Movie and show FanartTV lookups left to do: -->
</category> </category>
<!-- <!--
<category label="30235" visible="false"> <category label="30235" visible="false">
@ -141,8 +146,8 @@
--> -->
<category label="39073"><!-- Appearance Tweaks --> <category label="39073"><!-- Appearance Tweaks -->
<setting id="fetch_pms_item_number" label="39077" type="number" default="25" option="int" /> <setting id="fetch_pms_item_number" label="39077" type="number" default="50" option="int" />
<setting id="forceReloadSkinOnPlaybackStop" type="bool" label="39065" default="false" /><!-- Force-refresh Kodi skin on stopping playback --> <setting type="sep" />
<setting type="lsep" label="39074" /><!-- TV Shows --> <setting type="lsep" label="39074" /><!-- TV Shows -->
<setting id="OnDeckTVextended" type="bool" label="39058" default="true" /><!-- Extend Plex TV Series "On Deck" view to all shows --> <setting id="OnDeckTVextended" type="bool" label="39058" default="true" /><!-- Extend Plex TV Series "On Deck" view to all shows -->
<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-->
@ -150,15 +155,20 @@
<setting id="TVShowWatched" type="bool" label="39064" default="true" /><!--Recently Added: Also show already watched episodes--> <setting id="TVShowWatched" type="bool" label="39064" default="true" /><!--Recently Added: Also show already watched episodes-->
<setting id="RecentTvAppendShow" type="bool" label="39059" default="false" /><!--Recently added: Append show title to episode--> <setting id="RecentTvAppendShow" type="bool" label="39059" default="false" /><!--Recently added: Append show title to episode-->
<setting id="RecentTvAppendSeason" type="bool" label="39060" default="false" /><!--Recently Added: Append season- and episode-number SxxExx--> <setting id="RecentTvAppendSeason" type="bool" label="39060" default="false" /><!--Recently Added: Append season- and episode-number SxxExx-->
<setting type="sep" />
<setting type="lsep" label="30302" /><!-- Movies --> <setting type="lsep" label="30302" /><!-- Movies -->
<setting id="MovieShowWatched" type="bool" label="39066" default="true" /><!--Recently Added: Also show already watched episodes--> <setting id="MovieShowWatched" type="bool" label="39066" default="true" /><!--Recently Added: Also show already watched episodes-->
<setting type="sep" />
<setting type="lsep" label="30022" /><!-- Advanced -->
<setting id="forceReloadSkinOnPlaybackStop" type="bool" label="39065" default="false" /><!-- Force-refresh Kodi skin on stopping playback -->
</category> </category>
<category label="30022"><!-- Advanced --> <category label="30022"><!-- Advanced -->
<setting id="startupDelay" type="number" label="30529" default="0" option="int" /> <setting id="startupDelay" type="number" label="30529" default="0" option="int" />
<setting label="39018" type="action" action="RunPlugin(plugin://plugin.video.plexkodiconnect/?mode=repair)" option="close" /> <!-- Repair local database (force update all content) --> <setting label="[COLOR yellow]$ADDON[plugin.video.plexkodiconnect 39018][/COLOR]" type="action" action="RunPlugin(plugin://plugin.video.plexkodiconnect/?mode=repair)" option="close" /> <!-- Repair the Kodi database (force update all content) -->
<setting label="30535" type="action" action="RunPlugin(plugin://plugin.video.plexkodiconnect?mode=deviceid)" /><!-- Reset device id uuid --> <setting label="[COLOR yellow]$ADDON[plugin.video.plexkodiconnect 30535][/COLOR]" type="action" action="RunPlugin(plugin://plugin.video.plexkodiconnect?mode=deviceid)" /><!-- Generate a new unique Plex device Id (e.g. to clone Kodi) -->
<setting type="sep" />
<setting type="lsep" label="39049" /><!-- Nothing works? Try a full reset --> <setting type="lsep" label="39049" /><!-- Nothing works? Try a full reset -->
<setting label="39019" type="action" action="RunPlugin(plugin://plugin.video.plexkodiconnect/?mode=reset)" option="close" /> <!-- Partial or full reset of Database and PKC --> <setting label="[COLOR red]$ADDON[plugin.video.plexkodiconnect 39019][/COLOR]" type="action" action="RunPlugin(plugin://plugin.video.plexkodiconnect/?mode=reset)" option="close" /> <!-- Reset the Kodi database and optionally reset PlexKodiConnect -->
</category> </category>
</settings> </settings>