diff --git a/resources/lib/path_ops.py b/resources/lib/path_ops.py index b915fa1c..072e27f2 100644 --- a/resources/lib/path_ops.py +++ b/resources/lib/path_ops.py @@ -19,6 +19,8 @@ import shutil import os from os import path # allows to use path_ops.path.join, for example from distutils import dir_util +import re + import xbmc import xbmcvfs @@ -26,6 +28,7 @@ from .tools import unicode_paths # Kodi seems to encode in utf-8 in ALL cases (unlike e.g. the OS filesystem) KODI_ENCODING = 'utf-8' +REGEX_FILE_NUMBERING = re.compile(r'''_(\d\d)\.\w+$''') def encode_path(path): @@ -216,3 +219,25 @@ def basename(path): return path.rsplit('\\', 1)[1] except IndexError: return '' + + +def create_unique_path(directory, filename, extension): + """ + Checks whether 'directory/filename.extension' exists. If so, will start + numbering the filename until the file does not exist yet (up to 99) + """ + res = path.join(directory, '.'.join((filename, extension))) + while exists(res): + occurance = REGEX_FILE_NUMBERING.search(res) + if not occurance: + filename = '{}_00'.format(filename[:min(len(filename), + 251 - len(extension))]) + res = path.join(directory, '.'.join((filename, extension))) + else: + number = int(occurance.group(1)) + 1 + if number > 99: + raise RuntimeError('Could not create unique file: {} {} {}'.format( + directory, filename, extension)) + basename = re.sub(REGEX_FILE_NUMBERING, '', res) + res = '{}_{:02d}.{}'.format(basename, number, extension) + return res diff --git a/resources/lib/playback_decision.py b/resources/lib/playback_decision.py index bcc69866..25970099 100644 --- a/resources/lib/playback_decision.py +++ b/resources/lib/playback_decision.py @@ -351,12 +351,12 @@ def audio_subtitle_prefs(api, listitem): for stream in mediastreams: # Since Plex returns all possible tracks together, have to sort # them. - index = stream.attrib.get('id') - typus = stream.attrib.get('streamType') + index = stream.get('id') + typus = stream.get('streamType') # Audio if typus == "2": - codec = stream.attrib.get('codec') - channellayout = stream.attrib.get('audioChannelLayout', "") + codec = stream.get('codec') + channellayout = stream.get('audioChannelLayout', "") try: track = "%s %s - %s %s" % (audio_numb + 1, stream.attrib['language'], @@ -368,48 +368,42 @@ def audio_subtitle_prefs(api, listitem): codec, channellayout) audio_streams_list.append(index) - audio_streams.append(utils.try_encode(track)) + audio_streams.append(track.encode('utf-8')) audio_numb += 1 # Subtitles elif typus == "3": try: - track = "%s %s" % (sub_num + 1, stream.attrib['language']) + track = '{} {}'.format(sub_num, stream.attrib['displayTitle']) except KeyError: - track = "%s %s (%s)" % (sub_num + 1, - utils.lang(39707), # unknown - stream.attrib.get('codec')) - default = stream.attrib.get('default') - forced = stream.attrib.get('forced') - downloadable = stream.attrib.get('key') + track = '{} {} ({})'.format(sub_num + 1, + utils.lang(39707), # unknown + stream.get('codec')) + default = stream.get('default') + forced = stream.get('forced') + downloadable = stream.get('key') if default: track = "%s - %s" % (track, utils.lang(39708)) # Default if forced: track = "%s - %s" % (track, utils.lang(39709)) # Forced if downloadable: - # We do know the language - temporarily download - if 'language' in stream.attrib: - path = api.download_external_subtitles( - '{server}%s' % stream.attrib['key'], - "subtitle.%s.%s" % (stream.attrib['languageCode'], - stream.attrib['codec'])) - # We don't know the language - no need to download - else: - path = api.attach_plex_token_to_url( - "%s%s" % (app.CONN.server, - stream.attrib['key'])) - downloadable_streams.append(index) - download_subs.append(utils.try_encode(path)) + path = api.download_external_subtitles( + '{{server}}{}'.format(stream.get('key')), + stream.get('displayTitle'), + stream.get('codec')) + if path: + downloadable_streams.append(index) + download_subs.append(path.encode('utf-8')) else: track = "%s (%s)" % (track, utils.lang(39710)) # burn-in - if stream.attrib.get('selected') == '1' and downloadable: + if stream.get('selected') == '1' and downloadable: # Only show subs without asking user if they can be # turned off default_sub = index subtitle_streams_list.append(index) - subtitle_streams.append(utils.try_encode(track)) + subtitle_streams.append(track.encode('utf-8')) sub_num += 1 if audio_numb > 1: diff --git a/resources/lib/plex_api/media.py b/resources/lib/plex_api/media.py index 3c7bf72b..7d091fa4 100644 --- a/resources/lib/plex_api/media.py +++ b/resources/lib/plex_api/media.py @@ -254,46 +254,33 @@ class Media(object): try: mediastreams = self.xml[0][self.part] except (TypeError, KeyError, IndexError): - return - kodiindex = 0 - fileindex = 0 + return externalsubs for stream in mediastreams: # Since plex returns all possible tracks together, have to pull # only external subtitles - only for these a 'key' exists - if cast(int, stream.get('streamType')) != 3: - # Not a subtitle + if int(stream.get('streamType')) != 3 or 'key' not in stream.attrib: + # Not a subtitle or not not an external subtitle continue - # Only set for additional external subtitles NOT lying beside video - key = stream.get('key') - # Only set for dedicated subtitle files lying beside video - # ext = stream.attrib.get('format') - if key: - # We do know the language - temporarily download - if stream.get('languageCode') is not None: - language = stream.get('languageCode') - codec = stream.get('codec') - path = self.download_external_subtitles( - "{server}%s" % key, - "subtitle%02d.%s.%s" % (fileindex, language, codec)) - fileindex += 1 - # We don't know the language - no need to download - else: - path = self.attach_plex_token_to_url( - "%s%s" % (app.CONN.server, key)) + path = self.download_external_subtitles( + '{server}%s' % stream.get('key'), + stream.get('displayTitle'), + stream.get('codec')) + if path: externalsubs.append(path) - kodiindex += 1 LOG.info('Found external subs: %s', externalsubs) return externalsubs @staticmethod - def download_external_subtitles(url, filename): + def download_external_subtitles(url, filename, extension): """ One cannot pass the subtitle language for ListItems. Workaround; will download the subtitle at url to the Kodi PKC directory in a temp dir Returns the path to the downloaded subtitle or None """ - path = path_ops.path.join(v.EXTERNAL_SUBTITLE_TEMP_PATH, filename) + path = path_ops.create_unique_path(v.EXTERNAL_SUBTITLE_TEMP_PATH, + filename, + extension) response = DU().downloadUrl(url, return_response=True) try: response.status_code @@ -302,8 +289,8 @@ class Media(object): return else: LOG.debug('Writing temp subtitle to %s', path) - with open(path_ops.encode_path(path), 'wb') as filer: - filer.write(response.content) + with open(path_ops.encode_path(path), 'wb') as f: + f.write(response.content) return path def validate_playurl(self, path, typus, force_check=False, folder=False,