8 Commits

Author SHA1 Message Date
Maveno
62877dfed6 ff 2024-11-19 07:54:39 +01:00
Maveno
87ff94e204 add codec srt 2024-11-19 07:54:06 +01:00
Maveno
0c78ed7cf7 ff 2024-11-18 21:15:29 +01:00
Maveno
4db9bfd103 ff 2024-11-18 20:57:04 +01:00
Maveno
db7700a6b9 fix #409: Doppelter Show-Eintrag bei ffx inspect 2024-11-18 20:53:15 +01:00
Maveno
222234f978 hf fix tmdb filename filters 2024-11-18 18:37:31 +01:00
Maveno
3672474ff5 ff 2024-11-18 07:53:07 +01:00
Maveno
5ff0fc3fad hf Episodenteil Substitutionen 2024-11-18 07:51:23 +01:00
10 changed files with 105 additions and 35 deletions

View File

@@ -22,7 +22,7 @@ from ffx.track_disposition import TrackDisposition
from ffx.track_codec import TrackCodec from ffx.track_codec import TrackCodec
from ffx.process import executeProcess from ffx.process import executeProcess
from ffx.helper import filterFilename from ffx.helper import filterFilename, substituteTmdbFilename
from ffx.helper import getEpisodeFileBasename from ffx.helper import getEpisodeFileBasename
from ffx.constants import DEFAULT_STEREO_BANDWIDTH, DEFAULT_AC3_BANDWIDTH, DEFAULT_DTS_BANDWIDTH, DEFAULT_7_1_BANDWIDTH from ffx.constants import DEFAULT_STEREO_BANDWIDTH, DEFAULT_AC3_BANDWIDTH, DEFAULT_DTS_BANDWIDTH, DEFAULT_7_1_BANDWIDTH
@@ -653,9 +653,9 @@ def convert(ctx,
ctx.obj['logger'].debug(f"tmdbEpisodeResult={tmdbEpisodeResult}") ctx.obj['logger'].debug(f"tmdbEpisodeResult={tmdbEpisodeResult}")
if tmdbEpisodeResult: if tmdbEpisodeResult:
filteredEpisodeName = filterFilename(tmdbEpisodeResult['name']) substitutedEpisodeName = filterFilename(substituteTmdbFilename(tmdbEpisodeResult['name']))
sourceFileBasename = getEpisodeFileBasename(showFilenamePrefix, sourceFileBasename = getEpisodeFileBasename(showFilenamePrefix,
filteredEpisodeName, substitutedEpisodeName,
shiftedShowSeason, shiftedShowSeason,
shiftedShowEpisode, shiftedShowEpisode,
indexSeasonDigits, indexSeasonDigits,

View File

@@ -1,4 +1,4 @@
import logging import re, logging
from jinja2 import Environment, Undefined from jinja2 import Environment, Undefined
from .constants import DEFAULT_OUTPUT_FILENAME_TEMPLATE from .constants import DEFAULT_OUTPUT_FILENAME_TEMPLATE
@@ -78,10 +78,7 @@ def filterFilename(fileName: str) -> str:
"""This filter replaces charactes from TMDB responses with characters """This filter replaces charactes from TMDB responses with characters
less problemating when using in filenames or removes them""" less problemating when using in filenames or removes them"""
# This appears in TMDB episode names fileName = str(fileName).replace('/', '-')
fileName = str(fileName).replace(' (*)', '')
fileName = str(fileName).replace('(*)', '')
fileName = str(fileName).replace(':', ';') fileName = str(fileName).replace(':', ';')
fileName = str(fileName).replace('*', '') fileName = str(fileName).replace('*', '')
fileName = str(fileName).replace("'", '') fileName = str(fileName).replace("'", '')
@@ -89,6 +86,30 @@ def filterFilename(fileName: str) -> str:
return fileName.strip() return fileName.strip()
def substituteTmdbFilename(fileName: str) -> str:
"""If chaining this method with filterFilename use this one first as the latter will destroy some patterns"""
# This indicates filler episodes in TMDB episode names
fileName = str(fileName).replace(' (*)', '')
fileName = str(fileName).replace('(*)', '')
# This indicates the index of multi-episode files
episodePartMatch = re.search("\\(([0-9]+)\\)$", fileName)
if episodePartMatch is not None:
partSuffix = str(episodePartMatch.group(0))
partIndex = episodePartMatch.groups()[0]
fileName = str(fileName).replace(partSuffix, f"Teil {partIndex}")
# Also multi-episodes with first and last episode index
episodePartMatch = re.search("\\(([0-9]+)[-\\/]([0-9]+)\\)$", fileName)
if episodePartMatch is not None:
partSuffix = str(episodePartMatch.group(0))
partFirstIndex = episodePartMatch.groups()[0]
partLastIndex = episodePartMatch.groups()[1]
fileName = str(fileName).replace(partSuffix, f"Teil {partFirstIndex}-{partLastIndex}")
return fileName
def getEpisodeFileBasename(showName, def getEpisodeFileBasename(showName,
episodeName, episodeName,

View File

@@ -15,6 +15,7 @@ from .show_details_screen import ShowDetailsScreen
from .pattern_details_screen import PatternDetailsScreen from .pattern_details_screen import PatternDetailsScreen
from ffx.track_type import TrackType from ffx.track_type import TrackType
from ffx.track_codec import TrackCodec
from ffx.model.track import Track from ffx.model.track import Track
from ffx.track_disposition import TrackDisposition from ffx.track_disposition import TrackDisposition
@@ -36,7 +37,7 @@ class MediaDetailsScreen(Screen):
Grid { Grid {
grid-size: 5 8; grid-size: 5 8;
grid-rows: 8 2 2 2 8 2 2 8; grid-rows: 8 2 2 2 2 8 2 2 8;
grid-columns: 25 25 120 10 75; grid-columns: 25 25 120 10 75;
height: 100%; height: 100%;
width: 100%; width: 100%;
@@ -90,6 +91,10 @@ class MediaDetailsScreen(Screen):
border: solid green; border: solid green;
} }
.purple {
tint: purple 40%;
}
.yellow { .yellow {
tint: yellow 40%; tint: yellow 40%;
} }
@@ -137,7 +142,25 @@ class MediaDetailsScreen(Screen):
self.loadProperties() self.loadProperties()
def getRowIndexFromShowId(self, showId : int) -> int: def removeShow(self, showId : int = -1):
"""Remove show entry from DataTable.
Removes the <New show> entry if showId is not set"""
for rowKey, row in self.showsTable.rows.items(): # dict[RowKey, Row]
rowData = self.showsTable.get_row(rowKey)
try:
if (showId == -1 and rowData[0] == ' '
or showId == int(rowData[0])):
self.showsTable.remove_row(rowKey)
return
except:
continue
def getRowIndexFromShowId(self, showId : int = -1) -> int:
"""Find the index of the row where the value in the specified column matches the target_value.""" """Find the index of the row where the value in the specified column matches the target_value."""
for rowKey, row in self.showsTable.rows.items(): # dict[RowKey, Row] for rowKey, row in self.showsTable.rows.items(): # dict[RowKey, Row]
@@ -145,7 +168,8 @@ class MediaDetailsScreen(Screen):
rowData = self.showsTable.get_row(rowKey) rowData = self.showsTable.get_row(rowKey)
try: try:
if showId == int(rowData[0]): if ((showId == -1 and rowData[0] == ' ')
or showId == int(rowData[0])):
return int(self.showsTable.get_row_index(rowKey)) return int(self.showsTable.get_row_index(rowKey))
except: except:
continue continue
@@ -378,33 +402,36 @@ class MediaDetailsScreen(Screen):
yield self.differencesTable yield self.differencesTable
# 2 # 2
yield Static(" ", classes="four")
# 3
yield Static(" ") yield Static(" ")
yield Button("Substitute", id="pattern_button") yield Button("Substitute", id="pattern_button")
yield Static(" ", classes="two") yield Static(" ", classes="two")
# 3 # 4
yield Static("Pattern") yield Static("Pattern")
yield Input(type="text", id='pattern_input', classes="two") yield Input(type="text", id='pattern_input', classes="two")
yield Static(" ") yield Static(" ")
# 4 # 5
yield Static(" ", classes="four") yield Static(" ", classes="four")
# 5 # 6
yield Static("Media Tags") yield Static("Media Tags")
yield self.mediaTagsTable yield self.mediaTagsTable
yield Static(" ") yield Static(" ")
# 6 # 7
yield Static(" ", classes="four") yield Static(" ", classes="four")
# 7 # 8
yield Static(" ") yield Static(" ")
yield Button("Set Default", id="select_default_button") yield Button("Set Default", id="select_default_button")
yield Button("Set Forced", id="select_forced_button") yield Button("Set Forced", id="select_forced_button")
yield Static(" ") yield Static(" ")
# 8 # 9
yield Static("Streams") yield Static("Streams")
yield self.tracksTable yield self.tracksTable
yield Static(" ") yield Static(" ")
@@ -462,7 +489,7 @@ class MediaDetailsScreen(Screen):
kwargs[TrackDescriptor.INDEX_KEY] = int(selected_track_data[0]) kwargs[TrackDescriptor.INDEX_KEY] = int(selected_track_data[0])
kwargs[TrackDescriptor.TRACK_TYPE_KEY] = TrackType.fromLabel(selected_track_data[1]) kwargs[TrackDescriptor.TRACK_TYPE_KEY] = TrackType.fromLabel(selected_track_data[1])
kwargs[TrackDescriptor.SUB_INDEX_KEY] = int(selected_track_data[2]) kwargs[TrackDescriptor.SUB_INDEX_KEY] = int(selected_track_data[2])
kwargs[TrackDescriptor.CODEC_NAME_KEY] = int(selected_track_data[3]) kwargs[TrackDescriptor.CODEC_KEY] = TrackCodec.fromLabel(selected_track_data[3])
kwargs[TrackDescriptor.AUDIO_LAYOUT_KEY] = AudioLayout.fromLabel(selected_track_data[4]) kwargs[TrackDescriptor.AUDIO_LAYOUT_KEY] = AudioLayout.fromLabel(selected_track_data[4])
return TrackDescriptor(**kwargs) return TrackDescriptor(**kwargs)
@@ -473,11 +500,10 @@ class MediaDetailsScreen(Screen):
return None return None
def getSelectedShowDescriptor(self): def getSelectedShowDescriptor(self) -> ShowDescriptor:
try: try:
# Fetch the currently selected row when 'Enter' is pressed
#selected_row_index = self.table.cursor_row
row_key, col_key = self.showsTable.coordinate_to_cell_key(self.showsTable.cursor_coordinate) row_key, col_key = self.showsTable.coordinate_to_cell_key(self.showsTable.cursor_coordinate)
if row_key is not None: if row_key is not None:
@@ -501,6 +527,13 @@ class MediaDetailsScreen(Screen):
def handle_new_pattern(self, showDescriptor: ShowDescriptor): def handle_new_pattern(self, showDescriptor: ShowDescriptor):
if type(showDescriptor) is not ShowDescriptor:
raise TypeError("MediaDetailsScreen.handle_new_pattern(): Argument 'showDescriptor' has to be of type ShowDescriptor")
self.removeShow()
showRowIndex = self.getRowIndexFromShowId(showDescriptor.getId())
if showRowIndex is None:
show = (showDescriptor.getId(), showDescriptor.getName(), showDescriptor.getYear()) show = (showDescriptor.getId(), showDescriptor.getName(), showDescriptor.getYear())
self.showsTable.add_row(*map(str, show)) self.showsTable.add_row(*map(str, show))
@@ -524,10 +557,11 @@ class MediaDetailsScreen(Screen):
def action_new_pattern(self): def action_new_pattern(self):
try: #TODO #427: Fehlermeldung in TUI
self.__currentMediaDescriptor.checkConfiguration() # try:
except ValueError: # self.__currentMediaDescriptor.checkConfiguration()
return # except ValueError:
# return
selectedShowDescriptor = self.getSelectedShowDescriptor() selectedShowDescriptor = self.getSelectedShowDescriptor()

View File

@@ -155,6 +155,7 @@ class PatternDetailsScreen(Screen):
trackLanguage = td.getLanguage() trackLanguage = td.getLanguage()
audioLayout = td.getAudioLayout() audioLayout = td.getAudioLayout()
row = (td.getIndex(), row = (td.getIndex(),
trackType.label(), trackType.label(),
typeCounter[trackType], typeCounter[trackType],
@@ -491,13 +492,14 @@ class PatternDetailsScreen(Screen):
trackType = trackDescriptor.getType() trackType = trackDescriptor.getType()
index = trackDescriptor.getIndex() index = trackDescriptor.getIndex()
subIndex = trackDescriptor.getSubIndex() subIndex = trackDescriptor.getSubIndex()
codec = trackDescriptor.getCodec()
language = trackDescriptor.getLanguage() language = trackDescriptor.getLanguage()
title = trackDescriptor.getTitle() title = trackDescriptor.getTitle()
row = (index, row = (index,
trackType.label(), trackType.label(),
subIndex, subIndex,
" ", codec.label(),
language.label(), language.label(),
title, title,
'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No', 'Yes' if TrackDisposition.DEFAULT in dispoSet else 'No',
@@ -512,7 +514,10 @@ class PatternDetailsScreen(Screen):
row_key, col_key = self.tracksTable.coordinate_to_cell_key(self.tracksTable.cursor_coordinate) row_key, col_key = self.tracksTable.coordinate_to_cell_key(self.tracksTable.cursor_coordinate)
self.tracksTable.update_cell(row_key, self.column_key_track_audio_layout, trackDescriptor.getAudioLayout().label()) self.tracksTable.update_cell(row_key, self.column_key_track_audio_layout,
trackDescriptor.getAudioLayout().label()
if trackDescriptor.getType() == TrackType.AUDIO else ' ')
self.tracksTable.update_cell(row_key, self.column_key_track_language, trackDescriptor.getLanguage().label()) 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_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_default, 'Yes' if TrackDisposition.DEFAULT in trackDescriptor.getDispositionSet() else 'No')

View File

@@ -400,7 +400,7 @@ class ShowDetailsScreen(Screen):
yield Footer() yield Footer()
def getShowDescriptorFromInput(self): def getShowDescriptorFromInput(self) -> ShowDescriptor:
kwargs = {} kwargs = {}

View File

@@ -162,4 +162,7 @@ class ShowsScreen(Screen):
yield self.table yield self.table
yield Footer() f = Footer()
f.description = "yolo"
yield f

View File

@@ -8,6 +8,7 @@ class TrackCodec(Enum):
AAC = {'identifier': 'aac', 'format': None, 'extension': 'aac' , 'label': 'AAC'} AAC = {'identifier': 'aac', 'format': None, 'extension': 'aac' , 'label': 'AAC'}
AC3 = {'identifier': 'ac3', 'format': 'ac3', 'extension': 'ac3' , 'label': 'AC3'} AC3 = {'identifier': 'ac3', 'format': 'ac3', 'extension': 'ac3' , 'label': 'AC3'}
DTS = {'identifier': 'dts', 'format': 'dts', 'extension': 'dts' , 'label': 'DTS'} DTS = {'identifier': 'dts', 'format': 'dts', 'extension': 'dts' , 'label': 'DTS'}
SRT = {'identifier': 'srt', 'format': 'srt', 'extension': 'srt' , 'label': 'SRT'}
ASS = {'identifier': 'ass', 'format': 'ass', 'extension': 'ass' , 'label': 'ASS'} ASS = {'identifier': 'ass', 'format': 'ass', 'extension': 'ass' , 'label': 'ASS'}
PGS = {'identifier': 'hdmv_pgs_subtitle', 'format': 'sup', 'extension': 'sup' , 'label': 'PGS'} PGS = {'identifier': 'hdmv_pgs_subtitle', 'format': 'sup', 'extension': 'sup' , 'label': 'PGS'}

View File

@@ -29,7 +29,7 @@ class TrackController():
s = self.Session() s = self.Session()
track = Track(pattern_id = patId, track = Track(pattern_id = patId,
track_type = int(trackDescriptor.getType().index()), track_type = int(trackDescriptor.getType().index()),
codec_name = str(trackDescriptor.getCodec().label()), codec_name = str(trackDescriptor.getCodec().identifier()),
index = int(trackDescriptor.getIndex()), index = int(trackDescriptor.getIndex()),
source_index = int(trackDescriptor.getSourceIndex()), source_index = int(trackDescriptor.getSourceIndex()),
disposition_flags = int(TrackDisposition.toFlags(trackDescriptor.getDispositionSet())), disposition_flags = int(TrackDisposition.toFlags(trackDescriptor.getDispositionSet())),

View File

@@ -292,7 +292,11 @@ class TrackDetailsScreen(Screen):
kwargs[TrackDescriptor.TRACK_TYPE_KEY] = TrackType.fromLabel(self.query_one("#type_select", Select).value) kwargs[TrackDescriptor.TRACK_TYPE_KEY] = TrackType.fromLabel(self.query_one("#type_select", Select).value)
kwargs[TrackDescriptor.CODEC_KEY] = self.__trackCodec kwargs[TrackDescriptor.CODEC_KEY] = self.__trackCodec
if self.__trackType == TrackType.AUDIO:
kwargs[TrackDescriptor.AUDIO_LAYOUT_KEY] = AudioLayout.fromLabel(self.query_one("#audio_layout_select", Select).value) kwargs[TrackDescriptor.AUDIO_LAYOUT_KEY] = AudioLayout.fromLabel(self.query_one("#audio_layout_select", Select).value)
else:
kwargs[TrackDescriptor.AUDIO_LAYOUT_KEY] = AudioLayout.LAYOUT_UNDEFINED
trackTags = {} trackTags = {}
language = self.query_one("#language_select", Select).value language = self.query_one("#language_select", Select).value

View File

@@ -2,6 +2,8 @@
. ~/.local/share/ffx.venv/bin/activate . ~/.local/share/ffx.venv/bin/activate
pushd ~/.local/src/ffx/ pushd ~/.local/src/ffx/
git checkout "${1:-main}"
git pull
pip install --editable . pip install --editable .
popd popd
deactivate deactivate