diff --git a/README.md b/README.md index ce11318b..a33e47d0 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -[![stable version](https://img.shields.io/badge/stable_version-2.3.10-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.3.11-red.svg?maxAge=60&style=flat) ](https://github.com/croneter/binary_repo/raw/master/beta/repository.plexkodiconnectbeta/repository.plexkodiconnectbeta-1.0.2.zip) +[![stable version](https://img.shields.io/badge/stable_version-2.3.12-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.3.12-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) [![FAQ](https://img.shields.io/badge/wiki-FAQ-brightgreen.svg?maxAge=60&style=flat)](https://github.com/croneter/PlexKodiConnect/wiki/faq) diff --git a/addon.xml b/addon.xml index a524247b..6a49b165 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + @@ -73,7 +73,12 @@ Нативна інтеграція Plex в Kodi Підключає Kodi до серверу Plex. Цей плагін передбачає, що ви керуєте всіма своїми відео за допомогою Plex (і ніяк не Kodi). Ви можете втратити дані, які вже зберігаються у відео та музичних БД Kodi (оскільки цей плагін безпосередньо їх змінює). Використовуйте на свій страх і ризик! Використовуйте на свій ризик - version 2.3.11 (beta only): + version 2.3.12: +- Fix Kodi hanging if media stream selection is aborted +- Fix potential sync crash +- Revert "Fix Kodi crash by committing to DB frequently" + +version 2.3.11 (beta only): - Fix Kodi crash by committing to DB frequently version 2.3.10: diff --git a/changelog.txt b/changelog.txt index ead72a4c..f0d3eb80 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,8 @@ +version 2.3.12: +- Fix Kodi hanging if media stream selection is aborted +- Fix potential sync crash +- Revert "Fix Kodi crash by committing to DB frequently" + version 2.3.11 (beta only): - Fix Kodi crash by committing to DB frequently diff --git a/resources/lib/itemtypes.py b/resources/lib/itemtypes.py index 17beb66f..b7442c85 100644 --- a/resources/lib/itemtypes.py +++ b/resources/lib/itemtypes.py @@ -804,20 +804,24 @@ class TVShows(Items): seasonid = self.kodi_db.add_season(showid, season) # GET THE FILE AND PATH ##### + do_indirect = not state.DIRECT_PATHS if state.DIRECT_PATHS: playurl = api.file_path(force_first_media=True) - playurl = api.validate_playurl(playurl, v.PLEX_TYPE_EPISODE) - if "\\" in playurl: - # Local path - filename = playurl.rsplit("\\", 1)[1] + if playurl is None: + do_indirect = True else: - # Network share - filename = playurl.rsplit("/", 1)[1] - path = playurl.replace(filename, "") - parent_path_id = self.kodi_db.parent_path_id(path) - pathid = self.kodi_db.add_video_path(path, - id_parent_path=parent_path_id) - else: + playurl = api.validate_playurl(playurl, v.PLEX_TYPE_EPISODE) + if "\\" in playurl: + # Local path + filename = playurl.rsplit("\\", 1)[1] + else: + # Network share + filename = playurl.rsplit("/", 1)[1] + path = playurl.replace(filename, "") + parent_path_id = self.kodi_db.parent_path_id(path) + pathid = self.kodi_db.add_video_path(path, + id_parent_path=parent_path_id) + if do_indirect: # Set plugin path - do NOT use "intermediate" paths for the show # as with direct paths! filename = api.file_name(force_first_media=True) diff --git a/resources/lib/library_sync/process_metadata.py b/resources/lib/library_sync/process_metadata.py index 2aa683e0..c0258730 100644 --- a/resources/lib/library_sync/process_metadata.py +++ b/resources/lib/library_sync/process_metadata.py @@ -12,11 +12,6 @@ from . import sync_info ############################################################################### LOG = getLogger("PLEX." + __name__) -# Commit to DB happens only after leaving respective itemtypes context manager -# with item_fct() as item_class: -# After how many items shall we additionally commit? Otherwise, Kodi -# crashes if we sync thousands of items without a single commit. -COMMIT_AFTER_N_ITEMS = 1000 ############################################################################### @@ -62,12 +57,14 @@ class ThreadedProcessMetadata(Thread): LOG.debug('Processing thread started') # Constructs the method name, e.g. itemtypes.Movies item_fct = getattr(itemtypes, self.item_class) - n = 0 + # cache local variables because it's faster + queue = self.queue + stopped = self.stopped with item_fct() as item_class: - while self.stopped() is False: + while stopped() is False: # grabs item from queue try: - item = self.queue.get(block=False) + item = queue.get(block=False) except Empty: sleep(20) continue @@ -86,11 +83,6 @@ class ThreadedProcessMetadata(Thread): with sync_info.LOCK: sync_info.PROCESS_METADATA_COUNT += 1 sync_info.PROCESSING_VIEW_NAME = item['title'] - n += 1 - if n == COMMIT_AFTER_N_ITEMS: - n = 0 - item_class.plexconn.commit() - item_class.kodiconn.commit() - self.queue.task_done() + queue.task_done() self.terminate_now() LOG.debug('Processing thread terminated') diff --git a/resources/lib/playback.py b/resources/lib/playback.py index 1e8f80f7..77e613af 100644 --- a/resources/lib/playback.py +++ b/resources/lib/playback.py @@ -413,6 +413,11 @@ def _conclude_playback(playqueue, pos): else: api = None playurl = item.file + if not playurl: + LOG.info('Did not get a playurl, aborting playback silently') + state.RESUME_PLAYBACK = False + pickler.pickle_me(result) + return listitem.setPath(utils.try_encode(playurl)) if item.playmethod == 'DirectStream': listitem.setSubtitles(api.cache_external_subs()) diff --git a/resources/lib/playutils.py b/resources/lib/playutils.py index 68d45fe5..0021fcc8 100644 --- a/resources/lib/playutils.py +++ b/resources/lib/playutils.py @@ -24,12 +24,11 @@ class PlayUtils(): def getPlayUrl(self): """ - Returns the playurl for the part + Returns the playurl [unicode] for the part or returns None. (movie might consist of several files) - - playurl is in unicode! """ - self.api.mediastream_number() + if self.api.mediastream_number() is None: + return playurl = self.isDirectPlay() if playurl is not None: LOG.info("File is direct playing.") @@ -232,8 +231,9 @@ class PlayUtils(): stream by a PUT request to the PMS """ # Set media and part where we're at - if self.api.mediastream is None: - self.api.mediastream_number() + if (self.api.mediastream is None and + self.api.mediastream_number() is None): + return try: mediastreams = self.api.plex_media_streams() except (TypeError, IndexError): diff --git a/resources/lib/plex_api.py b/resources/lib/plex_api.py index 526076d9..baf56a7e 100644 --- a/resources/lib/plex_api.py +++ b/resources/lib/plex_api.py @@ -203,7 +203,8 @@ class API(object): files are present for the same PMS item """ if self.mediastream is None and force_first_media is False: - self.mediastream_number() + if self.mediastream_number() is None: + return try: if force_first_media is False: ans = self.item[self.mediastream][self.part].attrib['file'] @@ -1294,6 +1295,9 @@ class API(object): Returns the Media stream as an int (mostly 0). Will let the user choose if several media streams are present for a PMS item (if settings are set accordingly) + + Returns None if the user aborted selection (leaving self.mediastream at + its default of None) """ # How many streams do we have? count = 0 @@ -1345,6 +1349,9 @@ class API(object): option = utils.try_encode(option.strip()) dialoglist.append(option) media = utils.dialog('select', 'Select stream', dialoglist) + if media == -1: + LOG.info('User cancelled media stream selection') + return else: media = 0 self.mediastream = media @@ -1371,8 +1378,8 @@ class API(object): TODO: mediaIndex """ - if self.mediastream is None: - self.mediastream_number() + if self.mediastream is None and self.mediastream_number() is None: + return if quality is None: quality = {} xargs = clientinfo.getXArgsDeviceInfo()