mirror of
https://github.com/denizsafak/abogen.git
synced 2026-07-18 05:40:26 +02:00
Add preview button to voice mixer
This commit is contained in:
+2
-1
@@ -1,4 +1,5 @@
|
||||
- Added `Insert chapter marker` button in text editor to insert chapter markers at the current cursor position.
|
||||
- Added `Preview` button in voice mixer to preview the voice mix with the selected settings.
|
||||
- Fixed `f-string: unmatched '['` error in Voice preview, mentioned in #14
|
||||
- Fixed the content before first chapter not being included in the output (added handling for initial content).
|
||||
- Fixed the issue with the content before first chapter not being included in the output.
|
||||
- Fixed m4b chapter generation opens CMD window in Windows.
|
||||
+6
-7
@@ -290,8 +290,8 @@ class InputBox(QLabel):
|
||||
)
|
||||
win.selected_book_path = file_path
|
||||
win.open_book_file(
|
||||
file_path
|
||||
) # This will handle the dialog and setting file info
|
||||
file_path # This will handle the dialog and setting file info
|
||||
)
|
||||
event.acceptProposedAction()
|
||||
else:
|
||||
self.set_error("Please drop a .txt, .epub, or .pdf file.")
|
||||
@@ -328,7 +328,7 @@ class TextboxDialog(QDialog):
|
||||
self.setWindowFlags(
|
||||
Qt.Window | Qt.WindowCloseButtonHint | Qt.WindowMaximizeButtonHint
|
||||
)
|
||||
self.resize(600, 400)
|
||||
self.resize(700, 500)
|
||||
|
||||
layout = QVBoxLayout(self)
|
||||
|
||||
@@ -452,7 +452,7 @@ class TextboxDialog(QDialog):
|
||||
def insert_chapter_marker(self):
|
||||
# Insert a fixed chapter marker without prompting
|
||||
cursor = self.text_edit.textCursor()
|
||||
cursor.insertText("<<CHAPTER_MARKER:Chapter Title>>")
|
||||
cursor.insertText("<<CHAPTER_MARKER:Title>>")
|
||||
self.text_edit.setTextCursor(cursor)
|
||||
self.update_char_count()
|
||||
|
||||
@@ -1500,14 +1500,14 @@ class abogen(QWidget):
|
||||
# Build voice formula string
|
||||
components = [f"{name}*{weight}" for name, weight in self.mixed_voice_state]
|
||||
voice = " + ".join(filter(None, components))
|
||||
# determine language: use profile setting if available, else first voice code
|
||||
# determine language: use profile setting, else explicit mixer selection, else fallback to first voice code
|
||||
if self.selected_profile_name:
|
||||
from voice_profiles import load_profiles
|
||||
|
||||
entry = load_profiles().get(self.selected_profile_name, {})
|
||||
lang = entry.get("language")
|
||||
else:
|
||||
lang = None
|
||||
lang = self.selected_lang
|
||||
if not lang and self.mixed_voice_state:
|
||||
lang = (
|
||||
self.mixed_voice_state[0][0][0]
|
||||
@@ -2138,4 +2138,3 @@ class abogen(QWidget):
|
||||
"Setting Saved",
|
||||
f"Maximum words per subtitle set to {value}.",
|
||||
)
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ VOICE_MIXER_WIDTH = 100
|
||||
SLIDER_WIDTH = 32
|
||||
MIN_WINDOW_WIDTH = 600
|
||||
MIN_WINDOW_HEIGHT = 400
|
||||
INITIAL_WINDOW_WIDTH = 1000
|
||||
INITIAL_WINDOW_WIDTH = 1200
|
||||
INITIAL_WINDOW_HEIGHT = 500
|
||||
|
||||
# Language options for the language selector loaded from constants
|
||||
@@ -413,6 +413,11 @@ class VoiceFormulaDialog(QDialog):
|
||||
self.language_combo.setCurrentIndex(idx)
|
||||
self.language_combo.currentIndexChanged.connect(self.mark_profile_modified)
|
||||
header_row.addWidget(self.language_combo)
|
||||
# Preview current voice mix using main window's preview
|
||||
self.btn_preview_mix = QPushButton("Preview", self)
|
||||
self.btn_preview_mix.setToolTip("Preview current voice mix")
|
||||
self.btn_preview_mix.clicked.connect(self.preview_current_mix)
|
||||
header_row.addWidget(self.btn_preview_mix)
|
||||
mixer_layout.addLayout(header_row)
|
||||
|
||||
# Error message
|
||||
@@ -708,6 +713,8 @@ class VoiceFormulaDialog(QDialog):
|
||||
]
|
||||
|
||||
total = sum(w for _, w in selected)
|
||||
# disable Preview if no voices selected
|
||||
self.btn_preview_mix.setEnabled(total > 0)
|
||||
|
||||
if total > 0:
|
||||
self.error_label.hide()
|
||||
@@ -1338,3 +1345,37 @@ class VoiceFormulaDialog(QDialog):
|
||||
else:
|
||||
item.setBackground(QColor("white"))
|
||||
self.update_profile_save_buttons()
|
||||
|
||||
def preview_current_mix(self):
|
||||
# Disable preview until playback completes
|
||||
self.btn_preview_mix.setEnabled(False)
|
||||
self.btn_preview_mix.setText("Loading...")
|
||||
parent = self.parent()
|
||||
if parent and hasattr(parent, "preview_voice"):
|
||||
# Apply mixed voices and selected language
|
||||
parent.mixed_voice_state = self.get_selected_voices()
|
||||
parent.selected_profile_name = None
|
||||
lang = self.language_combo.currentData()
|
||||
parent.selected_lang = lang
|
||||
parent.subtitle_combo.setEnabled(
|
||||
lang in SUPPORTED_LANGUAGES_FOR_SUBTITLE_GENERATION
|
||||
)
|
||||
# Reset start flag and trigger preview
|
||||
self._started = False
|
||||
parent.preview_voice()
|
||||
# Poll preview_playing: wait for start then end
|
||||
self._preview_poll_timer = QTimer(self)
|
||||
self._preview_poll_timer.timeout.connect(self._check_preview_done)
|
||||
self._preview_poll_timer.start(200)
|
||||
|
||||
def _check_preview_done(self):
|
||||
parent = self.parent()
|
||||
if parent and hasattr(parent, "preview_playing"):
|
||||
# Mark when playback starts
|
||||
if parent.preview_playing:
|
||||
self._started = True
|
||||
# Once started and then stopped, re-enable
|
||||
elif getattr(self, "_started", False):
|
||||
self.btn_preview_mix.setEnabled(True)
|
||||
self.btn_preview_mix.setText("Preview")
|
||||
self._preview_poll_timer.stop()
|
||||
|
||||
Reference in New Issue
Block a user