diff --git a/src/ffx/ffx_controller.py b/src/ffx/ffx_controller.py index 4095b71..f55619d 100644 --- a/src/ffx/ffx_controller.py +++ b/src/ffx/ffx_controller.py @@ -1,13 +1,12 @@ import os, click +from ffx.media_descriptor_change_set import MediaDescriptorChangeSet + from ffx.media_descriptor import MediaDescriptor -from ffx.track_descriptor import TrackDescriptor from ffx.audio_layout import AudioLayout from ffx.track_type import TrackType from ffx.video_encoder import VideoEncoder from ffx.process import executeProcess -from ffx.track_disposition import TrackDisposition -from ffx.track_codec import TrackCodec from ffx.constants import DEFAULT_CROP_START, DEFAULT_CROP_LENGTH @@ -31,8 +30,7 @@ class FfxController(): CHANNEL_MAP_5_1 = 'FL-FL|FR-FR|FC-FC|LFE-LFE|SL-BL|SR-BR:5.1' - #! - SIGNATURE_TAGS = {'RECODED_WITH': 'FFX'} + # SIGNATURE_TAGS = {'RECODED_WITH': 'FFX'} def __init__(self, context : dict, @@ -40,10 +38,11 @@ class FfxController(): sourceMediaDescriptor : MediaDescriptor = None): self.__context = context - self.__sourceMediaDescriptor = sourceMediaDescriptor - self.__targetMediaDescriptor = targetMediaDescriptor - self.__configurationData = self.__context['config'].getData() + self.__targetMediaDescriptor = targetMediaDescriptor + self.__mdcs = MediaDescriptorChangeSet(context, + targetMediaDescriptor, + sourceMediaDescriptor) self.__logger = context['logger'] @@ -147,92 +146,92 @@ class FfxController(): trackSubIndex += 1 return audioTokens - - # -disposition:s:0 default -disposition:s:1 0 - def generateDispositionTokens(self): - - targetTrackDescriptors = self.__targetMediaDescriptor.getAllTrackDescriptors() - - sourceTrackDescriptors = ([] if self.__sourceMediaDescriptor is None - else self.__sourceMediaDescriptor.getAllTrackDescriptors()) - - dispositionTokens = [] - - for trackIndex in range(len(targetTrackDescriptors)): - - td = targetTrackDescriptors[trackIndex] - - #HINT: No dispositions for pgs subtitle tracks that have no external file source - if (td.getExternalSourceFilePath() - or td.getCodec() != TrackCodec.PGS): - - subIndex = td.getSubIndex() - streamIndicator = td.getType().indicator() - - - sourceDispositionSet = sourceTrackDescriptors[td.getSourceIndex()].getDispositionSet() if sourceTrackDescriptors else set() - - #TODO: Alles discarden was im targetDescriptor vorhanden ist (?) - sourceDispositionSet.discard(TrackDisposition.DEFAULT) - - dispositionSet = td.getDispositionSet() | sourceDispositionSet - - if dispositionSet: - dispositionTokens += [f"-disposition:{streamIndicator}:{subIndex}", '+'.join([d.label() for d in dispositionSet])] - else: - dispositionTokens += [f"-disposition:{streamIndicator}:{subIndex}", '0'] - - return dispositionTokens - - - def generateMetadataTokens(self): - - metadataTokens = [] - - metadataConfiguration = self.__configurationData['metadata'] if 'metadata' in self.__configurationData.keys() else {} - - signatureTags = metadataConfiguration['signature'] if 'signature' in metadataConfiguration.keys() else {} - removeGlobalKeys = metadataConfiguration['remove'] if 'remove' in metadataConfiguration.keys() else [] - removeTrackKeys = metadataConfiguration['streams']['remove'] if 'streams' in metadataConfiguration.keys() and 'remove' in metadataConfiguration['streams'].keys() else [] - - mediaTags = {k:v for k,v in self.__targetMediaDescriptor.getTags().items() if not k in removeGlobalKeys} - - if (not 'no_signature' in self.__context.keys() - or not self.__context['no_signature']): - outputMediaTags = mediaTags | signatureTags - else: - outputMediaTags = mediaTags - - for tagKey, tagValue in outputMediaTags.items(): - metadataTokens += [f"-metadata:g", - f"{tagKey}={tagValue}"] - - for removeKey in removeGlobalKeys: - metadataTokens += [f"-metadata:g", - f"{removeKey}="] - - - removeMkvmergeMetadata = (not 'keep_mkvmerge_metadata' in self.__context.keys() - or not self.__context['keep_mkvmerge_metadata']) - - #HINT: With current ffmpeg version track metadata tags are not passed to the outfile - for td in self.__targetMediaDescriptor.getAllTrackDescriptors(): - - typeIndicator = td.getType().indicator() - subIndex = td.getSubIndex() - - for tagKey, tagValue in td.getTags().items(): - - if not tagKey in removeTrackKeys: - metadataTokens += [f"-metadata:s:{typeIndicator}:{subIndex}", - f"{tagKey}={tagValue}"] - - for removeKey in removeTrackKeys: - metadataTokens += [f"-metadata:s:{typeIndicator}:{subIndex}", - f"{removeKey}="] - - - return metadataTokens +# +# # -disposition:s:0 default -disposition:s:1 0 +# def generateDispositionTokens(self): +# +# targetTrackDescriptors = self.__targetMediaDescriptor.getAllTrackDescriptors() +# +# sourceTrackDescriptors = ([] if self.__sourceMediaDescriptor is None +# else self.__sourceMediaDescriptor.getAllTrackDescriptors()) +# +# dispositionTokens = [] +# +# for trackIndex in range(len(targetTrackDescriptors)): +# +# td = targetTrackDescriptors[trackIndex] +# +# #HINT: No dispositions for pgs subtitle tracks that have no external file source +# if (td.getExternalSourceFilePath() +# or td.getCodec() != TrackCodec.PGS): +# +# subIndex = td.getSubIndex() +# streamIndicator = td.getType().indicator() +# +# +# sourceDispositionSet = sourceTrackDescriptors[td.getSourceIndex()].getDispositionSet() if sourceTrackDescriptors else set() +# +# #TODO: Alles discarden was im targetDescriptor vorhanden ist (?) +# sourceDispositionSet.discard(TrackDisposition.DEFAULT) +# +# dispositionSet = td.getDispositionSet() | sourceDispositionSet +# +# if dispositionSet: +# dispositionTokens += [f"-disposition:{streamIndicator}:{subIndex}", '+'.join([d.label() for d in dispositionSet])] +# else: +# dispositionTokens += [f"-disposition:{streamIndicator}:{subIndex}", '0'] +# +# return dispositionTokens +# +# +# def generateMetadataTokens(self): +# +# metadataTokens = [] +# +# metadataConfiguration = self.__configurationData['metadata'] if 'metadata' in self.__configurationData.keys() else {} +# +# signatureTags = metadataConfiguration['signature'] if 'signature' in metadataConfiguration.keys() else {} +# removeGlobalKeys = metadataConfiguration['remove'] if 'remove' in metadataConfiguration.keys() else [] +# removeTrackKeys = metadataConfiguration['streams']['remove'] if 'streams' in metadataConfiguration.keys() and 'remove' in metadataConfiguration['streams'].keys() else [] +# +# mediaTags = {k:v for k,v in self.__targetMediaDescriptor.getTags().items() if not k in removeGlobalKeys} +# +# if (not 'no_signature' in self.__context.keys() +# or not self.__context['no_signature']): +# outputMediaTags = mediaTags | signatureTags +# else: +# outputMediaTags = mediaTags +# +# for tagKey, tagValue in outputMediaTags.items(): +# metadataTokens += [f"-metadata:g", +# f"{tagKey}={tagValue}"] +# +# for removeKey in removeGlobalKeys: +# metadataTokens += [f"-metadata:g", +# f"{removeKey}="] +# +# +# removeMkvmergeMetadata = (not 'keep_mkvmerge_metadata' in self.__context.keys() +# or not self.__context['keep_mkvmerge_metadata']) +# +# #HINT: With current ffmpeg version track metadata tags are not passed to the outfile +# for td in self.__targetMediaDescriptor.getAllTrackDescriptors(): +# +# typeIndicator = td.getType().indicator() +# subIndex = td.getSubIndex() +# +# for tagKey, tagValue in td.getTags().items(): +# +# if not tagKey in removeTrackKeys: +# metadataTokens += [f"-metadata:s:{typeIndicator}:{subIndex}", +# f"{tagKey}={tagValue}"] +# +# for removeKey in removeTrackKeys: +# metadataTokens += [f"-metadata:s:{typeIndicator}:{subIndex}", +# f"{removeKey}="] +# +# +# return metadataTokens def runJob(self, @@ -262,10 +261,10 @@ class FfxController(): commandSequence = (commandTokens + self.__targetMediaDescriptor.getImportFileTokens() + self.__targetMediaDescriptor.getInputMappingTokens() - + self.generateDispositionTokens()) + + self.__mdcs.generateDispositionTokens()) # Optional tokens - commandSequence += self.generateMetadataTokens() + commandSequence += self.__mdcs.generateMetadataTokens() commandSequence += denoiseTokens commandSequence += (self.generateAudioEncodingTokens() @@ -314,10 +313,10 @@ class FfxController(): commandSequence2 = (commandTokens + self.__targetMediaDescriptor.getImportFileTokens() + self.__targetMediaDescriptor.getInputMappingTokens() - + self.generateDispositionTokens()) + + self.__mdcs.generateDispositionTokens()) # Optional tokens - commandSequence2 += self.generateMetadataTokens() + commandSequence2 += self.__mdcs.generateMetadataTokens() commandSequence2 += denoiseTokens commandSequence2 += self.generateVP9Pass2Tokens(int(quality)) + self.generateAudioEncodingTokens() diff --git a/src/ffx/helper.py b/src/ffx/helper.py index c0d8af9..ef447c8 100644 --- a/src/ffx/helper.py +++ b/src/ffx/helper.py @@ -15,8 +15,41 @@ DIFF_REMOVED_KEY = 'removed' DIFF_CHANGED_KEY = 'changed' DIFF_UNCHANGED_KEY = 'unchanged' +RICH_COLOR_PATTERN = '\[[a-z_]+\](.+)\[\/[a-z_]+\]' -def dictDiff(a : dict, b : dict): + +def dictDiff(a : dict, b : dict, ignoreKeys: list = [], removeKeys: list = []): + """ + ignoreKeys: Ignored keys are filtered from calculating diff at all + removeKeys: Override diff calculation to remove keys certainly + """ + + a_filtered = {k:v for k,v in a.items() if k not in ignoreKeys} + b_filtered = {k:v for k,v in b.items() if k not in ignoreKeys and k not in removeKeys} + + a_only = {k:v for k,v in a_filtered.items() if k not in b_filtered.keys()} + b_only = {k:v for k,v in b_filtered.items() if k not in a_filtered.keys()} + + a_b = set(a_filtered.keys()) & set(b_filtered.keys()) + + changed = {k:b_filtered[k] for k in a_b if a_filtered[k] != b_filtered[k]} + unchanged = {k:b_filtered[k] for k in a_b if a_filtered[k] == b_filtered[k]} + + diffResult = {} + + + if a_only: + diffResult[DIFF_REMOVED_KEY] = a_only + diffResult[DIFF_UNCHANGED_KEY] = unchanged + if b_only: + diffResult[DIFF_ADDED_KEY] = b_only + if changed: + diffResult[DIFF_CHANGED_KEY] = changed + + return diffResult + + +def dictKeysDiff(a : dict, b : dict): a_keys = set(a.keys()) b_keys = set(b.keys()) @@ -40,9 +73,10 @@ def dictDiff(a : dict, b : dict): return diffResult + def dictCache(element: dict, cache: list = []): for index in range(len(cache)): - diff = dictDiff(cache[index], element) + diff = dictKeysDiff(cache[index], element) if not diff: return index, cache cache.append(element) @@ -53,11 +87,13 @@ def setDiff(a : set, b : set) -> set: a_only = a - b b_only = b - a + a_and_b = a & b diffResult = {} if a_only: diffResult[DIFF_REMOVED_KEY] = a_only + diffResult[DIFF_UNCHANGED_KEY] = a_and_b if b_only: diffResult[DIFF_ADDED_KEY] = b_only @@ -187,3 +223,17 @@ def getEpisodeFileBasename(showName, # return ''.join(filenameTokens) + +def formatRichColor(text: str, color: str = None): + if color is None: + return text + else: + return f"[{color}]{text}[/{color}]" + +def removeRichColor(text: str): + richColorMatch = re.search(RICH_COLOR_PATTERN, text) + if richColorMatch is None: + return text + else: + return str(richColorMatch.group(1)) + diff --git a/src/ffx/media_descriptor.py b/src/ffx/media_descriptor.py index 619046c..e3bec9f 100644 --- a/src/ffx/media_descriptor.py +++ b/src/ffx/media_descriptor.py @@ -10,8 +10,6 @@ from ffx.track_codec import TrackCodec from ffx.track_descriptor import TrackDescriptor -from ffx.helper import dictDiff, DIFF_ADDED_KEY, DIFF_CHANGED_KEY, DIFF_REMOVED_KEY - class MediaDescriptor: """This class represents the structural content of a media file including streams and metadata""" @@ -318,80 +316,6 @@ class MediaDescriptor: ] - def compare(self, vsMediaDescriptor: Self): - - if not isinstance(vsMediaDescriptor, self.__class__): - self.__logger.error(f"MediaDescriptor.compare(): Argument is required to be of type {self.__class__}") - raise click.Abort() - - vsTags = vsMediaDescriptor.getTags() - tags = self.getTags() - - # HINT: Some tags differ per file, for example creation_time, so these are removed before diff - for emt in MediaDescriptor.EXCLUDED_MEDIA_TAGS: - if emt in tags.keys(): - del tags[emt] - if emt in vsTags.keys(): - del vsTags[emt] - - tagsDiff = dictDiff(vsTags, tags) - - compareResult = {} - - if tagsDiff: - compareResult[MediaDescriptor.TAGS_KEY] = tagsDiff - - # Target track configuration (from DB) - # tracks = self.getAllTrackDescriptors() - tracks = self.getAllTrackDescriptors() # filtern - numTracks = len(tracks) - - # Current track configuration (of file) - vsTracks = vsMediaDescriptor.getAllTrackDescriptors() - numVsTracks = len(vsTracks) - - maxNumOfTracks = max(numVsTracks, numTracks) - - trackCompareResult = {} - - for tp in range(maxNumOfTracks): - - #! - vsTrackIndex = tracks[tp].getSourceIndex() - - # Will trigger if tracks are missing in file - if tp > (numVsTracks - 1): - if DIFF_ADDED_KEY not in trackCompareResult.keys(): - trackCompareResult[DIFF_ADDED_KEY] = set() - trackCompareResult[DIFF_ADDED_KEY].add(tracks[tp].getIndex()) - continue - - # Will trigger if tracks are missing in DB definition - # New tracks will be added per update via this way - if tp > (numTracks - 1): - if DIFF_REMOVED_KEY not in trackCompareResult.keys(): - trackCompareResult[DIFF_REMOVED_KEY] = {} - trackCompareResult[DIFF_REMOVED_KEY][ - vsTracks[vsTrackIndex].getIndex() - ] = vsTracks[vsTrackIndex] - continue - - # assumption is made here that the track order will not change for all files of a sequence - trackDiff = tracks[tp].compare(vsTracks[vsTrackIndex]) - - if trackDiff: - if DIFF_CHANGED_KEY not in trackCompareResult.keys(): - trackCompareResult[DIFF_CHANGED_KEY] = {} - trackCompareResult[DIFF_CHANGED_KEY][ - vsTracks[vsTrackIndex].getIndex() - ] = trackDiff - - if trackCompareResult: - compareResult[MediaDescriptor.TRACKS_KEY] = trackCompareResult - - return compareResult - - def getImportFileTokens(self, use_sub_index: bool = True): importFileTokens = [] diff --git a/src/ffx/media_descriptor_change_set.py b/src/ffx/media_descriptor_change_set.py new file mode 100644 index 0000000..9a800c2 --- /dev/null +++ b/src/ffx/media_descriptor_change_set.py @@ -0,0 +1,266 @@ +import click + +from ffx.media_descriptor import MediaDescriptor +from ffx.track_descriptor import TrackDescriptor + +from ffx.helper import dictDiff, setDiff, DIFF_ADDED_KEY, DIFF_CHANGED_KEY, DIFF_REMOVED_KEY, DIFF_UNCHANGED_KEY + +from ffx.track_codec import TrackCodec +from ffx.track_disposition import TrackDisposition + + +class MediaDescriptorChangeSet(): + + TAGS_KEY = "tags" + TRACKS_KEY = "tracks" + DISPOSITION_SET_KEY = "disposition_set" + + TRACK_DESCRIPTOR_KEY = "track_descriptor" + + + def __init__(self, context, + targetMediaDescriptor: MediaDescriptor = None, + sourceMediaDescriptor: MediaDescriptor = None): + + self.__context = context + self.__logger = context['logger'] + + self.__configurationData = self.__context['config'].getData() + + metadataConfiguration = self.__configurationData['metadata'] if 'metadata' in self.__configurationData.keys() else {} + + self.__signatureTags = metadataConfiguration['signature'] if 'signature' in metadataConfiguration.keys() else {} + self.__removeGlobalKeys = metadataConfiguration['remove'] if 'remove' in metadataConfiguration.keys() else [] + self.__ignoreGlobalKeys = metadataConfiguration['ignore'] if 'ignore' in metadataConfiguration.keys() else [] + self.__removeTrackKeys = (metadataConfiguration['streams']['remove'] + if 'streams' in metadataConfiguration.keys() + and 'remove' in metadataConfiguration['streams'].keys() else []) + self.__ignoreTrackKeys = (metadataConfiguration['streams']['ignore'] + if 'streams' in metadataConfiguration.keys() + and 'ignore' in metadataConfiguration['streams'].keys() else []) + + + self.__changeSetObj = {} + + if targetMediaDescriptor is not None: + + sourceMediaTags = sourceMediaDescriptor.getTags() if sourceMediaDescriptor is not None else {} + targetMediaTags = targetMediaDescriptor.getTags() + + #!!# + tagsDiff = dictDiff(sourceMediaTags, + targetMediaTags, + ignoreKeys=self.__ignoreGlobalKeys, + removeKeys=self.__removeGlobalKeys) + + if tagsDiff: + self.__changeSetObj[MediaDescriptorChangeSet.TAGS_KEY] = tagsDiff + + + self.__targetTrackDescriptors = targetMediaDescriptor.getTrackDescriptors() + self.__numTargetTracks = len(self.__targetTrackDescriptors) + + # Current track configuration (of file) + self.__sourceTrackDescriptors = sourceMediaDescriptor.getTrackDescriptors() if sourceMediaDescriptor is not None else [] + self.__numSourceTracks = len(self.__sourceTrackDescriptors) + + maxNumOfTracks = max(self.__numSourceTracks, self.__numTargetTracks) + + trackCompareResult = {} + + + for trackIndex in range(maxNumOfTracks): + + correspondingSourceTrackDescriptors = [st for st in self.__sourceTrackDescriptors if st.getIndex() == trackIndex] + correspondingTargetTrackDescriptors = [tt for tt in self.__targetTrackDescriptors if tt.getIndex() == trackIndex] + + # Track present in target but not in source + if (not correspondingSourceTrackDescriptors + and correspondingTargetTrackDescriptors): + + if DIFF_ADDED_KEY not in trackCompareResult.keys(): + trackCompareResult[DIFF_ADDED_KEY] = {} + + trackCompareResult[DIFF_ADDED_KEY][trackIndex] = correspondingTargetTrackDescriptors[0] + continue + + # Track present in target but not in source + if (correspondingSourceTrackDescriptors + and not correspondingTargetTrackDescriptors): + + if DIFF_REMOVED_KEY not in trackCompareResult.keys(): + trackCompareResult[DIFF_REMOVED_KEY] = {} + + trackCompareResult[DIFF_REMOVED_KEY][trackIndex] = correspondingSourceTrackDescriptors[0] + continue + + if (correspondingSourceTrackDescriptors + and correspondingTargetTrackDescriptors): + + trackDiff = self.compareTracks(correspondingSourceTrackDescriptors[0], correspondingTargetTrackDescriptors[0]) + + if trackDiff: + if DIFF_CHANGED_KEY not in trackCompareResult.keys(): + trackCompareResult[DIFF_CHANGED_KEY] = {} + + trackCompareResult[DIFF_CHANGED_KEY][trackIndex] = trackDiff + + + if trackCompareResult: + self.__changeSetObj[MediaDescriptorChangeSet.TRACKS_KEY] = trackCompareResult + + + def compareTracks(self, + targetTrackDescriptor: TrackDescriptor, + sourceTrackDescriptor: TrackDescriptor = None): + + if not isinstance(targetTrackDescriptor, TrackDescriptor): + self.__logger.error(f"MediaDescriptorChangeSet.compareTracks(): Argument targetTrackDescriptor is required to be of type TrackDescriptor") + raise click.Abort() + + sourceTrackTags = sourceTrackDescriptor.getTags() if sourceTrackDescriptor is not None else {} + targetTrackTags = targetTrackDescriptor.getTags() + + trackCompareResult = {} + + tagsDiffResult = dictDiff(sourceTrackTags, + targetTrackTags, + ignoreKeys=self.__ignoreTrackKeys, + removeKeys=self.__removeTrackKeys) + + if tagsDiffResult: + trackCompareResult[MediaDescriptorChangeSet.TAGS_KEY] = tagsDiffResult + + sourceDispositions = sourceTrackDescriptor.getDispositionSet() + targetDispositions = targetTrackDescriptor.getDispositionSet() + + dispositionDiffResult = setDiff(sourceDispositions, targetDispositions) + + if dispositionDiffResult: + trackCompareResult[MediaDescriptorChangeSet.DISPOSITION_SET_KEY] = dispositionDiffResult + + if trackCompareResult: + trackCompareResult[MediaDescriptorChangeSet.TRACK_DESCRIPTOR_KEY] = targetTrackDescriptor + + return trackCompareResult + + + def generateDispositionTokens(self): + """ + #Example: -disposition:s:0 default -disposition:s:1 0 + """ + dispositionTokens = [] + + if MediaDescriptorChangeSet.TRACKS_KEY in self.__changeSetObj.keys(): + + if DIFF_ADDED_KEY in self.__changeSetObj[MediaDescriptorChangeSet.TRACKS_KEY].keys(): + addedTracks: dict = self.__changeSetObj[MediaDescriptorChangeSet.TRACKS_KEY][DIFF_ADDED_KEY] + trackDescriptor: TrackDescriptor + for trackDescriptor in addedTracks.values(): + + dispositionSet = trackDescriptor.getDispositionSet() + + if dispositionSet: + dispositionTokens += [f"-disposition:{trackDescriptor.getType().indicator()}:{trackDescriptor.getSubIndex()}", + '+'.join([d.label() for d in dispositionSet])] + + if DIFF_CHANGED_KEY in self.__changeSetObj[MediaDescriptorChangeSet.TRACKS_KEY].keys(): + changedTracks: dict = self.__changeSetObj[MediaDescriptorChangeSet.TRACKS_KEY][DIFF_CHANGED_KEY] + trackDiffObj: dict + for trackDiffObj in changedTracks.values(): + + addedDispositions = trackDiffObj[DIFF_ADDED_KEY] if DIFF_ADDED_KEY in trackDiffObj.keys() else set() + removedDispositions = trackDiffObj[DIFF_REMOVED_KEY] if DIFF_REMOVED_KEY in trackDiffObj.keys() else set() + unchangedDispositions = trackDiffObj[DIFF_UNCHANGED_KEY] if DIFF_UNCHANGED_KEY in trackDiffObj.keys() else set() + + targetDispositions = addedDispositions | unchangedDispositions + + streamIndicator = trackDescriptor.getType().indicator() + subIndex = trackDescriptor.getSubIndex() + + if targetDispositions: + dispositionTokens += [f"-disposition:{streamIndicator}:{subIndex}", '+'.join([d.label() for d in targetDispositions])] + if not targetDispositions and removedDispositions: + dispositionTokens += [f"-disposition:{streamIndicator}:{subIndex}", '0'] + + return dispositionTokens + + + def generateMetadataTokens(self): + + metadataTokens = [] + + if MediaDescriptorChangeSet.TAGS_KEY in self.__changeSetObj.keys(): + + addedMediaTags = (self.__changeSetObj[MediaDescriptorChangeSet.TAGS_KEY][DIFF_ADDED_KEY] + if DIFF_ADDED_KEY in self.__changeSetObj[MediaDescriptorChangeSet.TAGS_KEY].keys() else {}) + removedMediaTags = (self.__changeSetObj[MediaDescriptorChangeSet.TAGS_KEY][DIFF_REMOVED_KEY] + if DIFF_REMOVED_KEY in self.__changeSetObj[MediaDescriptorChangeSet.TAGS_KEY].keys() else {}) + changedMediaTags = (self.__changeSetObj[MediaDescriptorChangeSet.TAGS_KEY][DIFF_CHANGED_KEY] + if DIFF_CHANGED_KEY in self.__changeSetObj[MediaDescriptorChangeSet.TAGS_KEY].keys() else {}) + + outputMediaTags = addedMediaTags | changedMediaTags + + if (not 'no_signature' in self.__context.keys() + or not self.__context['no_signature']): + outputMediaTags = outputMediaTags | self.__signatureTags + + # outputMediaTags = {k:v for k,v in outputMediaTags.items() if k not in self.__removeGlobalKeys} + + for tagKey, tagValue in outputMediaTags.items(): + metadataTokens += [f"-metadata:g", + f"{tagKey}={tagValue}"] + + for tagKey, tagValue in changedMediaTags.items(): + metadataTokens += [f"-metadata:g", + f"{tagKey}={tagValue}"] + + for removeKey in removedMediaTags.keys(): + metadataTokens += [f"-metadata:g", + f"{removeKey}="] + + + if MediaDescriptorChangeSet.TRACKS_KEY in self.__changeSetObj.keys(): + + if DIFF_ADDED_KEY in self.__changeSetObj[MediaDescriptorChangeSet.TRACKS_KEY].keys(): + addedTracks: dict = self.__changeSetObj[MediaDescriptorChangeSet.TRACKS_KEY][DIFF_ADDED_KEY] + trackDescriptor: TrackDescriptor + for trackDescriptor in addedTracks.values(): + for tagKey, tagValue in trackDescriptor.getTags().items(): + if not tagKey in self.__removeTrackKeys: + metadataTokens += [f"-metadata:s:{trackDescriptor.getType().indicator()}" + + f":{trackDescriptor.getSubIndex()}", + f"{tagKey}={tagValue}"] + + if DIFF_CHANGED_KEY in self.__changeSetObj[MediaDescriptorChangeSet.TRACKS_KEY].keys(): + changedTracks: dict = self.__changeSetObj[MediaDescriptorChangeSet.TRACKS_KEY][DIFF_CHANGED_KEY] + trackDiffObj: dict + for trackDiffObj in changedTracks.values(): + + addedTrackTags = trackDiffObj[DIFF_ADDED_KEY] if DIFF_ADDED_KEY in trackDiffObj.keys() else {} + changedTrackTags = trackDiffObj[DIFF_CHANGED_KEY] if DIFF_CHANGED_KEY in trackDiffObj.keys() else {} + removedTrackTags = trackDiffObj[DIFF_REMOVED_KEY] if DIFF_REMOVED_KEY in trackDiffObj.keys() else {} + + # outputTrackTags = {k:v for k,v in (addedTrackTags | changedTrackTags).items() if k not in self.__removeTrackKeys} + outputTrackTags = addedTrackTags | changedTrackTags + + for tagKey, tagValue in outputTrackTags.items(): + metadataTokens += [f"-metadata:s:{trackDescriptor.getType().indicator()}" + + f":{trackDescriptor.getSubIndex()}", + f"{tagKey}={tagValue}"] + + for tagKey, tagValue in changedTrackTags.items(): + metadataTokens += [f"-metadata:s:{trackDescriptor.getType().indicator()}" + + f":{trackDescriptor.getSubIndex()}", + f"{tagKey}={tagValue}"] + + for removeKey in removedTrackTags.keys(): + metadataTokens += [f"-metadata:s:{trackDescriptor.getType().indicator()}" + + f":{trackDescriptor.getSubIndex()}", + f"{removeKey}="] + + return metadataTokens + + + def getChangeSetObj(self): + return self.__changeSetObj diff --git a/src/ffx/media_details_screen.py b/src/ffx/media_details_screen.py index 970b27c..96df884 100644 --- a/src/ffx/media_details_screen.py +++ b/src/ffx/media_details_screen.py @@ -27,7 +27,9 @@ from textual.widgets._data_table import CellDoesNotExist from ffx.media_descriptor import MediaDescriptor from ffx.file_properties import FileProperties -from ffx.helper import DIFF_ADDED_KEY, DIFF_CHANGED_KEY, DIFF_REMOVED_KEY +from ffx.media_descriptor_change_set import MediaDescriptorChangeSet + +from ffx.helper import formatRichColor, DIFF_ADDED_KEY, DIFF_CHANGED_KEY, DIFF_REMOVED_KEY, DIFF_UNCHANGED_KEY # Screen[dict[int, str, int]] @@ -38,7 +40,7 @@ class MediaDetailsScreen(Screen): Grid { grid-size: 5 8; grid-rows: 8 2 2 2 2 8 2 2 8; - grid-columns: 25 25 120 10 75; + grid-columns: 15 25 90 10 105; height: 100%; width: 100%; padding: 1; @@ -110,6 +112,19 @@ class MediaDetailsScreen(Screen): """ + TRACKS_TABLE_INDEX_COLUMN_LABEL = "Index" + TRACKS_TABLE_TYPE_COLUMN_LABEL = "Type" + TRACKS_TABLE_SUB_INDEX_COLUMN_LABEL = "SubIndex" + TRACKS_TABLE_CODEC_COLUMN_LABEL = "Codec" + TRACKS_TABLE_LAYOUT_COLUMN_LABEL = "Layout" + TRACKS_TABLE_LANGUAGE_COLUMN_LABEL = "Language" + TRACKS_TABLE_TITLE_COLUMN_LABEL = "Title" + TRACKS_TABLE_DEFAULT_COLUMN_LABEL = "Default" + TRACKS_TABLE_FORCED_COLUMN_LABEL = "Forced" + + DIFFERENCES_TABLE_DIFFERENCES_COLUMN_LABEL = 'Differences (file->db/output)' + + BINDINGS = [ ("n", "new_pattern", "New Pattern"), ("u", "update_pattern", "Update Pattern"), @@ -123,6 +138,22 @@ class MediaDetailsScreen(Screen): self.context = self.app.getContext() self.Session = self.context['database']['session'] # convenience + + self.__configurationData = self.context['config'].getData() + + metadataConfiguration = self.__configurationData['metadata'] if 'metadata' in self.__configurationData.keys() else {} + + self.__signatureTags = metadataConfiguration['signature'] if 'signature' in metadataConfiguration.keys() else {} + self.__removeGlobalKeys = metadataConfiguration['remove'] if 'remove' in metadataConfiguration.keys() else [] + self.__ignoreGlobalKeys = metadataConfiguration['ignore'] if 'ignore' in metadataConfiguration.keys() else [] + self.__removeTrackKeys = (metadataConfiguration['streams']['remove'] + if 'streams' in metadataConfiguration.keys() + and 'remove' in metadataConfiguration['streams'].keys() else []) + self.__ignoreTrackKeys = (metadataConfiguration['streams']['ignore'] + if 'streams' in metadataConfiguration.keys() + and 'ignore' in metadataConfiguration['streams'].keys() else []) + + self.__pc = PatternController(context = self.context) self.__sc = ShowController(context = self.context) self.__tc = TrackController(context = self.context) @@ -191,9 +222,10 @@ class MediaDetailsScreen(Screen): # Enumerating differences between media descriptors # from file (=current) vs from stored in database (=target) try: - self.__mediaDifferences = self.__targetMediaDescriptor.compare(self.__currentMediaDescriptor) if self.__currentPattern is not None else {} + mdcs = MediaDescriptorChangeSet(self.context, self.__targetMediaDescriptor, self.__currentMediaDescriptor) + self.__mediaChangeSetObj = mdcs.getChangeSetObj() except ValueError: - self.__mediaDifferences = {} + self.__mediaChangeSetObj = {} def updateDifferences(self): @@ -202,74 +234,88 @@ class MediaDetailsScreen(Screen): self.differencesTable.clear() - if MediaDescriptor.TAGS_KEY in self.__mediaDifferences.keys(): - currentTags = self.__currentMediaDescriptor.getTags() - targetTags = self.__targetMediaDescriptor.getTags() + if MediaDescriptorChangeSet.TAGS_KEY in self.__mediaChangeSetObj.keys(): - if DIFF_ADDED_KEY in self.__mediaDifferences[MediaDescriptor.TAGS_KEY].keys(): - for addedTagKey in self.__mediaDifferences[MediaDescriptor.TAGS_KEY][DIFF_ADDED_KEY]: - row = (f"added media tag: key='{addedTagKey}' value='{targetTags[addedTagKey]}'",) - self.differencesTable.add_row(*map(str, row)) + if DIFF_ADDED_KEY in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TAGS_KEY].keys(): + for tagKey, tagValue in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TAGS_KEY][DIFF_ADDED_KEY].items(): + if tagKey not in self.__ignoreGlobalKeys: + row = (f"add media tag: key='{tagKey}' value='{tagValue}'",) + self.differencesTable.add_row(*map(str, row)) - if DIFF_REMOVED_KEY in self.__mediaDifferences[MediaDescriptor.TAGS_KEY].keys(): - for removedTagKey in self.__mediaDifferences[MediaDescriptor.TAGS_KEY][DIFF_REMOVED_KEY]: - row = (f"removed media tag: key='{removedTagKey}' value='{currentTags[removedTagKey]}'",) - self.differencesTable.add_row(*map(str, row)) + if DIFF_REMOVED_KEY in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TAGS_KEY].keys(): + for tagKey, tagValue in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TAGS_KEY][DIFF_REMOVED_KEY].items(): + if tagKey not in self.__ignoreGlobalKeys and tagKey not in self.__removeGlobalKeys: + row = (f"remove media tag: key='{tagKey}' value='{tagValue}'",) + self.differencesTable.add_row(*map(str, row)) - if DIFF_CHANGED_KEY in self.__mediaDifferences[MediaDescriptor.TAGS_KEY].keys(): - for changedTagKey in self.__mediaDifferences[MediaDescriptor.TAGS_KEY][DIFF_CHANGED_KEY]: - row = (f"changed media tag: key='{changedTagKey}' value='{currentTags[changedTagKey]}'->'{targetTags[changedTagKey]}'",) - self.differencesTable.add_row(*map(str, row)) + if DIFF_CHANGED_KEY in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TAGS_KEY].keys(): + for tagKey, tagValue in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TAGS_KEY][DIFF_CHANGED_KEY].items(): + if tagKey not in self.__ignoreGlobalKeys: + row = (f"change media tag: key='{tagKey}' value='{tagValue}'",) + self.differencesTable.add_row(*map(str, row)) - if MediaDescriptor.TRACKS_KEY in self.__mediaDifferences.keys(): - currentTracks = self.__currentMediaDescriptor.getAllTrackDescriptors() # 0,1,2,3 - targetTracks = self.__targetMediaDescriptor.getAllTrackDescriptors() # 0 <- from DB + if MediaDescriptorChangeSet.TRACKS_KEY in self.__mediaChangeSetObj.keys(): - if DIFF_ADDED_KEY in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY].keys(): + if DIFF_ADDED_KEY in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TRACKS_KEY].keys(): - #raise click.ClickException(f"add track {self.__mediaDifferences[MediaDescriptor.TRACKS_KEY][DIFF_ADDED_KEY]}") - for addedTrackIndex in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY][DIFF_ADDED_KEY]: - addedTrack : Track = targetTracks[addedTrackIndex] - row = (f"added {addedTrack.getType().label()} track: index={addedTrackIndex} lang={addedTrack.getLanguage().threeLetter()}",) + trackDescriptor: TrackDescriptor + for trackIndex, trackDescriptor in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TRACKS_KEY][DIFF_ADDED_KEY].items(): + row = (f"add {trackDescriptor.getType().label()} track: index={trackDescriptor.getIndex()} lang={trackDescriptor.getLanguage().threeLetter()}",) self.differencesTable.add_row(*map(str, row)) - if DIFF_REMOVED_KEY in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY].keys(): - for removedTrackIndex in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY][DIFF_REMOVED_KEY]: - row = (f"removed track: index={removedTrackIndex}",) + if DIFF_REMOVED_KEY in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TRACKS_KEY].keys(): + for trackIndex, trackDescriptor in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TRACKS_KEY][DIFF_REMOVED_KEY].items(): + row = (f"remove stream #{trackIndex}",) self.differencesTable.add_row(*map(str, row)) - if DIFF_CHANGED_KEY in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY].keys(): - for changedTrackIndex in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY][DIFF_CHANGED_KEY].keys(): + if DIFF_CHANGED_KEY in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TRACKS_KEY].keys(): + + changedTracks: dict = self.__mediaChangeSetObj[MediaDescriptorChangeSet.TRACKS_KEY][DIFF_CHANGED_KEY] - changedTrack : Track = targetTracks[changedTrackIndex] - changedTrackDiff : dict = self.__mediaDifferences[MediaDescriptor.TRACKS_KEY][DIFF_CHANGED_KEY][changedTrackIndex] + targetTrackDescriptors = self.__targetMediaDescriptor.getTrackDescriptors() - if MediaDescriptor.TAGS_KEY in changedTrackDiff.keys(): + trackDiffObj: dict + for trackIndex, trackDiffObj in changedTracks.items(): - if DIFF_ADDED_KEY in changedTrackDiff[MediaDescriptor.TAGS_KEY]: - for addedTagKey in changedTrackDiff[MediaDescriptor.TAGS_KEY][DIFF_ADDED_KEY]: - addedTagValue = changedTrack.getTags()[addedTagKey] - row = (f"changed {changedTrack.getType().label()} track index={changedTrackIndex} added key={addedTagKey} value={addedTagValue}",) - self.differencesTable.add_row(*map(str, row)) + ttd: TrackDescriptor = targetTrackDescriptors[trackIndex] - if DIFF_REMOVED_KEY in changedTrackDiff[MediaDescriptor.TAGS_KEY]: - for removedTagKey in changedTrackDiff[MediaDescriptor.TAGS_KEY][DIFF_REMOVED_KEY]: - row = (f"changed {changedTrack.getType().label()} track index={changedTrackIndex} removed key={removedTagKey}",) - self.differencesTable.add_row(*map(str, row)) - if TrackDescriptor.DISPOSITION_SET_KEY in changedTrackDiff.keys(): + if MediaDescriptorChangeSet.TAGS_KEY in trackDiffObj.keys(): - if DIFF_ADDED_KEY in changedTrackDiff[TrackDescriptor.DISPOSITION_SET_KEY]: - for addedDisposition in changedTrackDiff[TrackDescriptor.DISPOSITION_SET_KEY][DIFF_ADDED_KEY]: - row = (f"changed {changedTrack.getType().label()} track index={changedTrackIndex} added disposition={addedDisposition.label()}",) - self.differencesTable.add_row(*map(str, row)) + removedTags = (trackDiffObj[MediaDescriptorChangeSet.TAGS_KEY][DIFF_REMOVED_KEY] + if DIFF_REMOVED_KEY in trackDiffObj[MediaDescriptorChangeSet.TAGS_KEY].keys() else {}) + for tagKey, tagValue in removedTags.items(): + row = (f"change stream #{ttd.getIndex()} ({ttd.getType().label()}:{ttd.getSubIndex()}) remove key={tagKey} value={tagValue}",) + self.differencesTable.add_row(*map(str, row)) - if DIFF_REMOVED_KEY in changedTrackDiff[TrackDescriptor.DISPOSITION_SET_KEY]: - for removedDisposition in changedTrackDiff[TrackDescriptor.DISPOSITION_SET_KEY][DIFF_REMOVED_KEY]: - row = (f"changed {changedTrack.getType().label()} track index={changedTrackIndex} removed disposition={removedDisposition.label()}",) - self.differencesTable.add_row(*map(str, row)) + addedTags = (trackDiffObj[MediaDescriptorChangeSet.TAGS_KEY][DIFF_ADDED_KEY] + if DIFF_ADDED_KEY in trackDiffObj[MediaDescriptorChangeSet.TAGS_KEY].keys() else {}) + for tagKey, tagValue in addedTags.items(): + row = (f"change stream #{ttd.getIndex()} ({ttd.getType().label()}:{ttd.getSubIndex()}) add key={tagKey} value={tagValue}",) + self.differencesTable.add_row(*map(str, row)) + + changedTags = (trackDiffObj[MediaDescriptorChangeSet.TAGS_KEY][DIFF_CHANGED_KEY] + if DIFF_CHANGED_KEY in trackDiffObj[MediaDescriptorChangeSet.TAGS_KEY].keys() else {}) + for tagKey, tagValue in changedTags.items(): + row = (f"change stream #{ttd.getIndex()} ({ttd.getType().label()}:{ttd.getSubIndex()}) change key={tagKey} value={tagValue}",) + self.differencesTable.add_row(*map(str, row)) + + + if MediaDescriptorChangeSet.DISPOSITION_SET_KEY in trackDiffObj.keys(): + + addedDispositions = (trackDiffObj[MediaDescriptorChangeSet.DISPOSITION_SET_KEY][DIFF_ADDED_KEY] + if DIFF_ADDED_KEY in trackDiffObj[MediaDescriptorChangeSet.DISPOSITION_SET_KEY].keys() else set()) + for ad in addedDispositions: + row = (f"change stream #{ttd.getIndex()} ({ttd.getType().label()}:{ttd.getSubIndex()}) add disposition={ad.label()}",) + self.differencesTable.add_row(*map(str, row)) + + removedDispositions = (trackDiffObj[MediaDescriptorChangeSet.DISPOSITION_SET_KEY][DIFF_REMOVED_KEY] + if DIFF_REMOVED_KEY in trackDiffObj[MediaDescriptorChangeSet.DISPOSITION_SET_KEY].keys() else set()) + for rd in removedDispositions: + row = (f"change stream #{ttd.getIndex()} ({ttd.getType().label()}:{ttd.getSubIndex()}) remove disposition={rd.label()}",) + self.differencesTable.add_row(*map(str, row)) def on_mount(self): @@ -283,7 +329,14 @@ class MediaDetailsScreen(Screen): self.showsTable.add_row(*map(str, row)) for mediaTagKey, mediaTagValue in self.__currentMediaDescriptor.getTags().items(): - row = (mediaTagKey, mediaTagValue) # Convert each element to a string before adding + + textColor = None + if mediaTagKey in self.__ignoreGlobalKeys: + textColor = 'blue' + if mediaTagKey in self.__removeGlobalKeys: + textColor = 'red' + + row = (formatRichColor(mediaTagKey, textColor), formatRichColor(mediaTagValue, textColor)) # Convert each element to a string before adding self.mediaTagsTable.add_row(*map(str, row)) self.updateTracks() @@ -352,7 +405,7 @@ class MediaDetailsScreen(Screen): # Define the columns with headers self.column_key_show_id = self.showsTable.add_column("ID", width=10) - self.column_key_show_name = self.showsTable.add_column("Name", width=50) + self.column_key_show_name = self.showsTable.add_column("Name", width=80) self.column_key_show_year = self.showsTable.add_column("Year", width=10) self.showsTable.cursor_type = 'row' @@ -361,8 +414,8 @@ class MediaDetailsScreen(Screen): self.mediaTagsTable = DataTable(classes="two") # Define the columns with headers - self.column_key_track_tag_key = self.mediaTagsTable.add_column("Key", width=50) - self.column_key_track_tag_value = self.mediaTagsTable.add_column("Value", width=100) + self.column_key_track_tag_key = self.mediaTagsTable.add_column("Key", width=30) + self.column_key_track_tag_value = self.mediaTagsTable.add_column("Value", width=70) self.mediaTagsTable.cursor_type = 'row' @@ -370,15 +423,15 @@ class MediaDetailsScreen(Screen): self.tracksTable = DataTable(classes="two") # Define the columns with headers - self.column_key_track_index = self.tracksTable.add_column("Index", width=5) - self.column_key_track_type = self.tracksTable.add_column("Type", width=10) - self.column_key_track_sub_index = self.tracksTable.add_column("SubIndex", width=8) - self.column_key_track_codec = self.tracksTable.add_column("Codec", width=10) - self.column_key_track_layout = self.tracksTable.add_column("Layout", width=10) - self.column_key_track_language = self.tracksTable.add_column("Language", width=15) - self.column_key_track_title = self.tracksTable.add_column("Title", width=48) - self.column_key_track_default = self.tracksTable.add_column("Default", width=8) - self.column_key_track_forced = self.tracksTable.add_column("Forced", width=8) + self.column_key_track_index = self.tracksTable.add_column(MediaDetailsScreen.TRACKS_TABLE_INDEX_COLUMN_LABEL, width=5) + self.column_key_track_type = self.tracksTable.add_column(MediaDetailsScreen.TRACKS_TABLE_TYPE_COLUMN_LABEL, width=10) + self.column_key_track_sub_index = self.tracksTable.add_column(MediaDetailsScreen.TRACKS_TABLE_SUB_INDEX_COLUMN_LABEL, width=8) + self.column_key_track_codec = self.tracksTable.add_column(MediaDetailsScreen.TRACKS_TABLE_CODEC_COLUMN_LABEL, width=10) + self.column_key_track_layout = self.tracksTable.add_column(MediaDetailsScreen.TRACKS_TABLE_LAYOUT_COLUMN_LABEL, width=10) + self.column_key_track_language = self.tracksTable.add_column(MediaDetailsScreen.TRACKS_TABLE_LANGUAGE_COLUMN_LABEL, width=15) + self.column_key_track_title = self.tracksTable.add_column(MediaDetailsScreen.TRACKS_TABLE_TITLE_COLUMN_LABEL, width=48) + self.column_key_track_default = self.tracksTable.add_column(MediaDetailsScreen.TRACKS_TABLE_DEFAULT_COLUMN_LABEL, width=8) + self.column_key_track_forced = self.tracksTable.add_column(MediaDetailsScreen.TRACKS_TABLE_FORCED_COLUMN_LABEL, width=8) self.tracksTable.cursor_type = 'row' @@ -387,7 +440,7 @@ class MediaDetailsScreen(Screen): self.differencesTable = DataTable(id='differences-table') # classes="triple" # Define the columns with headers - self.column_key_differences = self.differencesTable.add_column("Differences (file->db)", width=70) + self.column_key_differences = self.differencesTable.add_column(MediaDetailsScreen.DIFFERENCES_TABLE_DIFFERENCES_COLUMN_LABEL, width=100) self.differencesTable.cursor_type = 'row' @@ -439,15 +492,15 @@ class MediaDetailsScreen(Screen): yield Footer() - def getPatternDescriptorFromInput(self): - """Returns show id and pattern from corresponding inputs""" - patternDescriptor = {} + def getPatternObjFromInput(self): + """Returns show id and pattern as obj from corresponding inputs""" + patternObj = {} try: - patternDescriptor['show_id'] = self.getSelectedShowDescriptor().getId() - patternDescriptor['pattern'] = str(self.query_one("#pattern_input", Input).value) + patternObj['show_id'] = self.getSelectedShowDescriptor().getId() + patternObj['pattern'] = str(self.query_one("#pattern_input", Input).value) except: - pass - return patternDescriptor + return {} + return patternObj def on_button_pressed(self, event: Button.Pressed) -> None: @@ -526,6 +579,7 @@ class MediaDetailsScreen(Screen): def handle_new_pattern(self, showDescriptor: ShowDescriptor): + """""" if type(showDescriptor) is not ShowDescriptor: raise TypeError("MediaDetailsScreen.handle_new_pattern(): Argument 'showDescriptor' has to be of type ShowDescriptor") @@ -541,21 +595,27 @@ class MediaDetailsScreen(Screen): if showRowIndex is not None: self.showsTable.move_cursor(row=showRowIndex) - patternDescriptor = self.getPatternDescriptorFromInput() + patternObj = self.getPatternObjFromInput() - if patternDescriptor: - patternId = self.__pc.addPattern(patternDescriptor) + if patternObj: + patternId = self.__pc.addPattern(patternObj) if patternId: self.highlightPattern(False) for tagKey, tagValue in self.__currentMediaDescriptor.getTags().items(): - self.__tac.updateMediaTag(patternId, tagKey, tagValue) + + # Filter tags that make no sense to preserve + if tagKey not in self.__ignoreGlobalKeys and not tagKey in self.__removeGlobalKeys: + self.__tac.updateMediaTag(patternId, tagKey, tagValue) for trackDescriptor in self.__currentMediaDescriptor.getAllTrackDescriptors(): self.__tc.addTrack(trackDescriptor, patternId = patternId) def action_new_pattern(self): + """Adding new patterns + + If the corresponding show does not exists in DB it is added beforehand""" selectedShowDescriptor = self.getSelectedShowDescriptor() @@ -568,90 +628,104 @@ class MediaDetailsScreen(Screen): def action_update_pattern(self): - """When updating the database the actions must reverse the difference (eq to diff db->file)""" + """Updating patterns + + When updating the database the actions must reverse the difference (eq to diff db->file)""" if self.__currentPattern is not None: - patternDescriptor = self.getPatternDescriptorFromInput() - if (patternDescriptor - and self.__currentPattern.getPattern() != patternDescriptor['pattern']): - return self.__pc.updatePattern(self.__currentPattern.getId(), patternDescriptor) + patternObj = self.getPatternObjFromInput() + if (patternObj + and self.__currentPattern.getPattern() != patternObj['pattern']): + return self.__pc.updatePattern(self.__currentPattern.getId(), patternObj) self.loadProperties() - if MediaDescriptor.TAGS_KEY in self.__mediaDifferences.keys(): + # __mediaChangeSetObj is file vs database + if MediaDescriptorChangeSet.TAGS_KEY in self.__mediaChangeSetObj.keys(): - if DIFF_ADDED_KEY in self.__mediaDifferences[MediaDescriptor.TAGS_KEY].keys(): - for addedTagKey in self.__mediaDifferences[MediaDescriptor.TAGS_KEY][DIFF_ADDED_KEY]: + if DIFF_ADDED_KEY in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TAGS_KEY].keys(): + for addedTagKey in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TAGS_KEY][DIFF_ADDED_KEY].keys(): + # click.ClickException(f"delete media tag patternId={self.__currentPattern.getId()} addedTagKey={addedTagKey}") self.__tac.deleteMediaTagByKey(self.__currentPattern.getId(), addedTagKey) - if DIFF_REMOVED_KEY in self.__mediaDifferences[MediaDescriptor.TAGS_KEY].keys(): - for removedTagKey in self.__mediaDifferences[MediaDescriptor.TAGS_KEY][DIFF_REMOVED_KEY]: + if DIFF_REMOVED_KEY in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TAGS_KEY].keys(): + for removedTagKey in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TAGS_KEY][DIFF_REMOVED_KEY].keys(): currentTags = self.__currentMediaDescriptor.getTags() + # click.ClickException(f"delete media tag patternId={self.__currentPattern.getId()} removedTagKey={removedTagKey} currentTags={currentTags[removedTagKey]}") self.__tac.updateMediaTag(self.__currentPattern.getId(), removedTagKey, currentTags[removedTagKey]) - if DIFF_CHANGED_KEY in self.__mediaDifferences[MediaDescriptor.TAGS_KEY].keys(): - for changedTagKey in self.__mediaDifferences[MediaDescriptor.TAGS_KEY][DIFF_CHANGED_KEY]: + if DIFF_CHANGED_KEY in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TAGS_KEY].keys(): + for changedTagKey in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TAGS_KEY][DIFF_CHANGED_KEY].keys(): currentTags = self.__currentMediaDescriptor.getTags() + # click.ClickException(f"delete media tag patternId={self.__currentPattern.getId()} changedTagKey={changedTagKey} currentTags={currentTags[changedTagKey]}") self.__tac.updateMediaTag(self.__currentPattern.getId(), changedTagKey, currentTags[changedTagKey]) - if MediaDescriptor.TRACKS_KEY in self.__mediaDifferences.keys(): + if MediaDescriptorChangeSet.TRACKS_KEY in self.__mediaChangeSetObj.keys(): - if DIFF_ADDED_KEY in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY].keys(): + if DIFF_ADDED_KEY in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TRACKS_KEY].keys(): - for addedTrackIndex in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY][DIFF_ADDED_KEY]: - targetTracks = [t for t in self.__targetMediaDescriptor.getAllTrackDescriptors() if t.getIndex() == addedTrackIndex] - if targetTracks: - self.__tc.deleteTrack(targetTracks[0].getId()) # id + for trackIndex, trackDescriptor in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TRACKS_KEY][DIFF_ADDED_KEY].items(): + #targetTracks = [t for t in self.__targetMediaDescriptor.getAllTrackDescriptors() if t.getIndex() == addedTrackIndex] + # if targetTracks: + # self.__tc.deleteTrack(targetTracks[0].getId()) # id + # self.__tc.deleteTrack(targetTracks[0].getId()) + self.__tc.addTrack(trackDescriptor, patternId = self.__currentPattern.getId()) - if DIFF_REMOVED_KEY in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY].keys(): - for removedTrackIndex, removedTrack in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY][DIFF_REMOVED_KEY].items(): - + if DIFF_REMOVED_KEY in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TRACKS_KEY].keys(): + trackDescriptor: TrackDescriptor + for trackIndex, trackDescriptor in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TRACKS_KEY][DIFF_REMOVED_KEY].items(): # Track per inspect/update hinzufügen - self.__tc.addTrack(removedTrack, patternId = self.__currentPattern.getId()) + #self.__tc.addTrack(removedTrack, patternId = self.__currentPattern.getId()) + self.__tc.deleteTrack(trackDescriptor.getId()) - if DIFF_CHANGED_KEY in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY].keys(): + if DIFF_CHANGED_KEY in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TRACKS_KEY].keys(): # [vsTracks[tp].getIndex()] = trackDiff - for changedTrackIndex, changedTrackDiff in self.__mediaDifferences[MediaDescriptor.TRACKS_KEY][DIFF_CHANGED_KEY].items(): + for trackIndex, trackDiff in self.__mediaChangeSetObj[MediaDescriptorChangeSet.TRACKS_KEY][DIFF_CHANGED_KEY].items(): - changedTargetTracks = [t for t in self.__targetMediaDescriptor.getAllTrackDescriptors() if t.getIndex() == changedTrackIndex] - changedTargeTrackId = changedTargetTracks[0].getId() if changedTargetTracks else None - changedTargetTrackIndex = changedTargetTracks[0].getIndex() if changedTargetTracks else None + targetTracks = [t for t in self.__targetMediaDescriptor.getTrackDescriptors() if t.getIndex() == trackIndex] + targetTrackId = targetTracks[0].getId() if targetTracks else None + targetTrackIndex = targetTracks[0].getIndex() if targetTracks else None - changedCurrentTracks = [t for t in self.__currentMediaDescriptor.getAllTrackDescriptors() if t.getIndex() == changedTrackIndex] + changedCurrentTracks = [t for t in self.__currentMediaDescriptor.getTrackDescriptors() if t.getIndex() == trackIndex] # changedCurrentTrackId #HINT: Undefined as track descriptors do not come from file with track_id - if TrackDescriptor.TAGS_KEY in changedTrackDiff.keys(): - changedTrackTagsDiff = changedTrackDiff[TrackDescriptor.TAGS_KEY] + if TrackDescriptor.TAGS_KEY in trackDiff.keys(): + tagsDiff = trackDiff[TrackDescriptor.TAGS_KEY] + + if DIFF_ADDED_KEY in tagsDiff.keys(): + for tagKey, tagValue in tagsDiff[DIFF_ADDED_KEY].items(): + + # if targetTracks: + # self.__tac.deleteTrackTagByKey(targetTrackId, addedTrackTagKey) + self.__tac.updateTrackTag(targetTrackId, tagKey, tagValue) - if DIFF_ADDED_KEY in changedTrackTagsDiff.keys(): - for addedTrackTagKey in changedTrackTagsDiff[DIFF_ADDED_KEY]: - if changedTargetTracks: - self.__tac.deleteTrackTagByKey(changedTargeTrackId, addedTrackTagKey) + if DIFF_REMOVED_KEY in tagsDiff.keys(): + for tagKey, tagValue in tagsDiff[DIFF_REMOVED_KEY].items(): + # if changedCurrentTracks: + # self.__tac.updateTrackTag(targetTrackId, removedTrackTagKey, changedCurrentTracks[0].getTags()[removedTrackTagKey]) + self.__tac.deleteTrackTagByKey(targetTrackId, tagKey) - if DIFF_REMOVED_KEY in changedTrackTagsDiff.keys(): - for removedTrackTagKey in changedTrackTagsDiff[DIFF_REMOVED_KEY]: - if changedCurrentTracks: - self.__tac.updateTrackTag(changedTargeTrackId, removedTrackTagKey, changedCurrentTracks[0].getTags()[removedTrackTagKey]) + if DIFF_CHANGED_KEY in tagsDiff.keys(): + for tagKey, tagValue in tagsDiff[DIFF_CHANGED_KEY].items(): + # if changedCurrentTracks: + # self.__tac.updateTrackTag(targetTrackId, changedTrackTagKey, changedCurrentTracks[0].getTags()[changedTrackTagKey]) + self.__tac.updateTrackTag(targetTrackId, tagKey, tagValue) - if DIFF_CHANGED_KEY in changedTrackTagsDiff.keys(): - for changedTrackTagKey in changedTrackTagsDiff[DIFF_CHANGED_KEY]: - if changedCurrentTracks: - self.__tac.updateTrackTag(changedTargeTrackId, changedTrackTagKey, changedCurrentTracks[0].getTags()[changedTrackTagKey]) - if TrackDescriptor.DISPOSITION_SET_KEY in changedTrackDiff.keys(): - changedTrackDispositionDiff = changedTrackDiff[TrackDescriptor.DISPOSITION_SET_KEY] + if TrackDescriptor.DISPOSITION_SET_KEY in trackDiff.keys(): + changedTrackDispositionDiff = trackDiff[TrackDescriptor.DISPOSITION_SET_KEY] if DIFF_ADDED_KEY in changedTrackDispositionDiff.keys(): - for changedTrackAddedDisposition in changedTrackDispositionDiff[DIFF_ADDED_KEY]: - if changedTargetTrackIndex is not None: - self.__tc.setDispositionState(self.__currentPattern.getId(), changedTargetTrackIndex, changedTrackAddedDisposition, False) + for changedDisposition in changedTrackDispositionDiff[DIFF_ADDED_KEY]: + if targetTrackIndex is not None: + self.__tc.setDispositionState(self.__currentPattern.getId(), targetTrackIndex, changedDisposition, True) if DIFF_REMOVED_KEY in changedTrackDispositionDiff.keys(): - for changedTrackRemovedDisposition in changedTrackDispositionDiff[DIFF_REMOVED_KEY]: - if changedTargetTrackIndex is not None: - self.__tc.setDispositionState(self.__currentPattern.getId(), changedTargetTrackIndex, changedTrackRemovedDisposition, True) + for changedDisposition in changedTrackDispositionDiff[DIFF_REMOVED_KEY]: + if targetTrackIndex is not None: + self.__tc.setDispositionState(self.__currentPattern.getId(), targetTrackIndex, changedDisposition, False) self.updateDifferences() @@ -660,11 +734,11 @@ class MediaDetailsScreen(Screen): def action_edit_pattern(self): - patternDescriptor = self.getPatternDescriptorFromInput() + patternObj = self.getPatternObjFromInput() - if patternDescriptor['pattern']: + if patternObj['pattern']: - selectedPatternId = self.__pc.findPattern(patternDescriptor) + selectedPatternId = self.__pc.findPattern(patternObj) if selectedPatternId is None: raise click.ClickException(f"MediaDetailsScreen.action_edit_pattern(): Pattern to edit has no id") diff --git a/src/ffx/pattern_controller.py b/src/ffx/pattern_controller.py index 4c31ea1..ae3c560 100644 --- a/src/ffx/pattern_controller.py +++ b/src/ffx/pattern_controller.py @@ -11,17 +11,20 @@ class PatternController(): self.Session = self.context['database']['session'] # convenience - def addPattern(self, patternDescriptor): + def addPattern(self, patternObj): + """Adds pattern to database from obj + + Returns database id or 0 if pattern already exists""" try: s = self.Session() - q = s.query(Pattern).filter(Pattern.show_id == int(patternDescriptor['show_id']), - Pattern.pattern == str(patternDescriptor['pattern'])) + q = s.query(Pattern).filter(Pattern.show_id == int(patternObj['show_id']), + Pattern.pattern == str(patternObj['pattern'])) if not q.count(): - pattern = Pattern(show_id = int(patternDescriptor['show_id']), - pattern = str(patternDescriptor['pattern'])) + pattern = Pattern(show_id = int(patternObj['show_id']), + pattern = str(patternObj['pattern'])) s.add(pattern) s.commit() return pattern.getId() @@ -34,7 +37,7 @@ class PatternController(): s.close() - def updatePattern(self, patternId, patternDescriptor): + def updatePattern(self, patternId, patternObj): try: s = self.Session() @@ -44,8 +47,8 @@ class PatternController(): pattern = q.first() - pattern.show_id = int(patternDescriptor['show_id']) - pattern.pattern = str(patternDescriptor['pattern']) + pattern.show_id = int(patternObj['show_id']) + pattern.pattern = str(patternObj['pattern']) s.commit() return True @@ -60,11 +63,11 @@ class PatternController(): - def findPattern(self, patternDescriptor): + def findPattern(self, patternObj): try: s = self.Session() - q = s.query(Pattern).filter(Pattern.show_id == int(patternDescriptor['show_id']), Pattern.pattern == str(patternDescriptor['pattern'])) + q = s.query(Pattern).filter(Pattern.show_id == int(patternObj['show_id']), Pattern.pattern == str(patternObj['pattern'])) if q.count(): pattern = q.first() diff --git a/src/ffx/pattern_details_screen.py b/src/ffx/pattern_details_screen.py index dab5cb6..955d91c 100644 --- a/src/ffx/pattern_details_screen.py +++ b/src/ffx/pattern_details_screen.py @@ -30,6 +30,8 @@ from ffx.file_properties import FileProperties from ffx.iso_language import IsoLanguage from ffx.audio_layout import AudioLayout +from ffx.helper import formatRichColor, removeRichColor + # Screen[dict[int, str, int]] class PatternDetailsScreen(Screen): @@ -103,6 +105,20 @@ class PatternDetailsScreen(Screen): self.context = self.app.getContext() self.Session = self.context['database']['session'] # convenience + self.__configurationData = self.context['config'].getData() + + metadataConfiguration = self.__configurationData['metadata'] if 'metadata' in self.__configurationData.keys() else {} + + self.__signatureTags = metadataConfiguration['signature'] if 'signature' in metadataConfiguration.keys() else {} + self.__removeGlobalKeys = metadataConfiguration['remove'] if 'remove' in metadataConfiguration.keys() else [] + self.__ignoreGlobalKeys = metadataConfiguration['ignore'] if 'ignore' in metadataConfiguration.keys() else [] + self.__removeTrackKeys = (metadataConfiguration['streams']['remove'] + if 'streams' in metadataConfiguration.keys() + and 'remove' in metadataConfiguration['streams'].keys() else []) + self.__ignoreTrackKeys = (metadataConfiguration['streams']['ignore'] + if 'streams' in metadataConfiguration.keys() + and 'ignore' in metadataConfiguration['streams'].keys() else []) + self.__pc = PatternController(context = self.context) self.__sc = ShowController(context = self.context) self.__tc = TrackController(context = self.context) @@ -218,7 +234,15 @@ class PatternDetailsScreen(Screen): tags = self.__tac.findAllMediaTags(self.__pattern.getId()) for tagKey, tagValue in tags.items(): - row = (tagKey, tagValue) + + textColor = None + if tagKey in self.__ignoreGlobalKeys: + textColor = 'blue' + if tagKey in self.__removeGlobalKeys: + textColor = 'red' + + # if tagKey not in self.__ignoreTrackKeys: + row = (formatRichColor(tagKey, textColor), formatRichColor(tagValue, textColor)) self.tagsTable.add_row(*map(str, row)) @@ -383,8 +407,8 @@ class PatternDetailsScreen(Screen): if row_key is not None: selected_tag_data = self.tagsTable.get_row(row_key) - tagKey = str(selected_tag_data[0]) - tagValue = str(selected_tag_data[1]) + tagKey = removeRichColor(selected_tag_data[0]) + tagValue = removeRichColor(selected_tag_data[1]) return tagKey, tagValue @@ -520,8 +544,10 @@ class PatternDetailsScreen(Screen): self.tracksTable.update_cell(row_key, self.column_key_track_language, trackDescriptor.getLanguage().label()) self.tracksTable.update_cell(row_key, self.column_key_track_title, trackDescriptor.getTitle()) - self.tracksTable.update_cell(row_key, self.column_key_track_default, 'Yes' if TrackDisposition.DEFAULT in trackDescriptor.getDispositionSet() else 'No') - self.tracksTable.update_cell(row_key, self.column_key_track_forced, 'Yes' if TrackDisposition.FORCED in trackDescriptor.getDispositionSet() else 'No') + self.tracksTable.update_cell(row_key, self.column_key_track_default, + 'Yes' if TrackDisposition.DEFAULT in trackDescriptor.getDispositionSet() else 'No') + self.tracksTable.update_cell(row_key, self.column_key_track_forced, + 'Yes' if TrackDisposition.FORCED in trackDescriptor.getDispositionSet() else 'No') except CellDoesNotExist: pass @@ -546,4 +572,6 @@ class PatternDetailsScreen(Screen): raise click.ClickException(f"PatternDetailsScreen.handle_delete_tag: pattern not set") if self.__tac.deleteMediaTagByKey(self.__pattern.getId(), tag[0]): - self.updateTags() + self.updateTags() + else: + raise click.ClickException('tag delete failed') diff --git a/src/ffx/show_details_screen.py b/src/ffx/show_details_screen.py index f732286..c0e2153 100644 --- a/src/ffx/show_details_screen.py +++ b/src/ffx/show_details_screen.py @@ -444,7 +444,7 @@ class ShowDetailsScreen(Screen): # Event handler for button press def on_button_pressed(self, event: Button.Pressed) -> None: - # Check if the button pressed is the one we are interested in + if event.button.id == "save_button": showDescriptor = self.getShowDescriptorFromInput() diff --git a/src/ffx/tag_controller.py b/src/ffx/tag_controller.py index 5257ac3..792dad7 100644 --- a/src/ffx/tag_controller.py +++ b/src/ffx/tag_controller.py @@ -68,7 +68,7 @@ class TagController(): s = self.Session() q = s.query(MediaTag).filter(MediaTag.pattern_id == int(patternId), - MediaTag.key == str(tagKey)) + MediaTag.key == str(tagKey)) if q.count(): tag = q.first() s.delete(tag) diff --git a/src/ffx/tag_delete_screen.py b/src/ffx/tag_delete_screen.py index f97e455..1956976 100644 --- a/src/ffx/tag_delete_screen.py +++ b/src/ffx/tag_delete_screen.py @@ -90,7 +90,7 @@ class TagDeleteScreen(Screen): if event.button.id == "delete_button": - tag = (self.__key, self.__value) + tag = (self.__key, self.__value) self.dismiss(tag) if event.button.id == "cancel_button": diff --git a/src/ffx/track_controller.py b/src/ffx/track_controller.py index d7a3898..5b1de31 100644 --- a/src/ffx/track_controller.py +++ b/src/ffx/track_controller.py @@ -19,6 +19,20 @@ class TrackController(): self.context = context self.Session = self.context['database']['session'] # convenience + self.__configurationData = self.context['config'].getData() + + metadataConfiguration = self.__configurationData['metadata'] if 'metadata' in self.__configurationData.keys() else {} + + self.__signatureTags = metadataConfiguration['signature'] if 'signature' in metadataConfiguration.keys() else {} + self.__removeGlobalKeys = metadataConfiguration['remove'] if 'remove' in metadataConfiguration.keys() else [] + self.__ignoreGlobalKeys = metadataConfiguration['ignore'] if 'ignore' in metadataConfiguration.keys() else [] + self.__removeTrackKeys = (metadataConfiguration['streams']['remove'] + if 'streams' in metadataConfiguration.keys() + and 'remove' in metadataConfiguration['streams'].keys() else []) + self.__ignoreTrackKeys = (metadataConfiguration['streams']['ignore'] + if 'streams' in metadataConfiguration.keys() + and 'ignore' in metadataConfiguration['streams'].keys() else []) + def addTrack(self, trackDescriptor : TrackDescriptor, patternId = None): @@ -40,10 +54,12 @@ class TrackController(): for k,v in trackDescriptor.getTags().items(): - tag = TrackTag(track_id = track.id, - key = k, - value = v) - s.add(tag) + # Filter tags that make no sense to preserve + if k not in self.__ignoreTrackKeys and k not in self.__removeTrackKeys: + tag = TrackTag(track_id = track.id, + key = k, + value = v) + s.add(tag) s.commit() except Exception as ex: diff --git a/src/ffx/track_descriptor.py b/src/ffx/track_descriptor.py index f45a332..c040b38 100644 --- a/src/ffx/track_descriptor.py +++ b/src/ffx/track_descriptor.py @@ -7,7 +7,7 @@ from .audio_layout import AudioLayout from .track_disposition import TrackDisposition from .track_codec import TrackCodec -from .helper import dictDiff, setDiff +# from .helper import dictDiff, setDiff class TrackDescriptor: @@ -321,24 +321,24 @@ class TrackDescriptor: else: self.__dispositionSet.discard(disposition) - def compare(self, vsTrackDescriptor: Self): - - compareResult = {} - - tagsDiffResult = dictDiff(vsTrackDescriptor.getTags(), self.getTags()) - - if tagsDiffResult: - compareResult[TrackDescriptor.TAGS_KEY] = tagsDiffResult - - vsDispositions = vsTrackDescriptor.getDispositionSet() - dispositions = self.getDispositionSet() - - dispositionDiffResult = setDiff(vsDispositions, dispositions) - - if dispositionDiffResult: - compareResult[TrackDescriptor.DISPOSITION_SET_KEY] = dispositionDiffResult - - return compareResult +# def compare(self, vsTrackDescriptor: Self): +# +# compareResult = {} +# +# tagsDiffResult = dictKeysDiff(vsTrackDescriptor.getTags(), self.getTags()) +# +# if tagsDiffResult: +# compareResult[TrackDescriptor.TAGS_KEY] = tagsDiffResult +# +# vsDispositions = vsTrackDescriptor.getDispositionSet() +# dispositions = self.getDispositionSet() +# +# dispositionDiffResult = setDiff(vsDispositions, dispositions) +# +# if dispositionDiffResult: +# compareResult[TrackDescriptor.DISPOSITION_SET_KEY] = dispositionDiffResult +# +# return compareResult def setExternalSourceFilePath(self, filePath: str): self.__externalSourceFilePath = str(filePath) diff --git a/src/ffx/track_details_screen.py b/src/ffx/track_details_screen.py index 10e6e64..e3a924a 100644 --- a/src/ffx/track_details_screen.py +++ b/src/ffx/track_details_screen.py @@ -24,6 +24,8 @@ from .tag_delete_screen import TagDeleteScreen from textual.widgets._data_table import CellDoesNotExist +from ffx.helper import formatRichColor, removeRichColor + # Screen[dict[int, str, int]] class TrackDetailsScreen(Screen): @@ -101,6 +103,21 @@ class TrackDetailsScreen(Screen): self.context = self.app.getContext() self.Session = self.context['database']['session'] # convenience + self.__configurationData = self.context['config'].getData() + + metadataConfiguration = self.__configurationData['metadata'] if 'metadata' in self.__configurationData.keys() else {} + + self.__signatureTags = metadataConfiguration['signature'] if 'signature' in metadataConfiguration.keys() else {} + self.__removeGlobalKeys = metadataConfiguration['remove'] if 'remove' in metadataConfiguration.keys() else [] + self.__ignoreGlobalKeys = metadataConfiguration['ignore'] if 'ignore' in metadataConfiguration.keys() else [] + self.__removeTrackKeys = (metadataConfiguration['streams']['remove'] + if 'streams' in metadataConfiguration.keys() + and 'remove' in metadataConfiguration['streams'].keys() else []) + self.__ignoreTrackKeys = (metadataConfiguration['streams']['ignore'] + if 'streams' in metadataConfiguration.keys() + and 'ignore' in metadataConfiguration['streams'].keys() else []) + + self.__tc = TrackController(context = self.context) self.__pc = PatternController(context = self.context) self.__tac = TagController(context = self.context) @@ -138,7 +155,14 @@ class TrackDetailsScreen(Screen): for k,v in trackTags.items(): if k != 'language' and k != 'title': - row = (k,v) + + textColor = None + if k in self.__ignoreTrackKeys: + textColor = 'blue' + if k in self.__removeTrackKeys: + textColor = 'red' + + row = (formatRichColor(k, textColor), formatRichColor(v, textColor)) self.trackTagsTable.add_row(*map(str, row)) @@ -328,8 +352,8 @@ class TrackDetailsScreen(Screen): if row_key is not None: selected_tag_data = self.trackTagsTable.get_row(row_key) - tagKey = str(selected_tag_data[0]) - tagValue = str(selected_tag_data[1]) + tagKey = removeRichColor(selected_tag_data[0]) + tagValue = removeRichColor(selected_tag_data[1]) return tagKey, tagValue