combine track datatables
This commit is contained in:
@@ -188,28 +188,6 @@ class FileProperties():
|
|||||||
return json.loads(ffprobeOutput)['streams']
|
return json.loads(ffprobeOutput)['streams']
|
||||||
|
|
||||||
|
|
||||||
# def getTrackDescriptor(self, streamObj):
|
|
||||||
# """Convert the stream describing json object into a track descriptor"""
|
|
||||||
#
|
|
||||||
# trackType = streamObj['codec_type']
|
|
||||||
#
|
|
||||||
# descriptor = {}
|
|
||||||
#
|
|
||||||
# if trackType in [t.label() for t in TrackType]:
|
|
||||||
#
|
|
||||||
# descriptor['type'] = trackType
|
|
||||||
#
|
|
||||||
# descriptor = {}
|
|
||||||
# descriptor['disposition_list'] = [t for d in (k for (k,v) in streamObj['disposition'].items() if v) if (t := TrackDisposition.find(d)) if t is not None]
|
|
||||||
#
|
|
||||||
# descriptor['tags'] = streamObj['tags'] if 'tags' in streamObj.keys() else {}
|
|
||||||
#
|
|
||||||
# if trackType == TrackType.AUDIO.label():
|
|
||||||
# descriptor['layout'] = AudioLayout.identify(streamObj)
|
|
||||||
#
|
|
||||||
# return descriptor
|
|
||||||
|
|
||||||
|
|
||||||
def getMediaDescriptor(self):
|
def getMediaDescriptor(self):
|
||||||
return MediaDescriptor.fromFfprobe(self.getFormatData(), self.getStreamData())
|
return MediaDescriptor.fromFfprobe(self.getFormatData(), self.getStreamData())
|
||||||
|
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ class MediaDetailsScreen(Screen):
|
|||||||
CSS = """
|
CSS = """
|
||||||
|
|
||||||
Grid {
|
Grid {
|
||||||
grid-size: 4 9;
|
grid-size: 4 7;
|
||||||
grid-rows: 8 2 2 2 8 2 8 2 8;
|
grid-rows: 8 2 2 2 8 2 8;
|
||||||
grid-columns: 25 125 10 75;
|
grid-columns: 25 125 10 75;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -149,7 +149,7 @@ class MediaDetailsScreen(Screen):
|
|||||||
#
|
#
|
||||||
# def updateAudioTracks(self):
|
# def updateAudioTracks(self):
|
||||||
#
|
#
|
||||||
# self.audioStreamsTable.clear()
|
# self.tracksTable.clear()
|
||||||
#
|
#
|
||||||
# if self.__pattern is not None:
|
# if self.__pattern is not None:
|
||||||
#
|
#
|
||||||
@@ -166,7 +166,7 @@ class MediaDetailsScreen(Screen):
|
|||||||
# 'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No',
|
# 'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No',
|
||||||
# 'Yes' if TrackDisposition.FORCED in dispoSet else 'No')
|
# 'Yes' if TrackDisposition.FORCED in dispoSet else 'No')
|
||||||
#
|
#
|
||||||
# self.audioStreamsTable.add_row(*map(str, row))
|
# self.tracksTable.add_row(*map(str, row))
|
||||||
#
|
#
|
||||||
# def updateSubtitleTracks(self):
|
# def updateSubtitleTracks(self):
|
||||||
#
|
#
|
||||||
@@ -220,8 +220,9 @@ class MediaDetailsScreen(Screen):
|
|||||||
row = (mediaTagKey, mediaTagValue) # Convert each element to a string before adding
|
row = (mediaTagKey, mediaTagValue) # Convert each element to a string before adding
|
||||||
self.mediaTagsTable.add_row(*map(str, row))
|
self.mediaTagsTable.add_row(*map(str, row))
|
||||||
|
|
||||||
self.updateAudioTracks(self.__mediaDescriptor.getAudioTracks())
|
#self.updateAudioTracks(self.__mediaDescriptor.getAudioTracks())
|
||||||
self.updateSubtitleTracks(self.__mediaDescriptor.getSubtitleTracks())
|
#self.updateSubtitleTracks(self.__mediaDescriptor.getSubtitleTracks())
|
||||||
|
self.updateTracks()
|
||||||
|
|
||||||
if self.__mediaFilenamePattern is not None:
|
if self.__mediaFilenamePattern is not None:
|
||||||
|
|
||||||
@@ -295,42 +296,34 @@ class MediaDetailsScreen(Screen):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def updateAudioTracks(self, audioTracks):
|
def updateTracks(self):
|
||||||
|
|
||||||
self.audioStreamsTable.clear()
|
self.tracksTable.clear()
|
||||||
|
|
||||||
for at in audioTracks:
|
trackDescriptorList = self.__mediaDescriptor.getAllTracks()
|
||||||
|
|
||||||
dispoSet = at.getDispositionSet()
|
typeCounter = {}
|
||||||
|
|
||||||
row = (at.getSubIndex(),
|
for td in trackDescriptorList:
|
||||||
|
|
||||||
|
trackType = td.getType()
|
||||||
|
if not trackType in typeCounter.keys():
|
||||||
|
typeCounter[trackType] = 0
|
||||||
|
|
||||||
|
dispoSet = td.getDispositionSet()
|
||||||
|
|
||||||
|
row = (td.getIndex(),
|
||||||
|
trackType.label(),
|
||||||
|
typeCounter[trackType],
|
||||||
" ",
|
" ",
|
||||||
at.getLanguage().label(),
|
td.getLanguage().label(),
|
||||||
at.getTitle(),
|
td.getTitle(),
|
||||||
'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No',
|
'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No',
|
||||||
'Yes' if TrackDisposition.FORCED in dispoSet else 'No')
|
'Yes' if TrackDisposition.FORCED in dispoSet else 'No')
|
||||||
|
|
||||||
self.audioStreamsTable.add_row(*map(str, row))
|
self.tracksTable.add_row(*map(str, row))
|
||||||
|
|
||||||
def updateSubtitleTracks(self, subtitleTracks):
|
|
||||||
|
|
||||||
self.subtitleStreamsTable.clear()
|
|
||||||
|
|
||||||
for st in subtitleTracks:
|
|
||||||
|
|
||||||
dispoSet = st.getDispositionSet()
|
|
||||||
|
|
||||||
row = (st.getSubIndex(),
|
|
||||||
" ",
|
|
||||||
st.getLanguage().label(),
|
|
||||||
st.getTitle(),
|
|
||||||
'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No',
|
|
||||||
'Yes' if TrackDisposition.FORCED in dispoSet else 'No')
|
|
||||||
|
|
||||||
self.subtitleStreamsTable.add_row(*map(str, row))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typeCounter[trackType] += 1
|
||||||
|
|
||||||
|
|
||||||
def compose(self):
|
def compose(self):
|
||||||
@@ -352,36 +345,24 @@ class MediaDetailsScreen(Screen):
|
|||||||
|
|
||||||
# Define the columns with headers
|
# Define the columns with headers
|
||||||
self.column_key_track_tag_key = self.mediaTagsTable.add_column("Key", width=20)
|
self.column_key_track_tag_key = self.mediaTagsTable.add_column("Key", width=20)
|
||||||
self.column_key_track_tag_value = self.mediaTagsTable.add_column("Value", width=90)
|
self.column_key_track_tag_value = self.mediaTagsTable.add_column("Value", width=100)
|
||||||
|
|
||||||
self.mediaTagsTable.cursor_type = 'row'
|
self.mediaTagsTable.cursor_type = 'row'
|
||||||
|
|
||||||
|
|
||||||
|
self.tracksTable = DataTable()
|
||||||
self.audioStreamsTable = DataTable()
|
|
||||||
|
|
||||||
# Define the columns with headers
|
# Define the columns with headers
|
||||||
self.column_key_audio_subid = self.audioStreamsTable.add_column("Subindex", width=20)
|
self.column_key_track_index = self.tracksTable.add_column("Index", width=5)
|
||||||
self.column_key_audio_layout = self.audioStreamsTable.add_column("Layout", width=20)
|
self.column_key_track_type = self.tracksTable.add_column("Type", width=10)
|
||||||
self.column_key_audio_language = self.audioStreamsTable.add_column("Language", width=20)
|
self.column_key_track_sub_index = self.tracksTable.add_column("Subindex", width=5)
|
||||||
self.column_key_audio_title = self.audioStreamsTable.add_column("Title", width=30)
|
self.column_key_track_layout = self.tracksTable.add_column("Layout", width=10)
|
||||||
self.column_key_audio_default = self.audioStreamsTable.add_column("Default", width=10)
|
self.column_key_track_language = self.tracksTable.add_column("Language", width=15)
|
||||||
self.column_key_audio_forced = self.audioStreamsTable.add_column("Forced", width=10)
|
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.audioStreamsTable.cursor_type = 'row'
|
self.tracksTable.cursor_type = 'row'
|
||||||
|
|
||||||
|
|
||||||
self.subtitleStreamsTable = DataTable()
|
|
||||||
|
|
||||||
# Define the columns with headers
|
|
||||||
self.column_key_subtitle_subid = self.subtitleStreamsTable.add_column("Subindex", width=20)
|
|
||||||
self.column_key_subtitle_spacer = self.subtitleStreamsTable.add_column(" ", width=20)
|
|
||||||
self.column_key_subtitle_language = self.subtitleStreamsTable.add_column("Language", width=20)
|
|
||||||
self.column_key_subtitle_title = self.subtitleStreamsTable.add_column("Title", width=30)
|
|
||||||
self.column_key_subtitle_default = self.subtitleStreamsTable.add_column("Default", width=10)
|
|
||||||
self.column_key_subtitle_forced = self.subtitleStreamsTable.add_column("Forced", width=10)
|
|
||||||
|
|
||||||
self.subtitleStreamsTable.cursor_type = 'row'
|
|
||||||
|
|
||||||
|
|
||||||
# Create the DataTable widget
|
# Create the DataTable widget
|
||||||
@@ -392,8 +373,6 @@ class MediaDetailsScreen(Screen):
|
|||||||
|
|
||||||
self.differencesTable.cursor_type = 'row'
|
self.differencesTable.cursor_type = 'row'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
yield Header()
|
yield Header()
|
||||||
|
|
||||||
with Grid():
|
with Grid():
|
||||||
@@ -427,17 +406,17 @@ class MediaDetailsScreen(Screen):
|
|||||||
yield Static(" ", classes="three")
|
yield Static(" ", classes="three")
|
||||||
|
|
||||||
# 7
|
# 7
|
||||||
yield Static("Audio Streams")
|
yield Static("Streams")
|
||||||
yield self.audioStreamsTable
|
yield self.tracksTable
|
||||||
yield Static(" ")
|
yield Static(" ")
|
||||||
|
|
||||||
# 8
|
# # 8
|
||||||
yield Static(" ", classes="three")
|
# yield Static(" ", classes="three")
|
||||||
|
#
|
||||||
# 9
|
# # 9
|
||||||
yield Static("Subtitle Streams")
|
# yield Static("Subtitle Streams")
|
||||||
yield self.subtitleStreamsTable
|
# yield self.subtitleStreamsTable
|
||||||
yield Static(" ")
|
# yield Static(" ")
|
||||||
|
|
||||||
|
|
||||||
# 1
|
# 1
|
||||||
@@ -467,7 +446,7 @@ class MediaDetailsScreen(Screen):
|
|||||||
# yield Static("")
|
# yield Static("")
|
||||||
# yield Static("")
|
# yield Static("")
|
||||||
# # 6
|
# # 6
|
||||||
# yield self.audioStreamsTable
|
# yield self.tracksTable
|
||||||
#
|
#
|
||||||
# # 7
|
# # 7
|
||||||
# yield Static(" ", classes="five")
|
# yield Static(" ", classes="five")
|
||||||
@@ -511,10 +490,10 @@ class MediaDetailsScreen(Screen):
|
|||||||
#
|
#
|
||||||
# # Fetch the currently selected row when 'Enter' is pressed
|
# # Fetch the currently selected row when 'Enter' is pressed
|
||||||
# #selected_row_index = self.table.cursor_row
|
# #selected_row_index = self.table.cursor_row
|
||||||
# row_key, col_key = self.audioStreamsTable.coordinate_to_cell_key(self.audioStreamsTable.cursor_coordinate)
|
# row_key, col_key = self.tracksTable.coordinate_to_cell_key(self.tracksTable.cursor_coordinate)
|
||||||
#
|
#
|
||||||
# if row_key is not None:
|
# if row_key is not None:
|
||||||
# selected_track_data = self.audioStreamsTable.get_row(row_key)
|
# selected_track_data = self.tracksTable.get_row(row_key)
|
||||||
#
|
#
|
||||||
# subIndex = int(selected_track_data[0])
|
# subIndex = int(selected_track_data[0])
|
||||||
#
|
#
|
||||||
@@ -589,7 +568,7 @@ class MediaDetailsScreen(Screen):
|
|||||||
# if self.__pattern is not None:
|
# if self.__pattern is not None:
|
||||||
#
|
#
|
||||||
# if event.button.id == "button_add_audio_stream":
|
# if event.button.id == "button_add_audio_stream":
|
||||||
# self.app.push_screen(TrackDetailsScreen(trackType = TrackType.AUDIO, patternId = self.__pattern.getId(), subIndex = len(self.audioStreamsTable.rows)), self.handle_add_track)
|
# self.app.push_screen(TrackDetailsScreen(trackType = TrackType.AUDIO, patternId = self.__pattern.getId(), subIndex = len(self.tracksTable.rows)), self.handle_add_track)
|
||||||
#
|
#
|
||||||
# selectedAudioTrack = self.getSelectedAudioTrackDescriptor()
|
# selectedAudioTrack = self.getSelectedAudioTrackDescriptor()
|
||||||
# if selectedAudioTrack is not None:
|
# if selectedAudioTrack is not None:
|
||||||
@@ -638,7 +617,7 @@ class MediaDetailsScreen(Screen):
|
|||||||
# 'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No',
|
# 'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No',
|
||||||
# 'Yes' if TrackDisposition.FORCED in dispoSet else 'No')
|
# 'Yes' if TrackDisposition.FORCED in dispoSet else 'No')
|
||||||
#
|
#
|
||||||
# self.audioStreamsTable.add_row(*map(str, row))
|
# self.tracksTable.add_row(*map(str, row))
|
||||||
#
|
#
|
||||||
# if trackType == TrackType.SUBTITLE:
|
# if trackType == TrackType.SUBTITLE:
|
||||||
#
|
#
|
||||||
@@ -657,12 +636,12 @@ class MediaDetailsScreen(Screen):
|
|||||||
# try:
|
# try:
|
||||||
# if trackDescriptor.getType() == TrackType.AUDIO:
|
# if trackDescriptor.getType() == TrackType.AUDIO:
|
||||||
#
|
#
|
||||||
# row_key, col_key = self.audioStreamsTable.coordinate_to_cell_key(self.audioStreamsTable.cursor_coordinate)
|
# row_key, col_key = self.tracksTable.coordinate_to_cell_key(self.tracksTable.cursor_coordinate)
|
||||||
#
|
#
|
||||||
# self.audioStreamsTable.update_cell(row_key, self.column_key_audio_language, trackDescriptor.getLanguage().label())
|
# self.tracksTable.update_cell(row_key, self.column_key_track_language, trackDescriptor.getLanguage().label())
|
||||||
# self.audioStreamsTable.update_cell(row_key, self.column_key_audio_title, trackDescriptor.getTitle())
|
# self.tracksTable.update_cell(row_key, self.column_key_track_title, trackDescriptor.getTitle())
|
||||||
# self.audioStreamsTable.update_cell(row_key, self.column_key_audio_default, 'Yes' if TrackDisposition.DEFAULT 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.audioStreamsTable.update_cell(row_key, self.column_key_audio_forced, 'Yes' if TrackDisposition.FORCED 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')
|
||||||
#
|
#
|
||||||
# if trackDescriptor.getType() == TrackType.SUBTITLE:
|
# if trackDescriptor.getType() == TrackType.SUBTITLE:
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class Track(Base):
|
|||||||
track_type = Column(Integer) # TrackType
|
track_type = Column(Integer) # TrackType
|
||||||
|
|
||||||
index = Column(Integer)
|
index = Column(Integer)
|
||||||
sub_index = Column(Integer)
|
# sub_index = Column(Integer)
|
||||||
|
|
||||||
# v1.x
|
# v1.x
|
||||||
pattern_id = Column(Integer, ForeignKey('patterns.id', ondelete="CASCADE"))
|
pattern_id = Column(Integer, ForeignKey('patterns.id', ondelete="CASCADE"))
|
||||||
@@ -57,7 +57,7 @@ class Track(Base):
|
|||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def fromStreamObj(cls, streamObj, subIndex, patternId):
|
def fromStreamObj(cls, streamObj, patternId):
|
||||||
"""{
|
"""{
|
||||||
'index': 4,
|
'index': 4,
|
||||||
'codec_name': 'hdmv_pgs_subtitle',
|
'codec_name': 'hdmv_pgs_subtitle',
|
||||||
@@ -128,8 +128,8 @@ class Track(Base):
|
|||||||
|
|
||||||
if trackType in [t.label() for t in TrackType]:
|
if trackType in [t.label() for t in TrackType]:
|
||||||
|
|
||||||
|
# sub_index = int(subIndex),
|
||||||
return cls(pattern_id = patternId,
|
return cls(pattern_id = patternId,
|
||||||
sub_index = int(subIndex),
|
|
||||||
track_type = trackType,
|
track_type = trackType,
|
||||||
disposition_flags = sum([2**t.index() for (k,v) in streamObj['disposition'].items() if v and (t := TrackDisposition.find(k)) is not None]))
|
disposition_flags = sum([2**t.index() for (k,v) in streamObj['disposition'].items() if v and (t := TrackDisposition.find(k)) is not None]))
|
||||||
|
|
||||||
@@ -149,9 +149,6 @@ class Track(Base):
|
|||||||
def getIndex(self):
|
def getIndex(self):
|
||||||
return int(self.index) if self.index is not None else -1
|
return int(self.index) if self.index is not None else -1
|
||||||
|
|
||||||
def getSubIndex(self):
|
|
||||||
return int(self.sub_index) if self.sub_index is not None else -1
|
|
||||||
|
|
||||||
def getLanguage(self):
|
def getLanguage(self):
|
||||||
tags = {t.key:t.value for t in self.track_tags}
|
tags = {t.key:t.value for t in self.track_tags}
|
||||||
return IsoLanguage.findThreeLetter(tags['language']) if 'language' in tags.keys() else IsoLanguage.UNDEFINED
|
return IsoLanguage.findThreeLetter(tags['language']) if 'language' in tags.keys() else IsoLanguage.UNDEFINED
|
||||||
@@ -167,7 +164,7 @@ class Track(Base):
|
|||||||
return {str(t.key):str(t.value) for t in self.track_tags}
|
return {str(t.key):str(t.value) for t in self.track_tags}
|
||||||
|
|
||||||
|
|
||||||
def getDescriptor(self) -> TrackDescriptor:
|
def getDescriptor(self, subIndex : int = -1) -> TrackDescriptor:
|
||||||
|
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
|
|
||||||
@@ -175,7 +172,9 @@ class Track(Base):
|
|||||||
kwargs[TrackDescriptor.PATTERN_ID_KEY] = self.getPatternId()
|
kwargs[TrackDescriptor.PATTERN_ID_KEY] = self.getPatternId()
|
||||||
|
|
||||||
kwargs[TrackDescriptor.INDEX_KEY] = self.getIndex()
|
kwargs[TrackDescriptor.INDEX_KEY] = self.getIndex()
|
||||||
kwargs[TrackDescriptor.SUB_INDEX_KEY] = self.getSubIndex()
|
|
||||||
|
if subIndex > -1:
|
||||||
|
kwargs[TrackDescriptor.SUB_INDEX_KEY] = subIndex
|
||||||
|
|
||||||
kwargs[TrackDescriptor.TRACK_TYPE_KEY] = self.getType()
|
kwargs[TrackDescriptor.TRACK_TYPE_KEY] = self.getType()
|
||||||
kwargs[TrackDescriptor.DISPOSITION_SET_KEY] = self.getDispositionSet()
|
kwargs[TrackDescriptor.DISPOSITION_SET_KEY] = self.getDispositionSet()
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ from textual.containers import Grid
|
|||||||
|
|
||||||
from ffx.model.show import Show
|
from ffx.model.show import Show
|
||||||
from ffx.model.pattern import Pattern
|
from ffx.model.pattern import Pattern
|
||||||
|
from ffx.model.track import Track
|
||||||
|
|
||||||
from .pattern_controller import PatternController
|
from .pattern_controller import PatternController
|
||||||
from .show_controller import ShowController
|
from .show_controller import ShowController
|
||||||
@@ -30,8 +31,8 @@ class PatternDetailsScreen(Screen):
|
|||||||
CSS = """
|
CSS = """
|
||||||
|
|
||||||
Grid {
|
Grid {
|
||||||
grid-size: 5 12;
|
grid-size: 5 9;
|
||||||
grid-rows: 2 2 2 2 2 6 2 2 6 2 2 2;
|
grid-rows: 2 2 2 2 2 6 2 2 2;
|
||||||
grid-columns: 25 25 25 25 25;
|
grid-columns: 25 25 25 25 25;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -68,6 +69,10 @@ class PatternDetailsScreen(Screen):
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
border: solid green;
|
border: solid green;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#tracks_table {
|
||||||
|
row-span: 4;
|
||||||
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, patternId = None, showId = None):
|
def __init__(self, patternId = None, showId = None):
|
||||||
@@ -105,47 +110,38 @@ class PatternDetailsScreen(Screen):
|
|||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
|
|
||||||
def updateAudioTracks(self):
|
def updateTracks(self):
|
||||||
|
|
||||||
self.audioStreamsTable.clear()
|
self.tracksTable.clear()
|
||||||
|
|
||||||
if self.__pattern is not None:
|
if self.__pattern is not None:
|
||||||
|
|
||||||
audioTracks = self.__tc.findAudioTracks(self.__pattern.getId())
|
tracks = self.__tc.findTracks(self.__pattern.getId())
|
||||||
|
|
||||||
for at in audioTracks:
|
typeCounter = {}
|
||||||
|
|
||||||
dispoSet = at.getDispositionSet()
|
for tr in tracks:
|
||||||
|
|
||||||
row = (at.getSubIndex(),
|
td : TrackDescriptor = tr.getDescriptor()
|
||||||
|
|
||||||
|
trackType = td.getType()
|
||||||
|
if not trackType in typeCounter.keys():
|
||||||
|
typeCounter[trackType] = 0
|
||||||
|
|
||||||
|
dispoSet = td.getDispositionSet()
|
||||||
|
|
||||||
|
row = (td.getIndex(),
|
||||||
|
trackType.label(),
|
||||||
|
typeCounter[trackType],
|
||||||
" ",
|
" ",
|
||||||
at.getLanguage().label(),
|
td.getLanguage().label(),
|
||||||
at.getTitle(),
|
td.getTitle(),
|
||||||
'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No',
|
'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No',
|
||||||
'Yes' if TrackDisposition.FORCED in dispoSet else 'No')
|
'Yes' if TrackDisposition.FORCED in dispoSet else 'No')
|
||||||
|
|
||||||
self.audioStreamsTable.add_row(*map(str, row))
|
self.tracksTable.add_row(*map(str, row))
|
||||||
|
|
||||||
def updateSubtitleTracks(self):
|
typeCounter[trackType] += 1
|
||||||
|
|
||||||
self.subtitleStreamsTable.clear()
|
|
||||||
|
|
||||||
if self.__pattern is not None:
|
|
||||||
|
|
||||||
subtitleTracks = self.__tc.findSubtitleTracks(self.__pattern.getId())
|
|
||||||
|
|
||||||
for st in subtitleTracks:
|
|
||||||
|
|
||||||
dispoSet = st.getDispositionSet()
|
|
||||||
|
|
||||||
row = (st.getSubIndex(),
|
|
||||||
" ",
|
|
||||||
st.getLanguage().label(),
|
|
||||||
st.getTitle(),
|
|
||||||
'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No',
|
|
||||||
'Yes' if TrackDisposition.FORCED in dispoSet else 'No')
|
|
||||||
|
|
||||||
self.subtitleStreamsTable.add_row(*map(str, row))
|
|
||||||
|
|
||||||
|
|
||||||
def on_mount(self):
|
def on_mount(self):
|
||||||
@@ -157,38 +153,25 @@ class PatternDetailsScreen(Screen):
|
|||||||
|
|
||||||
self.query_one("#pattern_input", Input).value = str(self.__pattern.getPattern())
|
self.query_one("#pattern_input", Input).value = str(self.__pattern.getPattern())
|
||||||
|
|
||||||
self.updateAudioTracks()
|
self.updateTracks()
|
||||||
self.updateSubtitleTracks()
|
|
||||||
|
|
||||||
|
|
||||||
def compose(self):
|
def compose(self):
|
||||||
|
|
||||||
self.audioStreamsTable = DataTable(classes="five")
|
self.tracksTable = DataTable(id="tracks_table", classes="five")
|
||||||
|
|
||||||
# Define the columns with headers
|
self.column_key_track_index = self.tracksTable.add_column("Index", width=5)
|
||||||
self.column_key_audio_subid = self.audioStreamsTable.add_column("Subindex", width=20)
|
self.column_key_track_type = self.tracksTable.add_column("Type", width=10)
|
||||||
self.column_key_audio_layout = self.audioStreamsTable.add_column("Layout", width=20)
|
self.column_key_track_sub_index = self.tracksTable.add_column("Subindex", width=5)
|
||||||
self.column_key_audio_language = self.audioStreamsTable.add_column("Language", width=20)
|
self.column_key_track_layout = self.tracksTable.add_column("Layout", width=10)
|
||||||
self.column_key_audio_title = self.audioStreamsTable.add_column("Title", width=30)
|
self.column_key_track_language = self.tracksTable.add_column("Language", width=15)
|
||||||
self.column_key_audio_default = self.audioStreamsTable.add_column("Default", width=10)
|
self.column_key_track_title = self.tracksTable.add_column("Title", width=48)
|
||||||
self.column_key_audio_forced = self.audioStreamsTable.add_column("Forced", width=10)
|
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.audioStreamsTable.cursor_type = 'row'
|
|
||||||
|
|
||||||
|
self.tracksTable.cursor_type = 'row'
|
||||||
|
|
||||||
self.subtitleStreamsTable = DataTable(classes="five")
|
self.subtitleStreamsTable = DataTable(classes="five")
|
||||||
|
|
||||||
# Define the columns with headers
|
|
||||||
self.column_key_subtitle_subid = self.subtitleStreamsTable.add_column("Subindex", width=20)
|
|
||||||
self.column_key_subtitle_spacer = self.subtitleStreamsTable.add_column(" ", width=20)
|
|
||||||
self.column_key_subtitle_language = self.subtitleStreamsTable.add_column("Language", width=20)
|
|
||||||
self.column_key_subtitle_title = self.subtitleStreamsTable.add_column("Title", width=30)
|
|
||||||
self.column_key_subtitle_default = self.subtitleStreamsTable.add_column("Default", width=10)
|
|
||||||
self.column_key_subtitle_forced = self.subtitleStreamsTable.add_column("Forced", width=10)
|
|
||||||
|
|
||||||
self.subtitleStreamsTable.cursor_type = 'row'
|
|
||||||
|
|
||||||
|
|
||||||
yield Header()
|
yield Header()
|
||||||
|
|
||||||
with Grid():
|
with Grid():
|
||||||
@@ -200,7 +183,7 @@ class PatternDetailsScreen(Screen):
|
|||||||
# 2
|
# 2
|
||||||
yield Static("from show")
|
yield Static("from show")
|
||||||
yield Static("", id="showlabel", classes="three")
|
yield Static("", id="showlabel", classes="three")
|
||||||
yield Button("Substitute pattern", id="patternbutton")
|
yield Button("Substitute pattern", id="pattern_button")
|
||||||
|
|
||||||
# 3
|
# 3
|
||||||
yield Static(" ", classes="five")
|
yield Static(" ", classes="five")
|
||||||
@@ -208,42 +191,27 @@ class PatternDetailsScreen(Screen):
|
|||||||
yield Static(" ", classes="five")
|
yield Static(" ", classes="five")
|
||||||
|
|
||||||
# 5
|
# 5
|
||||||
yield Static("Audio streams")
|
yield Static("Streams")
|
||||||
yield Static(" ")
|
yield Static(" ")
|
||||||
|
|
||||||
if self.__pattern is not None:
|
if self.__pattern is not None:
|
||||||
yield Button("Add", id="button_add_audio_stream")
|
yield Button("Add", id="button_add_track")
|
||||||
yield Button("Edit", id="button_edit_audio_stream")
|
yield Button("Edit", id="button_edit_track")
|
||||||
yield Button("Delete", id="button_delete_audio_stream")
|
yield Button("Delete", id="button_delete_track")
|
||||||
else:
|
else:
|
||||||
yield Static("")
|
yield Static("")
|
||||||
yield Static("")
|
yield Static("")
|
||||||
yield Static("")
|
yield Static("")
|
||||||
# 6
|
# 6
|
||||||
yield self.audioStreamsTable
|
yield self.tracksTable
|
||||||
|
|
||||||
# 7
|
# 7
|
||||||
yield Static(" ", classes="five")
|
yield Static(" ", classes="five")
|
||||||
|
|
||||||
# 8
|
# 8
|
||||||
yield Static("Subtitle streams")
|
|
||||||
yield Static(" ")
|
|
||||||
|
|
||||||
if self.__pattern is not None:
|
|
||||||
yield Button("Add", id="button_add_subtitle_stream")
|
|
||||||
yield Button("Edit", id="button_edit_subtitle_stream")
|
|
||||||
yield Button("Delete", id="button_delete_subtitle_stream")
|
|
||||||
else:
|
|
||||||
yield Static("")
|
|
||||||
yield Static("")
|
|
||||||
yield Static("")
|
|
||||||
# 9
|
|
||||||
yield self.subtitleStreamsTable
|
|
||||||
|
|
||||||
# 10
|
|
||||||
yield Static(" ", classes="five")
|
yield Static(" ", classes="five")
|
||||||
|
|
||||||
# 11
|
# 9
|
||||||
yield Button("Save", id="save_button")
|
yield Button("Save", id="save_button")
|
||||||
yield Button("Cancel", id="cancel_button")
|
yield Button("Cancel", id="cancel_button")
|
||||||
|
|
||||||
@@ -255,7 +223,7 @@ class PatternDetailsScreen(Screen):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def getSelectedAudioTrackDescriptor(self):
|
def getSelectedTrackDescriptor(self):
|
||||||
|
|
||||||
if not self.__pattern:
|
if not self.__pattern:
|
||||||
return None
|
return None
|
||||||
@@ -264,14 +232,15 @@ class PatternDetailsScreen(Screen):
|
|||||||
|
|
||||||
# Fetch the currently selected row when 'Enter' is pressed
|
# Fetch the currently selected row when 'Enter' is pressed
|
||||||
#selected_row_index = self.table.cursor_row
|
#selected_row_index = self.table.cursor_row
|
||||||
row_key, col_key = self.audioStreamsTable.coordinate_to_cell_key(self.audioStreamsTable.cursor_coordinate)
|
row_key, col_key = self.tracksTable.coordinate_to_cell_key(self.tracksTable.cursor_coordinate)
|
||||||
|
|
||||||
if row_key is not None:
|
if row_key is not None:
|
||||||
selected_track_data = self.audioStreamsTable.get_row(row_key)
|
selected_track_data = self.tracksTable.get_row(row_key)
|
||||||
|
|
||||||
subIndex = int(selected_track_data[0])
|
trackIndex = int(selected_track_data[0])
|
||||||
|
trackSubIndex = int(selected_track_data[2])
|
||||||
|
|
||||||
return self.__tc.findTrack(self.__pattern.getId(), TrackType.AUDIO, subIndex).getDescriptor()
|
return self.__tc.getTrack(self.__pattern.getId(), trackIndex).getDescriptor(subIndex=trackSubIndex)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
@@ -280,32 +249,6 @@ class PatternDetailsScreen(Screen):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def getSelectedSubtitleTrackDescriptor(self) -> TrackDescriptor:
|
|
||||||
|
|
||||||
if not self.__pattern is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
try:
|
|
||||||
|
|
||||||
# Fetch the currently selected row when 'Enter' is pressed
|
|
||||||
#selected_row_index = self.table.cursor_row
|
|
||||||
row_key, col_key = self.subtitleStreamsTable.coordinate_to_cell_key(self.subtitleStreamsTable.cursor_coordinate)
|
|
||||||
|
|
||||||
if row_key is not None:
|
|
||||||
|
|
||||||
selected_track_data = self.subtitleStreamsTable.get_row(row_key)
|
|
||||||
subIndex = int(selected_track_data[0])
|
|
||||||
|
|
||||||
return self.__tc.findTrack(self.__pattern.getId(), TrackType.SUBTITLE, subIndex).getDescriptor()
|
|
||||||
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
except CellDoesNotExist:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Event handler for button press
|
# Event handler for button press
|
||||||
def on_button_pressed(self, event: Button.Pressed) -> None:
|
def on_button_pressed(self, event: Button.Pressed) -> None:
|
||||||
# Check if the button pressed is the one we are interested in
|
# Check if the button pressed is the one we are interested in
|
||||||
@@ -327,14 +270,6 @@ class PatternDetailsScreen(Screen):
|
|||||||
patternId = self.__pc.addPattern(patternDescriptor)
|
patternId = self.__pc.addPattern(patternDescriptor)
|
||||||
if patternId is not None:
|
if patternId is not None:
|
||||||
|
|
||||||
# Add dummy video track
|
|
||||||
kwargs = {}
|
|
||||||
kwargs[TrackDescriptor.INDEX_KEY] = 0
|
|
||||||
kwargs[TrackDescriptor.SUB_INDEX_KEY] = 0
|
|
||||||
kwargs[TrackDescriptor.PATTERN_ID_KEY] = patternId
|
|
||||||
kwargs[TrackDescriptor.TRACK_TYPE_KEY] = TrackType.VIDEO
|
|
||||||
self.__tc.addTrack(TrackDescriptor(**kwargs))
|
|
||||||
|
|
||||||
self.dismiss(patternDescriptor)
|
self.dismiss(patternDescriptor)
|
||||||
else:
|
else:
|
||||||
#TODO: Meldung
|
#TODO: Meldung
|
||||||
@@ -349,36 +284,19 @@ class PatternDetailsScreen(Screen):
|
|||||||
# Save pattern when just created before adding streams
|
# Save pattern when just created before adding streams
|
||||||
if self.__pattern is not None:
|
if self.__pattern is not None:
|
||||||
|
|
||||||
numVideoStreams = len(self.__pattern.getMediaDescriptor().getVideoTracks())
|
numTracks = len(self.tracksTable.rows)
|
||||||
numAudioStreams = len(self.audioStreamsTable.rows)
|
|
||||||
numSubtitleStreams = len(self.subtitleStreamsTable.rows)
|
|
||||||
|
|
||||||
addedTrackIndex = numVideoStreams + numAudioStreams + numSubtitleStreams
|
if event.button.id == "button_add_track":
|
||||||
|
self.app.push_screen(TrackDetailsScreen(patternId = self.__pattern.getId(), index = numTracks), self.handle_add_track)
|
||||||
|
|
||||||
#NOTE: Track index
|
selectedTrack = self.getSelectedTrackDescriptor()
|
||||||
|
if selectedTrack is not None:
|
||||||
|
if event.button.id == "button_edit_track":
|
||||||
|
self.app.push_screen(TrackDetailsScreen(trackDescriptor = selectedTrack), self.handle_edit_track)
|
||||||
|
if event.button.id == "button_delete_track":
|
||||||
|
self.app.push_screen(TrackDeleteScreen(trackDescriptor = selectedTrack), self.handle_delete_track)
|
||||||
|
|
||||||
if event.button.id == "button_add_audio_stream":
|
if event.button.id == "pattern_button":
|
||||||
self.app.push_screen(TrackDetailsScreen(trackType = TrackType.AUDIO, patternId = self.__pattern.getId(), index = addedTrackIndex, subIndex = numAudioStreams), self.handle_add_track)
|
|
||||||
|
|
||||||
selectedAudioTrack = self.getSelectedAudioTrackDescriptor()
|
|
||||||
if selectedAudioTrack is not None:
|
|
||||||
if event.button.id == "button_edit_audio_stream":
|
|
||||||
|
|
||||||
self.app.push_screen(TrackDetailsScreen(trackDescriptor = selectedAudioTrack), self.handle_edit_track)
|
|
||||||
if event.button.id == "button_delete_audio_stream":
|
|
||||||
self.app.push_screen(TrackDeleteScreen(trackDescriptor = selectedAudioTrack), self.handle_delete_track)
|
|
||||||
|
|
||||||
if event.button.id == "button_add_subtitle_stream":
|
|
||||||
self.app.push_screen(TrackDetailsScreen(trackType = TrackType.SUBTITLE, patternId = self.__pattern.getId(), index = addedTrackIndex, subIndex = numSubtitleStreams), self.handle_add_track)
|
|
||||||
|
|
||||||
selectedSubtitleTrack = self.getSelectedSubtitleTrackDescriptor()
|
|
||||||
if selectedSubtitleTrack is not None:
|
|
||||||
if event.button.id == "button_edit_subtitle_stream":
|
|
||||||
self.app.push_screen(TrackDetailsScreen(trackDescriptor = selectedSubtitleTrack), self.handle_edit_track)
|
|
||||||
if event.button.id == "button_delete_subtitle_stream":
|
|
||||||
self.app.push_screen(TrackDeleteScreen(trackDescriptor = selectedSubtitleTrack), self.handle_delete_track)
|
|
||||||
|
|
||||||
if event.button.id == "patternbutton":
|
|
||||||
|
|
||||||
INDICATOR_PATTERN = '([sS][0-9]+[eE][0-9]+)'
|
INDICATOR_PATTERN = '([sS][0-9]+[eE][0-9]+)'
|
||||||
|
|
||||||
@@ -390,70 +308,41 @@ class PatternDetailsScreen(Screen):
|
|||||||
self.query_one("#pattern_input", Input).value = pattern.replace(patternMatch.group(1), INDICATOR_PATTERN)
|
self.query_one("#pattern_input", Input).value = pattern.replace(patternMatch.group(1), INDICATOR_PATTERN)
|
||||||
|
|
||||||
|
|
||||||
def handle_add_track(self, trackDescriptor):
|
def handle_add_track(self, trackDescriptor : TrackDescriptor):
|
||||||
|
|
||||||
dispoSet = trackDescriptor.getDispositionSet()
|
dispoSet = trackDescriptor.getDispositionSet()
|
||||||
trackType = trackDescriptor.getType()
|
trackType = trackDescriptor.getType()
|
||||||
|
index = trackDescriptor.getIndex()
|
||||||
subIndex = trackDescriptor.getSubIndex()
|
subIndex = trackDescriptor.getSubIndex()
|
||||||
language = trackDescriptor.getLanguage()
|
language = trackDescriptor.getLanguage()
|
||||||
title = trackDescriptor.getTitle()
|
title = trackDescriptor.getTitle()
|
||||||
|
|
||||||
if trackType == TrackType.AUDIO:
|
row = (index,
|
||||||
|
trackType.label(),
|
||||||
row = (subIndex,
|
subIndex,
|
||||||
" ",
|
" ",
|
||||||
language.label(),
|
language.label(),
|
||||||
title,
|
title,
|
||||||
'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No',
|
'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No',
|
||||||
'Yes' if TrackDisposition.FORCED in dispoSet else 'No')
|
'Yes' if TrackDisposition.FORCED in dispoSet else 'No')
|
||||||
|
|
||||||
self.audioStreamsTable.add_row(*map(str, row))
|
self.tracksTable.add_row(*map(str, row))
|
||||||
|
|
||||||
if trackType == TrackType.SUBTITLE:
|
|
||||||
|
|
||||||
row = (subIndex,
|
|
||||||
" ",
|
|
||||||
language.label(),
|
|
||||||
title,
|
|
||||||
'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No',
|
|
||||||
'Yes' if TrackDisposition.FORCED in dispoSet else 'No')
|
|
||||||
|
|
||||||
self.subtitleStreamsTable.add_row(*map(str, row))
|
|
||||||
|
|
||||||
|
|
||||||
def handle_edit_track(self, trackDescriptor : TrackDescriptor):
|
def handle_edit_track(self, trackDescriptor : TrackDescriptor):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if trackDescriptor.getType() == TrackType.AUDIO:
|
|
||||||
|
|
||||||
row_key, col_key = self.audioStreamsTable.coordinate_to_cell_key(self.audioStreamsTable.cursor_coordinate)
|
row_key, col_key = self.tracksTable.coordinate_to_cell_key(self.tracksTable.cursor_coordinate)
|
||||||
|
|
||||||
self.audioStreamsTable.update_cell(row_key, self.column_key_audio_language, trackDescriptor.getLanguage().label())
|
self.tracksTable.update_cell(row_key, self.column_key_track_language, trackDescriptor.getLanguage().label())
|
||||||
self.audioStreamsTable.update_cell(row_key, self.column_key_audio_title, trackDescriptor.getTitle())
|
self.tracksTable.update_cell(row_key, self.column_key_track_title, trackDescriptor.getTitle())
|
||||||
self.audioStreamsTable.update_cell(row_key, self.column_key_audio_default, 'Yes' if TrackDisposition.DEFAULT 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.audioStreamsTable.update_cell(row_key, self.column_key_audio_forced, 'Yes' if TrackDisposition.FORCED 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')
|
||||||
|
|
||||||
if trackDescriptor.getType() == TrackType.SUBTITLE:
|
|
||||||
|
|
||||||
row_key, col_key = self.subtitleStreamsTable.coordinate_to_cell_key(self.subtitleStreamsTable.cursor_coordinate)
|
|
||||||
|
|
||||||
self.subtitleStreamsTable.update_cell(row_key, self.column_key_subtitle_language, trackDescriptor.getLanguage().label())
|
|
||||||
self.subtitleStreamsTable.update_cell(row_key, self.column_key_subtitle_title, trackDescriptor.getTitle())
|
|
||||||
self.subtitleStreamsTable.update_cell(row_key, self.column_key_subtitle_default, 'Yes' if TrackDisposition.DEFAULT in trackDescriptor.getDispositionSet() else 'No')
|
|
||||||
self.subtitleStreamsTable.update_cell(row_key, self.column_key_subtitle_forced, 'Yes' if TrackDisposition.FORCED in trackDescriptor.getDispositionSet() else 'No')
|
|
||||||
|
|
||||||
except CellDoesNotExist:
|
except CellDoesNotExist:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def handle_delete_track(self, trackDescriptor : TrackDescriptor):
|
def handle_delete_track(self, trackDescriptor : TrackDescriptor):
|
||||||
|
self.updateTracks()
|
||||||
try:
|
|
||||||
if trackDescriptor.getType() == TrackType.AUDIO:
|
|
||||||
self.updateAudioTracks()
|
|
||||||
|
|
||||||
if trackDescriptor.getType() == TrackType.SUBTITLE:
|
|
||||||
self.updateSubtitleTracks()
|
|
||||||
|
|
||||||
except CellDoesNotExist:
|
|
||||||
pass
|
|
||||||
|
|||||||
@@ -21,14 +21,13 @@ class TrackController():
|
|||||||
self.Session = self.context['database']['session'] # convenience
|
self.Session = self.context['database']['session'] # convenience
|
||||||
|
|
||||||
|
|
||||||
def addTrack(self, trackDescriptor):
|
def addTrack(self, trackDescriptor : TrackDescriptor):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
s = self.Session()
|
s = self.Session()
|
||||||
track = Track(pattern_id = int(trackDescriptor.getPatternId()),
|
track = Track(pattern_id = int(trackDescriptor.getPatternId()),
|
||||||
track_type = int(trackDescriptor.getType().index()),
|
track_type = int(trackDescriptor.getType().index()),
|
||||||
index = int(trackDescriptor.getIndex()),
|
index = int(trackDescriptor.getIndex()),
|
||||||
sub_index = int(trackDescriptor.getSubIndex()),
|
|
||||||
disposition_flags = int(TrackDisposition.toFlags(trackDescriptor.getDispositionSet())))
|
disposition_flags = int(TrackDisposition.toFlags(trackDescriptor.getDispositionSet())))
|
||||||
|
|
||||||
s.add(track)
|
s.add(track)
|
||||||
@@ -89,6 +88,32 @@ class TrackController():
|
|||||||
finally:
|
finally:
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
|
def findTracks(self, patternId):
|
||||||
|
|
||||||
|
try:
|
||||||
|
s = self.Session()
|
||||||
|
|
||||||
|
q = s.query(Track).filter(Track.pattern_id == int(patternId))
|
||||||
|
return [a for a in q.all()]
|
||||||
|
|
||||||
|
except Exception as ex:
|
||||||
|
raise click.ClickException(f"TrackController.findTracks(): {repr(ex)}")
|
||||||
|
finally:
|
||||||
|
s.close()
|
||||||
|
|
||||||
|
#TODO: mit optionalem Parameter lösen ^
|
||||||
|
def findVideoTracks(self, patternId):
|
||||||
|
|
||||||
|
try:
|
||||||
|
s = self.Session()
|
||||||
|
|
||||||
|
q = s.query(Track).filter(Track.pattern_id == int(patternId), Track.track_type == TrackType.VIDEO.index())
|
||||||
|
return [a for a in q.all()]
|
||||||
|
|
||||||
|
except Exception as ex:
|
||||||
|
raise click.ClickException(f"TrackController.findVideoTracks(): {repr(ex)}")
|
||||||
|
finally:
|
||||||
|
s.close()
|
||||||
|
|
||||||
def findAudioTracks(self, patternId):
|
def findAudioTracks(self, patternId):
|
||||||
|
|
||||||
@@ -117,11 +142,11 @@ class TrackController():
|
|||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
|
|
||||||
def findTrack(self, patternId : int, trackType : TrackType, subIndex : int) -> Track:
|
def getTrack(self, patternId : int, index: int) -> Track:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
s = self.Session()
|
s = self.Session()
|
||||||
q = s.query(Track).filter(Track.pattern_id == int(patternId), Track.track_type == trackType.index(), Track.sub_index == int(subIndex))
|
q = s.query(Track).filter(Track.pattern_id == int(patternId), Track.index == int(index))
|
||||||
|
|
||||||
if q.count():
|
if q.count():
|
||||||
return q.first()
|
return q.first()
|
||||||
@@ -129,37 +154,35 @@ class TrackController():
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
raise click.ClickException(f"TrackController.findTrack(): {repr(ex)}")
|
raise click.ClickException(f"TrackController.getTrack(): {repr(ex)}")
|
||||||
finally:
|
finally:
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
def deleteTrack(self, trackId):
|
def deleteTrack(self, trackId):
|
||||||
try:
|
try:
|
||||||
s = self.Session()
|
s = self.Session()
|
||||||
|
|
||||||
q = s.query(Track).filter(Track.id == int(trackId))
|
q = s.query(Track).filter(Track.id == int(trackId))
|
||||||
|
|
||||||
if q.count():
|
if q.count():
|
||||||
|
patternId = int(q.first().pattern_id)
|
||||||
|
|
||||||
track = q.first()
|
q_siblings = s.query(Track).filter(Track.pattern_id == patternId).order_by(Track.index)
|
||||||
|
|
||||||
q_siblings = s.query(Track).filter(Track.pattern_id == track.getPatternId(), Track.track_type == track.getType().index()).order_by(Track.sub_index)
|
index = 0
|
||||||
|
|
||||||
subIndex = 0
|
|
||||||
for track in q_siblings.all():
|
for track in q_siblings.all():
|
||||||
|
|
||||||
if track.sub_index == track.getSubIndex():
|
if track.id == int(trackId):
|
||||||
s.delete(track)
|
s.delete(track)
|
||||||
else:
|
else:
|
||||||
track.sub_index = subIndex
|
track.index = index
|
||||||
subIndex += 1
|
index += 1
|
||||||
|
|
||||||
s.commit()
|
s.commit()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
raise click.ClickException(f"TrackController.deleteTrack(): {repr(ex)}")
|
raise click.ClickException(f"TrackController.deleteTrack(): {repr(ex)}")
|
||||||
finally:
|
finally:
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ from textual.widgets import Header, Footer, Static, Button
|
|||||||
from textual.containers import Grid
|
from textual.containers import Grid
|
||||||
|
|
||||||
from ffx.model.pattern import Pattern
|
from ffx.model.pattern import Pattern
|
||||||
|
from ffx.model.track import Track
|
||||||
from ffx.track_descriptor import TrackDescriptor
|
from ffx.track_descriptor import TrackDescriptor
|
||||||
|
|
||||||
from .track_controller import TrackController
|
from .track_controller import TrackController
|
||||||
@@ -121,7 +122,7 @@ class TrackDeleteScreen(Screen):
|
|||||||
|
|
||||||
if event.button.id == "delete_button":
|
if event.button.id == "delete_button":
|
||||||
|
|
||||||
track = self.__tc.findTrack(self.__trackDescriptor.getPatternId(), self.__trackDescriptor.getType(), self.__trackDescriptor.getSubIndex())
|
track = self.__tc.getTrack(self.__trackDescriptor.getPatternId(), self.__trackDescriptor.getIndex())
|
||||||
|
|
||||||
if track is None:
|
if track is None:
|
||||||
raise click.ClickException(f"Track is none: patternId={self.__trackDescriptor.getPatternId()} type={self.__trackDescriptor.getType()} subIndex={self.__trackDescriptor.getSubIndex()}")
|
raise click.ClickException(f"Track is none: patternId={self.__trackDescriptor.getPatternId()} type={self.__trackDescriptor.getType()} subIndex={self.__trackDescriptor.getSubIndex()}")
|
||||||
|
|||||||
@@ -47,12 +47,11 @@ class TrackDescriptor():
|
|||||||
|
|
||||||
if TrackDescriptor.SUB_INDEX_KEY in kwargs.keys():
|
if TrackDescriptor.SUB_INDEX_KEY in kwargs.keys():
|
||||||
if type(kwargs[TrackDescriptor.SUB_INDEX_KEY]) is not int:
|
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 dict")
|
raise TypeError(f"TrackDesciptor.__init__(): Argument {TrackDescriptor.SUB_INDEX_KEY} is required to be of type int")
|
||||||
self.__subIndex = kwargs[TrackDescriptor.SUB_INDEX_KEY]
|
self.__subIndex = kwargs[TrackDescriptor.SUB_INDEX_KEY]
|
||||||
else:
|
else:
|
||||||
self.__subIndex = -1
|
self.__subIndex = -1
|
||||||
|
|
||||||
|
|
||||||
if TrackDescriptor.TRACK_TYPE_KEY in kwargs.keys():
|
if TrackDescriptor.TRACK_TYPE_KEY in kwargs.keys():
|
||||||
if type(kwargs[TrackDescriptor.TRACK_TYPE_KEY]) is not TrackType:
|
if type(kwargs[TrackDescriptor.TRACK_TYPE_KEY]) is not TrackType:
|
||||||
raise TypeError(f"TrackDesciptor.__init__(): Argument {TrackDescriptor.TRACK_TYPE_KEY} is required to be of type TrackType")
|
raise TypeError(f"TrackDesciptor.__init__(): Argument {TrackDescriptor.TRACK_TYPE_KEY} is required to be of type TrackType")
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ from textual.widgets import Header, Footer, Static, Button, SelectionList, Selec
|
|||||||
from textual.containers import Grid
|
from textual.containers import Grid
|
||||||
|
|
||||||
from ffx.model.pattern import Pattern
|
from ffx.model.pattern import Pattern
|
||||||
|
from ffx.model.track import Track
|
||||||
|
|
||||||
from .track_controller import TrackController
|
from .track_controller import TrackController
|
||||||
from .pattern_controller import PatternController
|
from .pattern_controller import PatternController
|
||||||
@@ -32,9 +33,9 @@ class TrackDetailsScreen(Screen):
|
|||||||
CSS = """
|
CSS = """
|
||||||
|
|
||||||
Grid {
|
Grid {
|
||||||
grid-size: 5 20;
|
grid-size: 5 21;
|
||||||
grid-rows: 2 2 2 2 2 3 2 2 2 2 2 6 2 2 6 2 2 2 2 6;
|
grid-rows: 2 2 2 2 2 3 2 2 3 2 2 2 2 2 6 2 2 6 2 2 2;
|
||||||
grid-columns: 25 25 25 25 225;
|
grid-columns: 25 25 25 25 125;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 1;
|
padding: 1;
|
||||||
@@ -79,6 +80,10 @@ class TrackDetailsScreen(Screen):
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
border: solid green;
|
border: solid green;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.yellow {
|
||||||
|
tint: yellow 40%;
|
||||||
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, trackDescriptor : TrackDescriptor = None, patternId = None, trackType : TrackType = None, index = None, subIndex = None):
|
def __init__(self, trackDescriptor : TrackDescriptor = None, patternId = None, trackType : TrackType = None, index = None, subIndex = None):
|
||||||
@@ -126,11 +131,14 @@ class TrackDetailsScreen(Screen):
|
|||||||
|
|
||||||
def on_mount(self):
|
def on_mount(self):
|
||||||
|
|
||||||
if self.__pattern is not None:
|
self.query_one("#index_label", Static).update(str(self.__index) if self.__index is not None else '-')
|
||||||
self.query_one("#patternlabel", Static).update(self.__pattern.getPattern())
|
self.query_one("#subindex_label", Static).update(str(self.__subIndex)if self.__subIndex is not None else '-')
|
||||||
|
|
||||||
if self.__subIndex is not None:
|
if self.__pattern is not None:
|
||||||
self.query_one("#subindexlabel", Static).update(str(self.__subIndex))
|
self.query_one("#pattern_label", Static).update(self.__pattern.getPattern())
|
||||||
|
|
||||||
|
if self.__trackType is not None:
|
||||||
|
self.query_one("#type_select", Select).value = self.__trackType.label()
|
||||||
|
|
||||||
for d in TrackDisposition:
|
for d in TrackDisposition:
|
||||||
|
|
||||||
@@ -153,7 +161,7 @@ class TrackDetailsScreen(Screen):
|
|||||||
|
|
||||||
# Define the columns with headers
|
# Define the columns with headers
|
||||||
self.column_key_track_tag_key = self.trackTagsTable.add_column("Key", width=10)
|
self.column_key_track_tag_key = self.trackTagsTable.add_column("Key", width=10)
|
||||||
self.column_key_track_tag_value = self.trackTagsTable.add_column("Value", width=30)
|
self.column_key_track_tag_value = self.trackTagsTable.add_column("Value", width=125)
|
||||||
|
|
||||||
self.trackTagsTable.cursor_type = 'row'
|
self.trackTagsTable.cursor_type = 'row'
|
||||||
|
|
||||||
@@ -165,71 +173,83 @@ class TrackDetailsScreen(Screen):
|
|||||||
with Grid():
|
with Grid():
|
||||||
|
|
||||||
# 1
|
# 1
|
||||||
yield Static(f"New {self.__trackType.label()} stream" if self.__isNew else f"Edit {self.__trackType.label()} stream", id="toplabel", classes="five")
|
yield Static(f"New stream" if self.__isNew else f"Edit stream", id="toplabel", classes="five")
|
||||||
|
|
||||||
# 2
|
# 2
|
||||||
yield Static("for pattern")
|
yield Static("for pattern")
|
||||||
yield Static("", id="patternlabel", classes="four")
|
yield Static("", id="pattern_label", classes="four")
|
||||||
|
|
||||||
# 3
|
# 3
|
||||||
yield Static("sub index")
|
yield Static(" ", classes="five")
|
||||||
yield Static("", id="subindexlabel", classes="four")
|
|
||||||
|
|
||||||
# 4
|
# 4
|
||||||
yield Static(" ", classes="five")
|
yield Static("Index / Subindex")
|
||||||
|
yield Static("", id="index_label", classes="two")
|
||||||
|
yield Static("", id="subindex_label", classes="two")
|
||||||
|
|
||||||
# 5
|
# 5
|
||||||
yield Static(" ", classes="five")
|
yield Static(" ", classes="five")
|
||||||
|
|
||||||
# 6
|
# 6
|
||||||
yield Static("Language")
|
yield Static("Type")
|
||||||
yield Select.from_values(languages, classes="four", id="language_select")
|
yield Select.from_values([t.label() for t in TrackType], classes="four", id="type_select")
|
||||||
|
|
||||||
# 7
|
# 7
|
||||||
yield Static(" ", classes="five")
|
yield Static(" ", classes="five")
|
||||||
|
|
||||||
# 8
|
|
||||||
yield Static("Title")
|
|
||||||
yield Input(id="title_input", classes="four")
|
|
||||||
|
|
||||||
# 9
|
# 9
|
||||||
yield Static(" ", classes="five")
|
yield Static(" ", classes="five")
|
||||||
|
|
||||||
# 10
|
# 10
|
||||||
|
yield Static("Language")
|
||||||
|
yield Select.from_values(languages, classes="four", id="language_select")
|
||||||
|
# 11
|
||||||
yield Static(" ", classes="five")
|
yield Static(" ", classes="five")
|
||||||
|
|
||||||
# 11
|
|
||||||
yield Static("Stream tags")
|
|
||||||
yield Static(" ")
|
|
||||||
yield Button("Add", id="button_add_stream_tag")
|
|
||||||
yield Button("Edit", id="button_edit_stream_tag")
|
|
||||||
yield Button("Delete", id="button_delete_stream_tag")
|
|
||||||
# 12
|
# 12
|
||||||
yield self.trackTagsTable
|
yield Static("Title")
|
||||||
|
yield Input(id="title_input", classes="four")
|
||||||
|
|
||||||
# 13
|
# 13
|
||||||
yield Static(" ", classes="five")
|
yield Static(" ", classes="five")
|
||||||
|
|
||||||
# 14
|
# 14
|
||||||
yield Static("Stream dispositions", classes="five")
|
yield Static(" ", classes="five")
|
||||||
|
|
||||||
# 15
|
# 15
|
||||||
|
yield Static("Stream tags")
|
||||||
|
yield Static(" ")
|
||||||
|
yield Button("Add", id="button_add_stream_tag")
|
||||||
|
yield Button("Edit", id="button_edit_stream_tag")
|
||||||
|
yield Button("Delete", id="button_delete_stream_tag")
|
||||||
|
# 16
|
||||||
|
yield self.trackTagsTable
|
||||||
|
|
||||||
|
# 17
|
||||||
|
yield Static(" ", classes="five")
|
||||||
|
|
||||||
|
# 18
|
||||||
|
yield Static("Stream dispositions", classes="five")
|
||||||
|
|
||||||
|
# 19
|
||||||
yield SelectionList[int](
|
yield SelectionList[int](
|
||||||
classes="five",
|
classes="five",
|
||||||
id = "dispositions_selection_list"
|
id = "dispositions_selection_list"
|
||||||
)
|
)
|
||||||
|
|
||||||
# 16
|
# 20
|
||||||
yield Static(" ", classes="five")
|
yield Static(" ", classes="five")
|
||||||
# 17
|
# 21
|
||||||
yield Static(" ", classes="five")
|
yield Static(" ", classes="five")
|
||||||
|
|
||||||
# 18
|
# 22
|
||||||
yield Button("Save", id="save_button")
|
yield Button("Save", id="save_button")
|
||||||
yield Button("Cancel", id="cancel_button")
|
yield Button("Cancel", id="cancel_button")
|
||||||
|
|
||||||
# 19
|
# 23
|
||||||
yield Static(" ", classes="five")
|
yield Static(" ", classes="five")
|
||||||
|
|
||||||
# 20
|
# 24
|
||||||
yield Static(" ", classes="five", id="messagestatic")
|
yield Static(" ", classes="five", id="messagestatic")
|
||||||
|
|
||||||
|
|
||||||
@@ -243,9 +263,9 @@ class TrackDetailsScreen(Screen):
|
|||||||
kwargs[TrackDescriptor.PATTERN_ID_KEY] = int(self.__pattern.getId())
|
kwargs[TrackDescriptor.PATTERN_ID_KEY] = int(self.__pattern.getId())
|
||||||
|
|
||||||
kwargs[TrackDescriptor.INDEX_KEY] = self.__index
|
kwargs[TrackDescriptor.INDEX_KEY] = self.__index
|
||||||
kwargs[TrackDescriptor.SUB_INDEX_KEY] = self.__subIndex
|
kwargs[TrackDescriptor.SUB_INDEX_KEY] = self.__subIndex #!
|
||||||
|
|
||||||
kwargs[TrackDescriptor.TRACK_TYPE_KEY] = self.__trackType
|
kwargs[TrackDescriptor.TRACK_TYPE_KEY] = TrackType.fromLabel(self.query_one("#type_select", Select).value)
|
||||||
|
|
||||||
trackTags = {}
|
trackTags = {}
|
||||||
language = self.query_one("#language_select", Select).value
|
language = self.query_one("#language_select", Select).value
|
||||||
@@ -298,10 +318,10 @@ class TrackDetailsScreen(Screen):
|
|||||||
# Check if the button pressed is the one we are interested in
|
# Check if the button pressed is the one we are interested in
|
||||||
if event.button.id == "save_button":
|
if event.button.id == "save_button":
|
||||||
|
|
||||||
trackDescriptor = self.getTrackDescriptorFromInput()
|
|
||||||
|
|
||||||
# Check for multiple default/forced disposition flags
|
# Check for multiple default/forced disposition flags
|
||||||
|
|
||||||
|
if self.__trackType == TrackType.VIDEO:
|
||||||
|
trackList = self.__tc.findVideoTracks(self.__pattern.getId())
|
||||||
if self.__trackType == TrackType.AUDIO:
|
if self.__trackType == TrackType.AUDIO:
|
||||||
trackList = self.__tc.findAudioTracks(self.__pattern.getId())
|
trackList = self.__tc.findAudioTracks(self.__pattern.getId())
|
||||||
elif self.__trackType == TrackType.SUBTITLE:
|
elif self.__trackType == TrackType.SUBTITLE:
|
||||||
@@ -314,6 +334,9 @@ class TrackDetailsScreen(Screen):
|
|||||||
numDefaultTracks = len([t for t in siblingTrackList if TrackDisposition.DEFAULT in t.getDispositionSet()])
|
numDefaultTracks = len([t for t in siblingTrackList if TrackDisposition.DEFAULT in t.getDispositionSet()])
|
||||||
numForcedTracks = len([t for t in siblingTrackList if TrackDisposition.FORCED in t.getDispositionSet()])
|
numForcedTracks = len([t for t in siblingTrackList if TrackDisposition.FORCED in t.getDispositionSet()])
|
||||||
|
|
||||||
|
self.__subIndex = len(trackList)
|
||||||
|
trackDescriptor = self.getTrackDescriptorFromInput()
|
||||||
|
|
||||||
if ((TrackDisposition.DEFAULT in trackDescriptor.getDispositionSet() and numDefaultTracks)
|
if ((TrackDisposition.DEFAULT in trackDescriptor.getDispositionSet() and numDefaultTracks)
|
||||||
or (TrackDisposition.FORCED in trackDescriptor.getDispositionSet() and numForcedTracks)):
|
or (TrackDisposition.FORCED in trackDescriptor.getDispositionSet() and numForcedTracks)):
|
||||||
|
|
||||||
@@ -330,7 +353,7 @@ class TrackDetailsScreen(Screen):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
||||||
track = self.__tc.findTrack(self.__pattern.getId(), self.__trackType, self.__subIndex)
|
track = self.__tc.getTrack(self.__pattern.getId(), self.__index)
|
||||||
|
|
||||||
if self.__tc.updateTrack(track.getId(), trackDescriptor):
|
if self.__tc.updateTrack(track.getId(), trackDescriptor):
|
||||||
self.dismiss(trackDescriptor)
|
self.dismiss(trackDescriptor)
|
||||||
|
|||||||
Reference in New Issue
Block a user