inc
This commit is contained in:
@@ -3,10 +3,13 @@ import click
|
||||
from typing import List, Self
|
||||
|
||||
from ffx.track_type import TrackType
|
||||
from ffx.track_disposition import TrackDisposition
|
||||
|
||||
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"""
|
||||
|
||||
@@ -14,11 +17,12 @@ class MediaDescriptor():
|
||||
TRACKS_KEY = 'tracks'
|
||||
|
||||
TRACK_DESCRIPTOR_LIST_KEY = 'track_descriptors'
|
||||
CLEAR_TAGS_KEY = 'clear_tags'
|
||||
CLEAR_TAGS_FLAG_KEY = 'clear_tags'
|
||||
|
||||
FFPROBE_DISPOSITION_KEY = 'disposition'
|
||||
FFPROBE_TAGS_KEY = 'tags'
|
||||
FFPROBE_CODEC_TYPE_KEY = 'codec_type'
|
||||
JELLYFIN_ORDER_FLAG_KEY = 'jellyfin_order'
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
|
||||
@@ -42,14 +46,64 @@ class MediaDescriptor():
|
||||
else:
|
||||
self.__trackDescriptors = []
|
||||
|
||||
if MediaDescriptor.CLEAR_TAGS_KEY in kwargs.keys():
|
||||
if type(kwargs[MediaDescriptor.CLEAR_TAGS_KEY]) is not bool:
|
||||
raise TypeError(f"MediaDescriptor.__init__(): Argument {MediaDescriptor.CLEAR_TAGS_KEY} is required to be of type bool")
|
||||
self.__clearTags = kwargs[MediaDescriptor.CLEAR_TAGS_KEY]
|
||||
if MediaDescriptor.CLEAR_TAGS_FLAG_KEY in kwargs.keys():
|
||||
if type(kwargs[MediaDescriptor.CLEAR_TAGS_FLAG_KEY]) is not bool:
|
||||
raise TypeError(f"MediaDescriptor.__init__(): Argument {MediaDescriptor.CLEAR_TAGS_FLAG_KEY} is required to be of type bool")
|
||||
self.__clearTags = kwargs[MediaDescriptor.CLEAR_TAGS_FLAG_KEY]
|
||||
else:
|
||||
self.__clearTags = False
|
||||
|
||||
if MediaDescriptor.JELLYFIN_ORDER_FLAG_KEY in kwargs.keys():
|
||||
if type(kwargs[MediaDescriptor.JELLYFIN_ORDER_FLAG_KEY]) is not bool:
|
||||
raise TypeError(f"MediaDescriptor.__init__(): Argument {MediaDescriptor.JELLYFIN_ORDER_FLAG_KEY} is required to be of type bool")
|
||||
self.__jellyfinOrder = kwargs[MediaDescriptor.JELLYFIN_ORDER_FLAG_KEY]
|
||||
else:
|
||||
self.__jellyfinOrder = False
|
||||
|
||||
|
||||
def __getReorderedTrackDescriptors(self):
|
||||
|
||||
videoTracks = [v for v in self.__trackDescriptors.copy() if v.getType() == TrackType.VIDEO]
|
||||
audioTracks = [a for a in self.__trackDescriptors.copy() if a.getType() == TrackType.AUDIO]
|
||||
subtitleTracks = [s for s in self.__trackDescriptors.copy() if s.getType() == TrackType.SUBTITLE]
|
||||
|
||||
videoDefaultTracks = [v for v in videoTracks if TrackDisposition.DEFAULT in v.getDispositionSet()]
|
||||
videoForcedTracks = [v for v in videoTracks if TrackDisposition.FORCED in v.getDispositionSet()]
|
||||
audioDefaultTracks = [a for a in audioTracks if TrackDisposition.DEFAULT in a.getDispositionSet()]
|
||||
audioForcedTracks = [a for a in audioTracks if TrackDisposition.FORCED in a.getDispositionSet()]
|
||||
subtitleDefaultTracks = [s for s in subtitleTracks if TrackDisposition.DEFAULT in s.getDispositionSet()]
|
||||
subtitleForcedTracks = [s for s in subtitleTracks if TrackDisposition.FORCED in s.getDispositionSet()]
|
||||
|
||||
if len(videoDefaultTracks) > 1:
|
||||
raise ValueError('MediaDescriptor.__getSourceIndexOrder(): More than one default video track is not supported')
|
||||
if len(videoForcedTracks) > 1:
|
||||
raise ValueError('MediaDescriptor.__getSourceIndexOrder(): More than one forced video track is not supported')
|
||||
if len(audioDefaultTracks) > 1:
|
||||
raise ValueError('MediaDescriptor.__getSourceIndexOrder(): More than one default audio track is not supported')
|
||||
if len(audioForcedTracks) > 1:
|
||||
raise ValueError('MediaDescriptor.__getSourceIndexOrder(): More than one forced audio track is not supported')
|
||||
if len(subtitleDefaultTracks) > 1:
|
||||
raise ValueError('MediaDescriptor.__getSourceIndexOrder(): More than one default subtitle track is not supported')
|
||||
if len(subtitleForcedTracks) > 1:
|
||||
raise ValueError('MediaDescriptor.__getSourceIndexOrder(): More than one forced subtitle track is not supported')
|
||||
|
||||
if self.__jellyfinOrder:
|
||||
if videoDefaultTracks:
|
||||
videoTracks.append(videoTracks.pop(videoTracks.index(videoDefaultTracks[0])))
|
||||
if audioDefaultTracks:
|
||||
audioTracks.append(audioTracks.pop(audioTracks.index(audioDefaultTracks[0])))
|
||||
if subtitleDefaultTracks:
|
||||
subtitleTracks.append(subtitleTracks.pop(subtitleTracks.index(subtitleDefaultTracks[0])))
|
||||
|
||||
reorderedTrackDescriptors = videoTracks + audioTracks + subtitleTracks
|
||||
orderedSourceTrackSequence = [t.getSourceIndex() for t in reorderedTrackDescriptors]
|
||||
|
||||
if len(set(orderedSourceTrackSequence)) < len(orderedSourceTrackSequence):
|
||||
raise ValueError(f"Multiple streams originating from the same source stream not supported")
|
||||
|
||||
return reorderedTrackDescriptors
|
||||
|
||||
|
||||
@classmethod
|
||||
def fromFfprobe(cls, formatData, streamData):
|
||||
|
||||
@@ -72,7 +126,8 @@ class MediaDescriptor():
|
||||
if trackType not in subIndexCounters.keys():
|
||||
subIndexCounters[trackType] = 0
|
||||
|
||||
kwargs[MediaDescriptor.TRACK_DESCRIPTOR_LIST_KEY].append(TrackDescriptor.fromFfprobe(streamObj, subIndex=subIndexCounters[trackType]))
|
||||
kwargs[MediaDescriptor.TRACK_DESCRIPTOR_LIST_KEY].append(TrackDescriptor.fromFfprobe(streamObj,
|
||||
subIndex=subIndexCounters[trackType]))
|
||||
subIndexCounters[trackType] += 1
|
||||
|
||||
|
||||
@@ -112,7 +167,8 @@ class MediaDescriptor():
|
||||
|
||||
|
||||
# Target track configuration (from DB)
|
||||
tracks = self.getAllTracks()
|
||||
#tracks = self.getAllTracks()
|
||||
tracks = self.__getReorderedTrackDescriptors()
|
||||
numTracks = len(tracks)
|
||||
|
||||
# Current track configuration (of file)
|
||||
@@ -134,6 +190,7 @@ class MediaDescriptor():
|
||||
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] = {}
|
||||
|
||||
@@ -158,6 +158,8 @@ class MediaDetailsScreen(Screen):
|
||||
# from file (=current) vs from stored in database (=target)
|
||||
self.__mediaDifferences = self.__targetMediaDescriptor.compare(self.__currentMediaDescriptor) if self.__currentPattern is not None else {}
|
||||
|
||||
#rtd = self.__targetMediaDescriptor.getReorderedTrackDescriptors()
|
||||
#raise click.ClickException(f"getReorderedTrackDescriptors={[r.getIndex() for r in rtd]}")
|
||||
|
||||
def updateDifferences(self):
|
||||
|
||||
@@ -242,6 +244,7 @@ class MediaDetailsScreen(Screen):
|
||||
row = (' ', '<New show>', ' ') # Convert each element to a string before adding
|
||||
self.showsTable.add_row(*map(str, row))
|
||||
|
||||
#TODO: Stürzt ab wenn keine Shows vorhanden sind. Onthefly Show add impl
|
||||
for show in self.__sc.getAllShows():
|
||||
row = (int(show.id), show.name, show.year) # Convert each element to a string before adding
|
||||
self.showsTable.add_row(*map(str, row))
|
||||
|
||||
@@ -32,7 +32,7 @@ class Track(Base):
|
||||
track_type = Column(Integer) # TrackType
|
||||
|
||||
index = Column(Integer)
|
||||
# sub_index = Column(Integer)
|
||||
source_index = Column(Integer)
|
||||
|
||||
# v1.x
|
||||
pattern_id = Column(Integer, ForeignKey('patterns.id', ondelete="CASCADE"))
|
||||
@@ -149,6 +149,9 @@ class Track(Base):
|
||||
def getIndex(self):
|
||||
return int(self.index) if self.index is not None else -1
|
||||
|
||||
def getSourceIndex(self):
|
||||
return int(self.source_index) if self.source_index is not None else -1
|
||||
|
||||
def getLanguage(self):
|
||||
tags = {t.key:t.value for t in self.track_tags}
|
||||
return IsoLanguage.findThreeLetter(tags['language']) if 'language' in tags.keys() else IsoLanguage.UNDEFINED
|
||||
@@ -182,6 +185,7 @@ class Track(Base):
|
||||
kwargs[TrackDescriptor.PATTERN_ID_KEY] = self.getPatternId()
|
||||
|
||||
kwargs[TrackDescriptor.INDEX_KEY] = self.getIndex()
|
||||
kwargs[TrackDescriptor.SOURCE_INDEX_KEY] = self.getSourceIndex()
|
||||
|
||||
if subIndex > -1:
|
||||
kwargs[TrackDescriptor.SUB_INDEX_KEY] = subIndex
|
||||
|
||||
@@ -31,6 +31,7 @@ class TrackController():
|
||||
track = Track(pattern_id = patId,
|
||||
track_type = int(trackDescriptor.getType().index()),
|
||||
index = int(trackDescriptor.getIndex()),
|
||||
source_index = int(trackDescriptor.getSourceIndex()),
|
||||
disposition_flags = int(TrackDisposition.toFlags(trackDescriptor.getDispositionSet())))
|
||||
|
||||
s.add(track)
|
||||
|
||||
@@ -10,6 +10,7 @@ class TrackDescriptor():
|
||||
|
||||
ID_KEY = 'id'
|
||||
INDEX_KEY = 'index'
|
||||
SOURCE_INDEX_KEY = 'source_index'
|
||||
SUB_INDEX_KEY = 'sub_index'
|
||||
PATTERN_ID_KEY = 'pattern_id'
|
||||
|
||||
@@ -46,6 +47,11 @@ class TrackDescriptor():
|
||||
else:
|
||||
self.__index = -1
|
||||
|
||||
if TrackDescriptor.SOURCE_INDEX_KEY in kwargs.keys() and type(kwargs[TrackDescriptor.SOURCE_INDEX_KEY]) is int:
|
||||
self.__sourceIndex = kwargs[TrackDescriptor.SOURCE_INDEX_KEY]
|
||||
else:
|
||||
self.__sourceIndex = self.__index
|
||||
|
||||
if TrackDescriptor.SUB_INDEX_KEY in kwargs.keys():
|
||||
if type(kwargs[TrackDescriptor.SUB_INDEX_KEY]) is not int:
|
||||
raise TypeError(f"TrackDesciptor.__init__(): Argument {TrackDescriptor.SUB_INDEX_KEY} is required to be of type int")
|
||||
@@ -136,6 +142,7 @@ class TrackDescriptor():
|
||||
kwargs = {}
|
||||
|
||||
kwargs[TrackDescriptor.INDEX_KEY] = int(streamObj[TrackDescriptor.FFPROBE_INDEX_KEY]) if TrackDescriptor.FFPROBE_INDEX_KEY in streamObj.keys() else -1
|
||||
kwargs[TrackDescriptor.SOURCE_INDEX_KEY] = kwargs[TrackDescriptor.INDEX_KEY]
|
||||
kwargs[TrackDescriptor.SUB_INDEX_KEY] = subIndex
|
||||
|
||||
kwargs[TrackDescriptor.TRACK_TYPE_KEY] = trackType
|
||||
@@ -158,6 +165,10 @@ class TrackDescriptor():
|
||||
def getIndex(self):
|
||||
return self.__index
|
||||
|
||||
def getSourceIndex(self):
|
||||
return self.__sourceIndex
|
||||
|
||||
|
||||
def getSubIndex(self):
|
||||
return self.__subIndex
|
||||
|
||||
|
||||
Reference in New Issue
Block a user