From 1eed16dd528e7224a024a70fa0c7a808f5976936 Mon Sep 17 00:00:00 2001 From: Croneter Date: Mon, 2 Jul 2018 20:23:16 +0200 Subject: [PATCH] Allow to only sync specific Plex or Kodi playlists --- .../resource.language.en_gb/strings.po | 20 ++++++ resources/lib/kodimonitor.py | 4 +- resources/lib/playlists.py | 62 ++++++++++++++++--- resources/lib/service_entry.py | 8 +++ resources/lib/state.py | 4 ++ resources/settings.xml | 8 ++- 6 files changed, 95 insertions(+), 11 deletions(-) diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po index d416b2ef..e674797c 100644 --- a/resources/language/resource.language.en_gb/strings.po +++ b/resources/language/resource.language.en_gb/strings.po @@ -113,11 +113,21 @@ msgctxt "#30020" msgid "Sync Plex playlists" msgstr "" +# PKC settings sync options +msgctxt "#30021" +msgid "Only sync specific Plex playlists to Kodi" +msgstr "" + # PKC settings category msgctxt "#30022" msgid "Advanced" msgstr "" +# PKC settings sync options +msgctxt "#30023" +msgid "Only sync specific Kodi playlists to Plex" +msgstr "" + msgctxt "#30024" msgid "Username" msgstr "" @@ -126,6 +136,16 @@ msgctxt "#30025" msgid "Display message if PMS goes offline" 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" msgid "Port Number" msgstr "" diff --git a/resources/lib/kodimonitor.py b/resources/lib/kodimonitor.py index c214d3cd..2ddeaf22 100644 --- a/resources/lib/kodimonitor.py +++ b/resources/lib/kodimonitor.py @@ -48,7 +48,9 @@ STATE_SETTINGS = { 'forceReloadSkinOnPlaybackStop': 'FORCE_RELOAD_SKIN', 'fetch_pms_item_number': 'FETCH_PMS_ITEM_NUMBER', 'imageSyncNotifications': 'IMAGE_SYNC_NOTIFICATIONS', - 'enablePlaylistSync': 'SYNC_PLAYLISTS' + 'enablePlaylistSync': 'SYNC_PLAYLISTS', + 'syncSpecificPlexPlaylists': 'SYNC_SPECIFIC_PLEX_PLAYLISTS', + 'syncSpecificKodiPlaylists': 'SYNC_SPECIFIC_KODI_PLAYLISTS' } ############################################################################### diff --git a/resources/lib/playlists.py b/resources/lib/playlists.py index 5429d591..37c63729 100644 --- a/resources/lib/playlists.py +++ b/resources/lib/playlists.py @@ -63,8 +63,16 @@ def delete_plex_playlist(playlist): entry in the Plex playlist table. Returns None or raises PL.PlaylistError """ - LOG.debug('Deleting playlist from PMS: %s', playlist) - PL.delete_playlist_from_pms(playlist) + if (state.SYNC_SPECIFIC_KODI_PLAYLISTS and + 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) @@ -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 is deleted from both disk and the Plex database. 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) if xml is None: LOG.error('Could not get Plex playlist %s', plex_id) raise PL.PlaylistError('Could not get Plex playlist %s' % plex_id) api = API(xml) + if state.SYNC_SPECIFIC_PLEX_PLAYLISTS: + prefix = utils.settings('syncSpecificPlexPlaylistsPrefix') + if api.title() and not api.title().startswith(prefix): + LOG.debug('User chose to not sync playlist %s', api.title()) + return playlist = PL.Playlist_Object() playlist.id = api.plex_id() playlist.type = v.KODI_PLAYLIST_TYPE_FROM_PLEX[api.playlist_type()] @@ -122,14 +138,17 @@ def delete_kodi_playlist(playlist): the Plex playlist table. Returns None or raises PL.PlaylistError """ - 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) + if not sync_kodi_playlist(playlist.kodi_path): + LOG.debug('Do not delete since we should not sync playlist %s', + playlist) 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): @@ -382,6 +401,8 @@ def _full_sync(): if extension not in SUPPORTED_FILETYPES: continue path = path_ops.path.join(root, file) + if not sync_kodi_playlist(path): + continue kodi_hash = utils.generate_file_md5(path) playlist = playlist_object_from_db(kodi_hash=kodi_hash) playlist_2 = playlist_object_from_db(path=path) @@ -417,6 +438,25 @@ def _full_sync(): 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') + if playlist.kodi_filename.startswith(prefix): + return True + return False + + class PlaylistEventhandler(FileSystemEventHandler): """ PKC eventhandler to monitor Kodi playlists safed to disk @@ -444,6 +484,10 @@ class PlaylistEventhandler(FileSystemEventHandler): if (not state.ENABLE_MUSIC and event.src_path.startswith(v.PLAYLIST_PATH_MUSIC)): 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 = { EVENT_TYPE_MODIFIED: self.on_modified, EVENT_TYPE_MOVED: self.on_moved, diff --git a/resources/lib/service_entry.py b/resources/lib/service_entry.py index f6ccc3dc..9d1e803a 100644 --- a/resources/lib/service_entry.py +++ b/resources/lib/service_entry.py @@ -57,6 +57,14 @@ class Service(): utils.settings('syncThreadNumber')) LOG.info('Playlist m3u encoding: %s', v.M3U_ENCODING) 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() # Load/Reset PKC entirely - important for user/Kodi profile switch initialsetup.reload_pkc() diff --git a/resources/lib/state.py b/resources/lib/state.py index 7cd67882..d62a79f4 100644 --- a/resources/lib/state.py +++ b/resources/lib/state.py @@ -55,6 +55,10 @@ SYNC_DIALOG = True IMAGE_SYNC_NOTIFICATIONS = True # Sync playlists from Plex to Kodi and vice-versa? 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? ENABLE_MUSIC = True # How often shall we sync? diff --git a/resources/settings.xml b/resources/settings.xml index d20c6c58..e089de73 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -57,12 +57,18 @@ - + + + + + + +