Merge branch 'beta-version'
This commit is contained in:
commit
92f3a9fd63
16 changed files with 141 additions and 80 deletions
|
@ -1,5 +1,5 @@
|
||||||
[![stable version](https://img.shields.io/badge/stable_version-2.1.3-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.3-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.6-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.7-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)
|
||||||
|
|
11
addon.xml
11
addon.xml
|
@ -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.6" provider-name="croneter">
|
<addon id="plugin.video.plexkodiconnect" name="PlexKodiConnect" version="2.2.7" 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,14 @@
|
||||||
<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.6 (beta only):
|
<news>version 2.2.7 (beta only):
|
||||||
|
- Allow to only sync specific Plex or Kodi playlists
|
||||||
|
- Don't show artwork sync progress, reduce setting-writes
|
||||||
|
- Fix playback sometimes not starting up
|
||||||
|
- Use __future__ for contextmenu.py
|
||||||
|
- Fix imports
|
||||||
|
|
||||||
|
version 2.2.6 (beta only):
|
||||||
- Fix default settings string, only show in English, hopefully fixes PKC loosing its settings
|
- Fix default settings string, only show in English, hopefully fixes PKC loosing its settings
|
||||||
|
|
||||||
version 2.2.5 (beta only):
|
version 2.2.5 (beta only):
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
version 2.2.7 (beta only):
|
||||||
|
- Allow to only sync specific Plex or Kodi playlists
|
||||||
|
- Don't show artwork sync progress, reduce setting-writes
|
||||||
|
- Fix playback sometimes not starting up
|
||||||
|
- Use __future__ for contextmenu.py
|
||||||
|
- Fix imports
|
||||||
|
|
||||||
version 2.2.6 (beta only):
|
version 2.2.6 (beta only):
|
||||||
- Fix default settings string, only show in English, hopefully fixes PKC loosing its settings
|
- Fix default settings string, only show in English, hopefully fixes PKC loosing its settings
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
from sys import listitem
|
from sys import listitem
|
||||||
from urllib import urlencode
|
from urllib import urlencode
|
||||||
|
|
||||||
|
|
|
@ -169,9 +169,9 @@ class Main():
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def deviceid():
|
def deviceid():
|
||||||
deviceId_old = pickler.pickl_window('plex_client_Id')
|
deviceId_old = pickler.pickl_window('plex_client_Id')
|
||||||
from clientinfo import getDeviceId
|
from resources.lib import clientinfo
|
||||||
try:
|
try:
|
||||||
deviceId = getDeviceId(reset=True)
|
deviceId = clientinfo.getDeviceId(reset=True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.error('Failed to generate a new device Id: %s' % e)
|
log.error('Failed to generate a new device Id: %s' % e)
|
||||||
utils.dialog('ok', utils.lang(29999), utils.lang(33032))
|
utils.dialog('ok', utils.lang(29999), utils.lang(33032))
|
||||||
|
|
|
@ -113,11 +113,21 @@ msgctxt "#30020"
|
||||||
msgid "Sync Plex playlists"
|
msgid "Sync Plex playlists"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
# PKC settings sync options
|
||||||
|
msgctxt "#30021"
|
||||||
|
msgid "Only sync specific Plex playlists to Kodi"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
# PKC settings category
|
# PKC settings category
|
||||||
msgctxt "#30022"
|
msgctxt "#30022"
|
||||||
msgid "Advanced"
|
msgid "Advanced"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
# PKC settings sync options
|
||||||
|
msgctxt "#30023"
|
||||||
|
msgid "Only sync specific Kodi playlists to Plex"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgctxt "#30024"
|
msgctxt "#30024"
|
||||||
msgid "Username"
|
msgid "Username"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -126,6 +136,16 @@ msgctxt "#30025"
|
||||||
msgid "Display message if PMS goes offline"
|
msgid "Display message if PMS goes offline"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
# PKC settings sync options
|
||||||
|
msgctxt "#30026"
|
||||||
|
msgid "Prefix in Plex playlist name to trigger sync"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
# PKC settings sync options
|
||||||
|
msgctxt "#30027"
|
||||||
|
msgid "Prefix in Kodi playlist name to trigger sync"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgctxt "#30030"
|
msgctxt "#30030"
|
||||||
msgid "Port Number"
|
msgid "Port Number"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
|
@ -51,8 +51,6 @@ class Image_Cache_Thread(Thread):
|
||||||
suspended = self.suspended
|
suspended = self.suspended
|
||||||
queue = self.queue
|
queue = self.queue
|
||||||
sleep_between = self.sleep_between
|
sleep_between = self.sleep_between
|
||||||
counter = 0
|
|
||||||
set_zero = False
|
|
||||||
while not stopped():
|
while not stopped():
|
||||||
# In the event the server goes offline
|
# In the event the server goes offline
|
||||||
while suspended():
|
while suspended():
|
||||||
|
@ -66,14 +64,8 @@ class Image_Cache_Thread(Thread):
|
||||||
try:
|
try:
|
||||||
url = queue.get(block=False)
|
url = queue.get(block=False)
|
||||||
except Empty:
|
except Empty:
|
||||||
if not set_zero and not xbmc.getCondVisibility(
|
|
||||||
'Window.IsVisible(DialogAddonSettings.xml)'):
|
|
||||||
# Avoid saving '0' all the time
|
|
||||||
set_zero = True
|
|
||||||
utils.settings('caching_artwork_count', value='0')
|
|
||||||
xbmc.sleep(1000)
|
xbmc.sleep(1000)
|
||||||
continue
|
continue
|
||||||
set_zero = False
|
|
||||||
if isinstance(url, ArtworkSyncMessage):
|
if isinstance(url, ArtworkSyncMessage):
|
||||||
if state.IMAGE_SYNC_NOTIFICATIONS:
|
if state.IMAGE_SYNC_NOTIFICATIONS:
|
||||||
utils.dialog('notification',
|
utils.dialog('notification',
|
||||||
|
@ -125,13 +117,6 @@ class Image_Cache_Thread(Thread):
|
||||||
# We did not even get a timeout
|
# We did not even get a timeout
|
||||||
break
|
break
|
||||||
queue.task_done()
|
queue.task_done()
|
||||||
# Update the caching state in the PKC settings.
|
|
||||||
counter += 1
|
|
||||||
if (counter > 20 and not xbmc.getCondVisibility(
|
|
||||||
'Window.IsVisible(DialogAddonSettings.xml)')):
|
|
||||||
counter = 0
|
|
||||||
utils.settings('caching_artwork_count',
|
|
||||||
value=str(queue.qsize()))
|
|
||||||
# Sleep for a bit to reduce CPU strain
|
# Sleep for a bit to reduce CPU strain
|
||||||
xbmc.sleep(sleep_between)
|
xbmc.sleep(sleep_between)
|
||||||
LOG.info("---===### Stopped Image_Cache_Thread ###===---")
|
LOG.info("---===### Stopped Image_Cache_Thread ###===---")
|
||||||
|
@ -172,13 +157,10 @@ 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"
|
|
||||||
utils.settings('caching_artwork_count', value=utils.lang(30069))
|
|
||||||
return
|
return
|
||||||
length = len(artworks_to_cache)
|
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',
|
||||||
length)
|
length)
|
||||||
utils.settings('caching_artwork_count', value=str(length))
|
|
||||||
# Caching %s Plex images
|
# Caching %s Plex images
|
||||||
self.queue.put(ArtworkSyncMessage(utils.lang(30006) % length))
|
self.queue.put(ArtworkSyncMessage(utils.lang(30006) % length))
|
||||||
for i, url in enumerate(artworks_to_cache):
|
for i, url in enumerate(artworks_to_cache):
|
||||||
|
|
|
@ -31,7 +31,7 @@ def choose_pms_server():
|
||||||
"""
|
"""
|
||||||
LOG.info("Choosing PMS server requested, starting")
|
LOG.info("Choosing PMS server requested, starting")
|
||||||
|
|
||||||
import initialsetup
|
from . import initialsetup
|
||||||
setup = initialsetup.InitialSetup()
|
setup = initialsetup.InitialSetup()
|
||||||
server = setup.pick_pms(showDialog=True)
|
server = setup.pick_pms(showDialog=True)
|
||||||
if server is None:
|
if server is None:
|
||||||
|
@ -46,9 +46,8 @@ def choose_pms_server():
|
||||||
if not _log_out():
|
if not _log_out():
|
||||||
return
|
return
|
||||||
|
|
||||||
from utils import wipe_database
|
|
||||||
# Wipe Kodi and Plex database as well as playlists and video nodes
|
# Wipe Kodi and Plex database as well as playlists and video nodes
|
||||||
wipe_database()
|
utils.wipe_database()
|
||||||
|
|
||||||
# Log in again
|
# Log in again
|
||||||
_log_in()
|
_log_in()
|
||||||
|
@ -81,7 +80,7 @@ def toggle_plex_tv_sign_in():
|
||||||
utils.plex_command('PLEX_USERNAME', '')
|
utils.plex_command('PLEX_USERNAME', '')
|
||||||
else:
|
else:
|
||||||
LOG.info('Login to plex.tv')
|
LOG.info('Login to plex.tv')
|
||||||
import initialsetup
|
from . import initialsetup
|
||||||
initialsetup.InitialSetup().plex_tv_sign_in()
|
initialsetup.InitialSetup().plex_tv_sign_in()
|
||||||
utils.dialog('notification',
|
utils.dialog('notification',
|
||||||
utils.lang(29999),
|
utils.lang(29999),
|
||||||
|
@ -180,10 +179,9 @@ def switch_plex_user():
|
||||||
if not _log_out():
|
if not _log_out():
|
||||||
return
|
return
|
||||||
# First remove playlists of old user
|
# First remove playlists of old user
|
||||||
from utils import delete_playlists, delete_nodes
|
utils.delete_playlists()
|
||||||
delete_playlists()
|
|
||||||
# Remove video nodes
|
# Remove video nodes
|
||||||
delete_nodes()
|
utils.delete_nodes()
|
||||||
_log_in()
|
_log_in()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,9 @@ STATE_SETTINGS = {
|
||||||
'forceReloadSkinOnPlaybackStop': 'FORCE_RELOAD_SKIN',
|
'forceReloadSkinOnPlaybackStop': 'FORCE_RELOAD_SKIN',
|
||||||
'fetch_pms_item_number': 'FETCH_PMS_ITEM_NUMBER',
|
'fetch_pms_item_number': 'FETCH_PMS_ITEM_NUMBER',
|
||||||
'imageSyncNotifications': 'IMAGE_SYNC_NOTIFICATIONS',
|
'imageSyncNotifications': 'IMAGE_SYNC_NOTIFICATIONS',
|
||||||
'enablePlaylistSync': 'SYNC_PLAYLISTS'
|
'enablePlaylistSync': 'SYNC_PLAYLISTS',
|
||||||
|
'syncSpecificPlexPlaylists': 'SYNC_SPECIFIC_PLEX_PLAYLISTS',
|
||||||
|
'syncSpecificKodiPlaylists': 'SYNC_SPECIFIC_KODI_PLAYLISTS'
|
||||||
}
|
}
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
|
@ -48,8 +48,6 @@ class ThreadedProcessFanart(Thread):
|
||||||
stopped = self.stopped
|
stopped = self.stopped
|
||||||
suspended = self.suspended
|
suspended = self.suspended
|
||||||
queue = self.queue
|
queue = self.queue
|
||||||
counter = 0
|
|
||||||
set_zero = False
|
|
||||||
while not stopped():
|
while not stopped():
|
||||||
# In the event the server goes offline
|
# In the event the server goes offline
|
||||||
while suspended():
|
while suspended():
|
||||||
|
@ -63,14 +61,8 @@ class ThreadedProcessFanart(Thread):
|
||||||
try:
|
try:
|
||||||
item = queue.get(block=False)
|
item = queue.get(block=False)
|
||||||
except Empty:
|
except Empty:
|
||||||
if not set_zero and not xbmc.getCondVisibility(
|
|
||||||
'Window.IsVisible(DialogAddonSettings.xml)'):
|
|
||||||
# Avoid saving '0' all the time
|
|
||||||
set_zero = True
|
|
||||||
utils.settings('fanarttv_lookups', value='0')
|
|
||||||
xbmc.sleep(200)
|
xbmc.sleep(200)
|
||||||
continue
|
continue
|
||||||
set_zero = False
|
|
||||||
if isinstance(item, artwork.ArtworkSyncMessage):
|
if isinstance(item, artwork.ArtworkSyncMessage):
|
||||||
if state.IMAGE_SYNC_NOTIFICATIONS:
|
if state.IMAGE_SYNC_NOTIFICATIONS:
|
||||||
utils.dialog('notification',
|
utils.dialog('notification',
|
||||||
|
@ -90,11 +82,5 @@ class ThreadedProcessFanart(Thread):
|
||||||
LOG.debug('Done getting fanart for Plex id %s', item['plex_id'])
|
LOG.debug('Done getting fanart for Plex id %s', item['plex_id'])
|
||||||
with plexdb.Get_Plex_DB() as plex_db:
|
with plexdb.Get_Plex_DB() as plex_db:
|
||||||
plex_db.set_fanart_synched(item['plex_id'])
|
plex_db.set_fanart_synched(item['plex_id'])
|
||||||
# Update the caching state in the PKC settings. Avoid saving '0'
|
|
||||||
counter += 1
|
|
||||||
if (counter > 20 and not xbmc.getCondVisibility(
|
|
||||||
'Window.IsVisible(DialogAddonSettings.xml)')):
|
|
||||||
counter = 0
|
|
||||||
utils.settings('fanarttv_lookups', value=str(queue.qsize()))
|
|
||||||
queue.task_done()
|
queue.task_done()
|
||||||
LOG.debug("---===### Stopped FanartSync ###===---")
|
LOG.debug("---===### Stopped FanartSync ###===---")
|
||||||
|
|
|
@ -63,8 +63,16 @@ def delete_plex_playlist(playlist):
|
||||||
entry in the Plex playlist table.
|
entry in the Plex playlist table.
|
||||||
Returns None or raises PL.PlaylistError
|
Returns None or raises PL.PlaylistError
|
||||||
"""
|
"""
|
||||||
LOG.debug('Deleting playlist from PMS: %s', playlist)
|
if (state.SYNC_SPECIFIC_KODI_PLAYLISTS and
|
||||||
PL.delete_playlist_from_pms(playlist)
|
not sync_kodi_playlist(playlist.kodi_path)):
|
||||||
|
# We might have already synced this playlist BEFORE user chose to only
|
||||||
|
# sync specific playlists. Let's NOT delete all those playlists.
|
||||||
|
# However, delete it from our database of synced playlists.
|
||||||
|
LOG.debug('Not deleting playlist since user chose not to sync: %s',
|
||||||
|
playlist)
|
||||||
|
else:
|
||||||
|
LOG.debug('Deleting playlist from PMS: %s', playlist)
|
||||||
|
PL.delete_playlist_from_pms(playlist)
|
||||||
update_plex_table(playlist, delete=True)
|
update_plex_table(playlist, delete=True)
|
||||||
|
|
||||||
|
|
||||||
|
@ -76,12 +84,20 @@ def create_kodi_playlist(plex_id=None, updated_at=None):
|
||||||
created in any case (not replaced). Thus make sure that the "same" playlist
|
created in any case (not replaced). Thus make sure that the "same" playlist
|
||||||
is deleted from both disk and the Plex database.
|
is deleted from both disk and the Plex database.
|
||||||
Returns the playlist or raises PL.PlaylistError
|
Returns the playlist or raises PL.PlaylistError
|
||||||
|
|
||||||
|
Be aware that user settings will be checked whether this Plex playlist
|
||||||
|
should actually indeed be synced
|
||||||
"""
|
"""
|
||||||
xml = PL.get_PMS_playlist(PL.Playlist_Object(), playlist_id=plex_id)
|
xml = PL.get_PMS_playlist(PL.Playlist_Object(), playlist_id=plex_id)
|
||||||
if xml is None:
|
if xml is None:
|
||||||
LOG.error('Could not get Plex playlist %s', plex_id)
|
LOG.error('Could not get Plex playlist %s', plex_id)
|
||||||
raise PL.PlaylistError('Could not get Plex playlist %s' % plex_id)
|
raise PL.PlaylistError('Could not get Plex playlist %s' % plex_id)
|
||||||
api = API(xml)
|
api = API(xml)
|
||||||
|
if state.SYNC_SPECIFIC_PLEX_PLAYLISTS:
|
||||||
|
prefix = utils.settings('syncSpecificPlexPlaylistsPrefix').lower()
|
||||||
|
if api.title() and not api.title().lower().startswith(prefix):
|
||||||
|
LOG.debug('User chose to not sync playlist %s', api.title())
|
||||||
|
return
|
||||||
playlist = PL.Playlist_Object()
|
playlist = PL.Playlist_Object()
|
||||||
playlist.id = api.plex_id()
|
playlist.id = api.plex_id()
|
||||||
playlist.type = v.KODI_PLAYLIST_TYPE_FROM_PLEX[api.playlist_type()]
|
playlist.type = v.KODI_PLAYLIST_TYPE_FROM_PLEX[api.playlist_type()]
|
||||||
|
@ -122,14 +138,17 @@ def delete_kodi_playlist(playlist):
|
||||||
the Plex playlist table.
|
the Plex playlist table.
|
||||||
Returns None or raises PL.PlaylistError
|
Returns None or raises PL.PlaylistError
|
||||||
"""
|
"""
|
||||||
try:
|
if not sync_kodi_playlist(playlist.kodi_path):
|
||||||
path_ops.remove(playlist.kodi_path)
|
LOG.debug('Do not delete since we should not sync playlist %s',
|
||||||
except (OSError, IOError) as err:
|
playlist)
|
||||||
LOG.error('Could not delete Kodi playlist file %s. Error:\n %s: %s',
|
|
||||||
playlist, err.errno, err.strerror)
|
|
||||||
raise PL.PlaylistError('Could not delete %s' % playlist.kodi_path)
|
|
||||||
else:
|
else:
|
||||||
update_plex_table(playlist, delete=True)
|
try:
|
||||||
|
path_ops.remove(playlist.kodi_path)
|
||||||
|
except (OSError, IOError) as err:
|
||||||
|
LOG.error('Could not delete Kodi playlist file %s. Error:\n%s: %s',
|
||||||
|
playlist, err.errno, err.strerror)
|
||||||
|
raise PL.PlaylistError('Could not delete %s' % playlist.kodi_path)
|
||||||
|
update_plex_table(playlist, delete=True)
|
||||||
|
|
||||||
|
|
||||||
def update_plex_table(playlist, delete=False):
|
def update_plex_table(playlist, delete=False):
|
||||||
|
@ -382,6 +401,8 @@ def _full_sync():
|
||||||
if extension not in SUPPORTED_FILETYPES:
|
if extension not in SUPPORTED_FILETYPES:
|
||||||
continue
|
continue
|
||||||
path = path_ops.path.join(root, file)
|
path = path_ops.path.join(root, file)
|
||||||
|
if not sync_kodi_playlist(path):
|
||||||
|
continue
|
||||||
kodi_hash = utils.generate_file_md5(path)
|
kodi_hash = utils.generate_file_md5(path)
|
||||||
playlist = playlist_object_from_db(kodi_hash=kodi_hash)
|
playlist = playlist_object_from_db(kodi_hash=kodi_hash)
|
||||||
playlist_2 = playlist_object_from_db(path=path)
|
playlist_2 = playlist_object_from_db(path=path)
|
||||||
|
@ -417,6 +438,25 @@ def _full_sync():
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def sync_kodi_playlist(path):
|
||||||
|
"""
|
||||||
|
Returns True if we should sync this Kodi playlist with path [unicode] to
|
||||||
|
Plex based on the playlist file name and the user settings, False otherwise
|
||||||
|
"""
|
||||||
|
if not state.SYNC_SPECIFIC_KODI_PLAYLISTS:
|
||||||
|
return True
|
||||||
|
playlist = PL.Playlist_Object()
|
||||||
|
try:
|
||||||
|
playlist.kodi_path = path
|
||||||
|
except PL.PlaylistError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
prefix = utils.settings('syncSpecificKodiPlaylistsPrefix').lower()
|
||||||
|
if playlist.kodi_filename.lower().startswith(prefix):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class PlaylistEventhandler(FileSystemEventHandler):
|
class PlaylistEventhandler(FileSystemEventHandler):
|
||||||
"""
|
"""
|
||||||
PKC eventhandler to monitor Kodi playlists safed to disk
|
PKC eventhandler to monitor Kodi playlists safed to disk
|
||||||
|
@ -444,6 +484,10 @@ class PlaylistEventhandler(FileSystemEventHandler):
|
||||||
if (not state.ENABLE_MUSIC and
|
if (not state.ENABLE_MUSIC and
|
||||||
event.src_path.startswith(v.PLAYLIST_PATH_MUSIC)):
|
event.src_path.startswith(v.PLAYLIST_PATH_MUSIC)):
|
||||||
return
|
return
|
||||||
|
path = event.dest_path if event.event_type == EVENT_TYPE_MOVED \
|
||||||
|
else event.src_path
|
||||||
|
if not sync_kodi_playlist(path):
|
||||||
|
return
|
||||||
_method_map = {
|
_method_map = {
|
||||||
EVENT_TYPE_MODIFIED: self.on_modified,
|
EVENT_TYPE_MODIFIED: self.on_modified,
|
||||||
EVENT_TYPE_MOVED: self.on_moved,
|
EVENT_TYPE_MOVED: self.on_moved,
|
||||||
|
|
|
@ -1228,46 +1228,49 @@ class API(object):
|
||||||
for entry in self.item.iterfind('./Media'):
|
for entry in self.item.iterfind('./Media'):
|
||||||
count += 1
|
count += 1
|
||||||
if (count > 1 and (
|
if (count > 1 and (
|
||||||
(self.plex_type() != 'clip' and
|
(self.plex_type() != v.PLEX_TYPE_CLIP and
|
||||||
utils.settings('bestQuality') == 'false')
|
utils.settings('bestQuality') == 'false')
|
||||||
or
|
or
|
||||||
(self.plex_type() == 'clip' and
|
(self.plex_type() == v.PLEX_TYPE_CLIP and
|
||||||
utils.settings('bestTrailer') == 'false'))):
|
utils.settings('bestTrailer') == 'false'))):
|
||||||
# Several streams/files available.
|
# Several streams/files available.
|
||||||
dialoglist = []
|
dialoglist = []
|
||||||
for entry in self.item.iterfind('./Media'):
|
for entry in self.item.iterfind('./Media'):
|
||||||
# Get additional info (filename / languages)
|
# Get additional info (filename / languages)
|
||||||
filename = None
|
|
||||||
if 'file' in entry[0].attrib:
|
if 'file' in entry[0].attrib:
|
||||||
filename = path_ops.path.basename(entry[0].attrib['file'])
|
option = utils.try_decode(entry[0].attrib['file'])
|
||||||
|
option = path_ops.path.basename(option)
|
||||||
|
else:
|
||||||
|
option = self.title() or ''
|
||||||
# Languages of audio streams
|
# Languages of audio streams
|
||||||
languages = []
|
languages = []
|
||||||
for stream in entry[0]:
|
for stream in entry[0]:
|
||||||
if (stream.attrib['streamType'] == '1' and
|
if (stream.attrib['streamType'] == '1' and
|
||||||
'language' in stream.attrib):
|
'language' in stream.attrib):
|
||||||
languages.append(stream.attrib['language'])
|
language = utils.try_decode(stream.attrib['language'])
|
||||||
|
languages.append(language)
|
||||||
languages = ', '.join(languages)
|
languages = ', '.join(languages)
|
||||||
if filename:
|
|
||||||
option = utils.try_encode(filename)
|
|
||||||
if languages:
|
if languages:
|
||||||
if option:
|
if option:
|
||||||
option = '%s (%s): ' % (option,
|
option = '%s (%s): ' % (option, languages)
|
||||||
utils.try_encode(languages))
|
|
||||||
else:
|
else:
|
||||||
option = '%s: ' % utils.try_encode(languages)
|
option = '%s: ' % languages
|
||||||
|
else:
|
||||||
|
option = '%s ' % option
|
||||||
if 'videoResolution' in entry.attrib:
|
if 'videoResolution' in entry.attrib:
|
||||||
option = '%s%sp ' % (option,
|
res = utils.try_decode(entry['videoResolution'])
|
||||||
entry.get('videoResolution'))
|
option = '%s%sp ' % (option, res)
|
||||||
if 'videoCodec' in entry.attrib:
|
if 'videoCodec' in entry.attrib:
|
||||||
option = '%s%s' % (option,
|
codec = utils.try_decode(entry['videoCodec'])
|
||||||
entry.get('videoCodec'))
|
option = '%s%s' % (option, codec)
|
||||||
option = option.strip() + ' - '
|
option = option.strip() + ' - '
|
||||||
if 'audioProfile' in entry.attrib:
|
if 'audioProfile' in entry.attrib:
|
||||||
option = '%s%s ' % (option,
|
profile = utils.try_decode(entry['audioProfile'])
|
||||||
entry.get('audioProfile'))
|
option = '%s%s ' % (option, profile)
|
||||||
if 'audioCodec' in entry.attrib:
|
if 'audioCodec' in entry.attrib:
|
||||||
option = '%s%s ' % (option,
|
codec = utils.try_decode(entry['audioCodec'])
|
||||||
entry.get('audioCodec'))
|
option = '%s%s ' % (option, codec)
|
||||||
|
option = utils.try_encode(option.strip())
|
||||||
dialoglist.append(option)
|
dialoglist.append(option)
|
||||||
media = utils.dialog('select', 'Select stream', dialoglist)
|
media = utils.dialog('select', 'Select stream', dialoglist)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -57,6 +57,14 @@ class Service():
|
||||||
utils.settings('syncThreadNumber'))
|
utils.settings('syncThreadNumber'))
|
||||||
LOG.info('Playlist m3u encoding: %s', v.M3U_ENCODING)
|
LOG.info('Playlist m3u encoding: %s', v.M3U_ENCODING)
|
||||||
LOG.info("Full sys.argv received: %s", sys.argv)
|
LOG.info("Full sys.argv received: %s", sys.argv)
|
||||||
|
LOG.info('Synching only specific Kodi playlists: %s',
|
||||||
|
utils.settings('syncSpecificKodiPlaylists') == 'true')
|
||||||
|
LOG.info('Kodi playlist prefix: %s',
|
||||||
|
utils.settings('syncSpecificKodiPlaylistsPrefix'))
|
||||||
|
LOG.info('Synching only specific Plex playlists: %s',
|
||||||
|
utils.settings('syncSpecificPlexPlaylistsPrefix') == 'true')
|
||||||
|
LOG.info('Play playlist prefix: %s',
|
||||||
|
utils.settings('syncSpecificPlexPlaylistsPrefix'))
|
||||||
self.monitor = xbmc.Monitor()
|
self.monitor = xbmc.Monitor()
|
||||||
# Load/Reset PKC entirely - important for user/Kodi profile switch
|
# Load/Reset PKC entirely - important for user/Kodi profile switch
|
||||||
initialsetup.reload_pkc()
|
initialsetup.reload_pkc()
|
||||||
|
|
|
@ -55,6 +55,10 @@ SYNC_DIALOG = True
|
||||||
IMAGE_SYNC_NOTIFICATIONS = True
|
IMAGE_SYNC_NOTIFICATIONS = True
|
||||||
# Sync playlists from Plex to Kodi and vice-versa?
|
# Sync playlists from Plex to Kodi and vice-versa?
|
||||||
SYNC_PLAYLISTS = True
|
SYNC_PLAYLISTS = True
|
||||||
|
# Only sync specific Plex playlists to Kodi?
|
||||||
|
SYNC_SPECIFIC_PLEX_PLAYLISTS = False
|
||||||
|
# Only sync specific Kodi playlists to Plex?
|
||||||
|
SYNC_SPECIFIC_KODI_PLAYLISTS = False
|
||||||
# Is synching of Plex music enabled?
|
# Is synching of Plex music enabled?
|
||||||
ENABLE_MUSIC = True
|
ENABLE_MUSIC = True
|
||||||
# How often shall we sync?
|
# How often shall we sync?
|
||||||
|
|
|
@ -464,9 +464,6 @@ 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_artwork_count', value='unknown')
|
|
||||||
settings('fanarttv_lookups', value='unknown')
|
|
||||||
# reset the install run flag
|
# reset the install run flag
|
||||||
settings('SyncInstallRunDone', value="false")
|
settings('SyncInstallRunDone', value="false")
|
||||||
|
|
||||||
|
|
|
@ -57,12 +57,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 type="sep" />
|
<setting type="sep" />
|
||||||
<setting id="enablePlaylistSync" type="bool" label="30020" default="true" visible="true"/><!-- Sync Plex playlists -->
|
|
||||||
<setting id="fullSyncInterval" type="number" label="39053" default="60" option="int" />
|
<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="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="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="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="lsep" label="$LOCALIZE[136]" /><!-- Playlists -->
|
||||||
|
<setting type="sep" />
|
||||||
|
<setting id="enablePlaylistSync" type="bool" label="30020" default="true" visible="true"/><!-- Sync Plex playlists -->
|
||||||
|
<setting id="syncSpecificKodiPlaylists" type="bool" label="30023" default="false" visible="true"/><!-- Only sync specific Kodi playlists to Plex -->
|
||||||
|
<setting id="syncSpecificKodiPlaylistsPrefix" type="text" label="30027" default="sync_" visible="eq(-1,true)"/><!-- Prefix in Kodi playlist name to trigger sync -->
|
||||||
|
<setting id="syncSpecificPlexPlaylists" type="bool" label="30021" default="false" visible="true"/><!-- Only sync specific Plex playlists to Kodi -->
|
||||||
|
<setting id="syncSpecificPlexPlaylistsPrefix" type="text" label="30026" default="sync_" visible="eq(-1,true)" /><!-- Prefix in Plex playlist name to trigger sync -->
|
||||||
<setting type="sep" />
|
<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"/>
|
||||||
|
@ -130,10 +136,6 @@
|
||||||
<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_artwork_count" label="30011" type="text" default="unknown" enable="false" visible="eq(-8,true)"/><!-- Plex artwork (posters and backgrounds) left to cache: -->
|
|
||||||
<setting id="fanarttv_lookups" label="30015" type="text" default="unknown" 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">
|
||||||
|
|
Loading…
Add table
Reference in a new issue