combine track datatables

click-textual
Maveno 12 months ago
parent ff93875a07
commit ca57e981a6

@ -188,28 +188,6 @@ class FileProperties():
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):
return MediaDescriptor.fromFfprobe(self.getFormatData(), self.getStreamData())

@ -34,8 +34,8 @@ class MediaDetailsScreen(Screen):
CSS = """
Grid {
grid-size: 4 9;
grid-rows: 8 2 2 2 8 2 8 2 8;
grid-size: 4 7;
grid-rows: 8 2 2 2 8 2 8;
grid-columns: 25 125 10 75;
height: 100%;
width: 100%;
@ -149,7 +149,7 @@ class MediaDetailsScreen(Screen):
#
# def updateAudioTracks(self):
#
# self.audioStreamsTable.clear()
# self.tracksTable.clear()
#
# if self.__pattern is not None:
#
@ -166,7 +166,7 @@ class MediaDetailsScreen(Screen):
# 'Yes' if TrackDisposition.DEFAULT 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):
#
@ -220,8 +220,9 @@ class MediaDetailsScreen(Screen):
row = (mediaTagKey, mediaTagValue) # Convert each element to a string before adding
self.mediaTagsTable.add_row(*map(str, row))
self.updateAudioTracks(self.__mediaDescriptor.getAudioTracks())
self.updateSubtitleTracks(self.__mediaDescriptor.getSubtitleTracks())
#self.updateAudioTracks(self.__mediaDescriptor.getAudioTracks())
#self.updateSubtitleTracks(self.__mediaDescriptor.getSubtitleTracks())
self.updateTracks()
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(),
" ",
at.getLanguage().label(),
at.getTitle(),
'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No',
'Yes' if TrackDisposition.FORCED in dispoSet else 'No')
self.audioStreamsTable.add_row(*map(str, row))
def updateSubtitleTracks(self, subtitleTracks):
self.subtitleStreamsTable.clear()
for td in trackDescriptorList:
for st in subtitleTracks:
trackType = td.getType()
if not trackType in typeCounter.keys():
typeCounter[trackType] = 0
dispoSet = st.getDispositionSet()
dispoSet = td.getDispositionSet()
row = (st.getSubIndex(),
row = (td.getIndex(),
trackType.label(),
typeCounter[trackType],
" ",
st.getLanguage().label(),
st.getTitle(),
td.getLanguage().label(),
td.getTitle(),
'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No',
'Yes' if TrackDisposition.FORCED in dispoSet else 'No')
self.subtitleStreamsTable.add_row(*map(str, row))
self.tracksTable.add_row(*map(str, row))
typeCounter[trackType] += 1
def compose(self):
@ -352,36 +345,24 @@ class MediaDetailsScreen(Screen):
# Define the columns with headers
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.audioStreamsTable = DataTable()
# Define the columns with headers
self.column_key_audio_subid = self.audioStreamsTable.add_column("Subindex", width=20)
self.column_key_audio_layout = self.audioStreamsTable.add_column("Layout", width=20)
self.column_key_audio_language = self.audioStreamsTable.add_column("Language", width=20)
self.column_key_audio_title = self.audioStreamsTable.add_column("Title", width=30)
self.column_key_audio_default = self.audioStreamsTable.add_column("Default", width=10)
self.column_key_audio_forced = self.audioStreamsTable.add_column("Forced", width=10)
self.audioStreamsTable.cursor_type = 'row'
self.subtitleStreamsTable = DataTable()
self.tracksTable = 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.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=5)
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.subtitleStreamsTable.cursor_type = 'row'
self.tracksTable.cursor_type = 'row'
# Create the DataTable widget
@ -392,8 +373,6 @@ class MediaDetailsScreen(Screen):
self.differencesTable.cursor_type = 'row'
yield Header()
with Grid():
@ -427,17 +406,17 @@ class MediaDetailsScreen(Screen):
yield Static(" ", classes="three")
# 7
yield Static("Audio Streams")
yield self.audioStreamsTable
yield Static("Streams")
yield self.tracksTable
yield Static(" ")
# 8
yield Static(" ", classes="three")
# 9
yield Static("Subtitle Streams")
yield self.subtitleStreamsTable
yield Static(" ")
# # 8
# yield Static(" ", classes="three")
#
# # 9
# yield Static("Subtitle Streams")
# yield self.subtitleStreamsTable
# yield Static(" ")
# 1
@ -467,7 +446,7 @@ class MediaDetailsScreen(Screen):
# yield Static("")
# yield Static("")
# # 6
# yield self.audioStreamsTable
# yield self.tracksTable
#
# # 7
# yield Static(" ", classes="five")
@ -511,10 +490,10 @@ class MediaDetailsScreen(Screen):
#
# # Fetch the currently selected row when 'Enter' is pressed
# #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:
# selected_track_data = self.audioStreamsTable.get_row(row_key)
# selected_track_data = self.tracksTable.get_row(row_key)
#
# subIndex = int(selected_track_data[0])
#
@ -589,7 +568,7 @@ class MediaDetailsScreen(Screen):
# if self.__pattern is not None:
#
# 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()
# if selectedAudioTrack is not None:
@ -638,7 +617,7 @@ class MediaDetailsScreen(Screen):
# 'Yes' if TrackDisposition.DEFAULT 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:
#
@ -657,12 +636,12 @@ class MediaDetailsScreen(Screen):
# 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.audioStreamsTable.update_cell(row_key, self.column_key_audio_title, trackDescriptor.getTitle())
# self.audioStreamsTable.update_cell(row_key, self.column_key_audio_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_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')
#
# if trackDescriptor.getType() == TrackType.SUBTITLE:
#

@ -32,7 +32,7 @@ class Track(Base):
track_type = Column(Integer) # TrackType
index = Column(Integer)
sub_index = Column(Integer)
# sub_index = Column(Integer)
# v1.x
pattern_id = Column(Integer, ForeignKey('patterns.id', ondelete="CASCADE"))
@ -57,7 +57,7 @@ class Track(Base):
@classmethod
def fromStreamObj(cls, streamObj, subIndex, patternId):
def fromStreamObj(cls, streamObj, patternId):
"""{
'index': 4,
'codec_name': 'hdmv_pgs_subtitle',
@ -128,8 +128,8 @@ class Track(Base):
if trackType in [t.label() for t in TrackType]:
# sub_index = int(subIndex),
return cls(pattern_id = patternId,
sub_index = int(subIndex),
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]))
@ -149,9 +149,6 @@ class Track(Base):
def getIndex(self):
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):
tags = {t.key:t.value for t in self.track_tags}
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}
def getDescriptor(self) -> TrackDescriptor:
def getDescriptor(self, subIndex : int = -1) -> TrackDescriptor:
kwargs = {}
@ -175,7 +172,9 @@ class Track(Base):
kwargs[TrackDescriptor.PATTERN_ID_KEY] = self.getPatternId()
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.DISPOSITION_SET_KEY] = self.getDispositionSet()

@ -8,6 +8,7 @@ from textual.containers import Grid
from ffx.model.show import Show
from ffx.model.pattern import Pattern
from ffx.model.track import Track
from .pattern_controller import PatternController
from .show_controller import ShowController
@ -30,8 +31,8 @@ class PatternDetailsScreen(Screen):
CSS = """
Grid {
grid-size: 5 12;
grid-rows: 2 2 2 2 2 6 2 2 6 2 2 2;
grid-size: 5 9;
grid-rows: 2 2 2 2 2 6 2 2 2;
grid-columns: 25 25 25 25 25;
height: 100%;
width: 100%;
@ -68,6 +69,10 @@ class PatternDetailsScreen(Screen):
height: 100%;
border: solid green;
}
#tracks_table {
row-span: 4;
}
"""
def __init__(self, patternId = None, showId = None):
@ -105,47 +110,38 @@ class PatternDetailsScreen(Screen):
s.close()
def updateAudioTracks(self):
def updateTracks(self):
self.audioStreamsTable.clear()
self.tracksTable.clear()
if self.__pattern is not None:
audioTracks = self.__tc.findAudioTracks(self.__pattern.getId())
for at in audioTracks:
dispoSet = at.getDispositionSet()
row = (at.getSubIndex(),
" ",
at.getLanguage().label(),
at.getTitle(),
'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No',
'Yes' if TrackDisposition.FORCED in dispoSet else 'No')
self.audioStreamsTable.add_row(*map(str, row))
tracks = self.__tc.findTracks(self.__pattern.getId())
def updateSubtitleTracks(self):
typeCounter = {}
self.subtitleStreamsTable.clear()
for tr in tracks:
if self.__pattern is not None:
subtitleTracks = self.__tc.findSubtitleTracks(self.__pattern.getId())
td : TrackDescriptor = tr.getDescriptor()
for st in subtitleTracks:
trackType = td.getType()
if not trackType in typeCounter.keys():
typeCounter[trackType] = 0
dispoSet = st.getDispositionSet()
dispoSet = td.getDispositionSet()
row = (st.getSubIndex(),
row = (td.getIndex(),
trackType.label(),
typeCounter[trackType],
" ",
st.getLanguage().label(),
st.getTitle(),
td.getLanguage().label(),
td.getTitle(),
'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No',
'Yes' if TrackDisposition.FORCED in dispoSet else 'No')
self.subtitleStreamsTable.add_row(*map(str, row))
self.tracksTable.add_row(*map(str, row))
typeCounter[trackType] += 1
def on_mount(self):
@ -157,38 +153,25 @@ class PatternDetailsScreen(Screen):
self.query_one("#pattern_input", Input).value = str(self.__pattern.getPattern())
self.updateAudioTracks()
self.updateSubtitleTracks()
self.updateTracks()
def compose(self):
self.audioStreamsTable = DataTable(classes="five")
# Define the columns with headers
self.column_key_audio_subid = self.audioStreamsTable.add_column("Subindex", width=20)
self.column_key_audio_layout = self.audioStreamsTable.add_column("Layout", width=20)
self.column_key_audio_language = self.audioStreamsTable.add_column("Language", width=20)
self.column_key_audio_title = self.audioStreamsTable.add_column("Title", width=30)
self.column_key_audio_default = self.audioStreamsTable.add_column("Default", width=10)
self.column_key_audio_forced = self.audioStreamsTable.add_column("Forced", width=10)
self.tracksTable = DataTable(id="tracks_table", classes="five")
self.audioStreamsTable.cursor_type = 'row'
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=5)
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.tracksTable.cursor_type = 'row'
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()
with Grid():
@ -200,7 +183,7 @@ class PatternDetailsScreen(Screen):
# 2
yield Static("from show")
yield Static("", id="showlabel", classes="three")
yield Button("Substitute pattern", id="patternbutton")
yield Button("Substitute pattern", id="pattern_button")
# 3
yield Static(" ", classes="five")
@ -208,42 +191,27 @@ class PatternDetailsScreen(Screen):
yield Static(" ", classes="five")
# 5
yield Static("Audio streams")
yield Static("Streams")
yield Static(" ")
if self.__pattern is not None:
yield Button("Add", id="button_add_audio_stream")
yield Button("Edit", id="button_edit_audio_stream")
yield Button("Delete", id="button_delete_audio_stream")
yield Button("Add", id="button_add_track")
yield Button("Edit", id="button_edit_track")
yield Button("Delete", id="button_delete_track")
else:
yield Static("")
yield Static("")
yield Static("")
# 6
yield self.audioStreamsTable
yield self.tracksTable
# 7
yield Static(" ", classes="five")
# 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")
# 11
# 9
yield Button("Save", id="save_button")
yield Button("Cancel", id="cancel_button")
@ -255,7 +223,7 @@ class PatternDetailsScreen(Screen):
def getSelectedAudioTrackDescriptor(self):
def getSelectedTrackDescriptor(self):
if not self.__pattern:
return None
@ -264,14 +232,15 @@ class PatternDetailsScreen(Screen):
# Fetch the currently selected row when 'Enter' is pressed
#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:
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:
return None
@ -280,32 +249,6 @@ class PatternDetailsScreen(Screen):
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
def on_button_pressed(self, event: Button.Pressed) -> None:
# Check if the button pressed is the one we are interested in
@ -327,14 +270,6 @@ class PatternDetailsScreen(Screen):
patternId = self.__pc.addPattern(patternDescriptor)
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)
else:
#TODO: Meldung
@ -349,36 +284,19 @@ class PatternDetailsScreen(Screen):
# Save pattern when just created before adding streams
if self.__pattern is not None:
numVideoStreams = len(self.__pattern.getMediaDescriptor().getVideoTracks())
numAudioStreams = len(self.audioStreamsTable.rows)
numSubtitleStreams = len(self.subtitleStreamsTable.rows)
addedTrackIndex = numVideoStreams + numAudioStreams + numSubtitleStreams
#NOTE: Track index
numTracks = len(self.tracksTable.rows)
if event.button.id == "button_add_audio_stream":
self.app.push_screen(TrackDetailsScreen(trackType = TrackType.AUDIO, patternId = self.__pattern.getId(), index = addedTrackIndex, subIndex = numAudioStreams), self.handle_add_track)
if event.button.id == "button_add_track":
self.app.push_screen(TrackDetailsScreen(patternId = self.__pattern.getId(), index = numTracks), self.handle_add_track)
selectedAudioTrack = self.getSelectedAudioTrackDescriptor()
if selectedAudioTrack is not None:
if event.button.id == "button_edit_audio_stream":
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)
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":
if event.button.id == "pattern_button":
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)
def handle_add_track(self, trackDescriptor):
def handle_add_track(self, trackDescriptor : TrackDescriptor):
dispoSet = trackDescriptor.getDispositionSet()
trackType = trackDescriptor.getType()
index = trackDescriptor.getIndex()
subIndex = trackDescriptor.getSubIndex()
language = trackDescriptor.getLanguage()
title = trackDescriptor.getTitle()
if trackType == TrackType.AUDIO:
row = (subIndex,
row = (index,
trackType.label(),
subIndex,
" ",
language.label(),
title,
'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No',
'Yes' if TrackDisposition.FORCED in dispoSet else 'No')
self.audioStreamsTable.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))
self.tracksTable.add_row(*map(str, row))
def handle_edit_track(self, trackDescriptor : TrackDescriptor):
try:
if trackDescriptor.getType() == TrackType.AUDIO:
row_key, col_key = self.audioStreamsTable.coordinate_to_cell_key(self.audioStreamsTable.cursor_coordinate)
self.audioStreamsTable.update_cell(row_key, self.column_key_audio_language, trackDescriptor.getLanguage().label())
self.audioStreamsTable.update_cell(row_key, self.column_key_audio_title, trackDescriptor.getTitle())
self.audioStreamsTable.update_cell(row_key, self.column_key_audio_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')
row_key, col_key = self.tracksTable.coordinate_to_cell_key(self.tracksTable.cursor_coordinate)
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')
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')
except CellDoesNotExist:
pass
def handle_delete_track(self, trackDescriptor : TrackDescriptor):
try:
if trackDescriptor.getType() == TrackType.AUDIO:
self.updateAudioTracks()
if trackDescriptor.getType() == TrackType.SUBTITLE:
self.updateSubtitleTracks()
except CellDoesNotExist:
pass
self.updateTracks()

@ -21,14 +21,13 @@ class TrackController():
self.Session = self.context['database']['session'] # convenience
def addTrack(self, trackDescriptor):
def addTrack(self, trackDescriptor : TrackDescriptor):
try:
s = self.Session()
track = Track(pattern_id = int(trackDescriptor.getPatternId()),
track_type = int(trackDescriptor.getType().index()),
index = int(trackDescriptor.getIndex()),
sub_index = int(trackDescriptor.getSubIndex()),
disposition_flags = int(TrackDisposition.toFlags(trackDescriptor.getDispositionSet())))
s.add(track)
@ -89,6 +88,32 @@ class TrackController():
finally:
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):
@ -117,11 +142,11 @@ class TrackController():
s.close()
def findTrack(self, patternId : int, trackType : TrackType, subIndex : int) -> Track:
def getTrack(self, patternId : int, index: int) -> Track:
try:
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():
return q.first()
@ -129,37 +154,35 @@ class TrackController():
return None
except Exception as ex:
raise click.ClickException(f"TrackController.findTrack(): {repr(ex)}")
raise click.ClickException(f"TrackController.getTrack(): {repr(ex)}")
finally:
s.close()
def deleteTrack(self, trackId):
try:
s = self.Session()
q = s.query(Track).filter(Track.id == int(trackId))
if q.count():
patternId = int(q.first().pattern_id)
track = q.first()
q_siblings = s.query(Track).filter(Track.pattern_id == track.getPatternId(), Track.track_type == track.getType().index()).order_by(Track.sub_index)
q_siblings = s.query(Track).filter(Track.pattern_id == patternId).order_by(Track.index)
subIndex = 0
index = 0
for track in q_siblings.all():
if track.sub_index == track.getSubIndex():
if track.id == int(trackId):
s.delete(track)
else:
track.sub_index = subIndex
subIndex += 1
track.index = index
index += 1
s.commit()
return True
return False
except Exception as ex:
raise click.ClickException(f"TrackController.deleteTrack(): {repr(ex)}")
finally:

@ -7,6 +7,7 @@ from textual.widgets import Header, Footer, Static, Button
from textual.containers import Grid
from ffx.model.pattern import Pattern
from ffx.model.track import Track
from ffx.track_descriptor import TrackDescriptor
from .track_controller import TrackController
@ -121,7 +122,7 @@ class TrackDeleteScreen(Screen):
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:
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 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]
else:
self.__subIndex = -1
if TrackDescriptor.TRACK_TYPE_KEY in kwargs.keys():
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")

@ -7,6 +7,7 @@ from textual.widgets import Header, Footer, Static, Button, SelectionList, Selec
from textual.containers import Grid
from ffx.model.pattern import Pattern
from ffx.model.track import Track
from .track_controller import TrackController
from .pattern_controller import PatternController
@ -32,9 +33,9 @@ class TrackDetailsScreen(Screen):
CSS = """
Grid {
grid-size: 5 20;
grid-rows: 2 2 2 2 2 3 2 2 2 2 2 6 2 2 6 2 2 2 2 6;
grid-columns: 25 25 25 25 225;
grid-size: 5 21;
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 125;
height: 100%;
width: 100%;
padding: 1;
@ -79,6 +80,10 @@ class TrackDetailsScreen(Screen):
height: 100%;
border: solid green;
}
.yellow {
tint: yellow 40%;
}
"""
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):
self.query_one("#index_label", Static).update(str(self.__index) if self.__index is not None else '-')
self.query_one("#subindex_label", Static).update(str(self.__subIndex)if self.__subIndex is not None else '-')
if self.__pattern is not None:
self.query_one("#patternlabel", Static).update(self.__pattern.getPattern())
self.query_one("#pattern_label", Static).update(self.__pattern.getPattern())
if self.__subIndex is not None:
self.query_one("#subindexlabel", Static).update(str(self.__subIndex))
if self.__trackType is not None:
self.query_one("#type_select", Select).value = self.__trackType.label()
for d in TrackDisposition:
@ -153,7 +161,7 @@ class TrackDetailsScreen(Screen):
# Define the columns with headers
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'
@ -165,71 +173,83 @@ class TrackDetailsScreen(Screen):
with Grid():
# 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
yield Static("for pattern")
yield Static("", id="patternlabel", classes="four")
yield Static("", id="pattern_label", classes="four")
# 3
yield Static("sub index")
yield Static("", id="subindexlabel", classes="four")
yield Static(" ", classes="five")
# 4
yield Static(" ", classes="five")
yield Static("Index / Subindex")
yield Static("", id="index_label", classes="two")
yield Static("", id="subindex_label", classes="two")
# 5
yield Static(" ", classes="five")
# 6
yield Static("Type")
yield Select.from_values([t.label() for t in TrackType], classes="four", id="type_select")
# 7
yield Static(" ", classes="five")
# 9
yield Static(" ", classes="five")
# 10
yield Static("Language")
yield Select.from_values(languages, classes="four", id="language_select")
# 7
# 11
yield Static(" ", classes="five")
# 8
# 12
yield Static("Title")
yield Input(id="title_input", classes="four")
# 9
# 13
yield Static(" ", classes="five")
# 10
# 14
yield Static(" ", classes="five")
# 11
# 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")
# 12
# 16
yield self.trackTagsTable
# 13
# 17
yield Static(" ", classes="five")
# 14
# 18
yield Static("Stream dispositions", classes="five")
# 15
# 19
yield SelectionList[int](
classes="five",
id = "dispositions_selection_list"
)
# 16
# 20
yield Static(" ", classes="five")
# 17
# 21
yield Static(" ", classes="five")
# 18
# 22
yield Button("Save", id="save_button")
yield Button("Cancel", id="cancel_button")
# 19
# 23
yield Static(" ", classes="five")
# 20
# 24
yield Static(" ", classes="five", id="messagestatic")
@ -243,9 +263,9 @@ class TrackDetailsScreen(Screen):
kwargs[TrackDescriptor.PATTERN_ID_KEY] = int(self.__pattern.getId())
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 = {}
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
if event.button.id == "save_button":
trackDescriptor = self.getTrackDescriptorFromInput()
# Check for multiple default/forced disposition flags
if self.__trackType == TrackType.VIDEO:
trackList = self.__tc.findVideoTracks(self.__pattern.getId())
if self.__trackType == TrackType.AUDIO:
trackList = self.__tc.findAudioTracks(self.__pattern.getId())
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()])
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)
or (TrackDisposition.FORCED in trackDescriptor.getDispositionSet() and numForcedTracks)):
@ -330,7 +353,7 @@ class TrackDetailsScreen(Screen):
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):
self.dismiss(trackDescriptor)

Loading…
Cancel
Save