Bookmarks improved. Removed old terminal based entry method, now using the pygame version.
This commit is contained in:
+78
-37
@@ -54,6 +54,7 @@ from src.bookmarks_menu import BookmarksMenu
|
||||
from src.wav_exporter import WavExporter
|
||||
from src.braille_output import BrailleOutput
|
||||
from src.braille_menu import BrailleMenu
|
||||
from src.ui import get_input
|
||||
|
||||
|
||||
class BookReader:
|
||||
@@ -1237,7 +1238,7 @@ class BookReader:
|
||||
self.speechEngine.speak("No book loaded")
|
||||
|
||||
elif event.key == pygame.K_HOME and shiftPressed:
|
||||
# Shift+Home: Clear bookmark and jump to beginning of book
|
||||
# Shift+Home: Clear ALL bookmarks and jump to beginning of book (fresh start)
|
||||
if not self.book:
|
||||
self.speechEngine.speak("No book loaded")
|
||||
else:
|
||||
@@ -1246,8 +1247,9 @@ class BookReader:
|
||||
self.isPlaying = False
|
||||
self._stop_playback()
|
||||
|
||||
# Delete bookmark for current book
|
||||
self.bookmarkManager.delete_bookmark(self.bookPath)
|
||||
# Delete ALL bookmarks for current book (auto-save + named)
|
||||
self.bookmarkManager.delete_bookmark(self.bookPath) # Auto-save bookmark
|
||||
self.bookmarkManager.delete_all_named_bookmarks(self.bookPath) # Named bookmarks
|
||||
self.bookmarkCleared = True # Mark that bookmark was explicitly cleared
|
||||
|
||||
# Jump to beginning
|
||||
@@ -1255,24 +1257,36 @@ class BookReader:
|
||||
self.currentParagraph = 0
|
||||
self.savedAudioPosition = 0.0
|
||||
|
||||
# For audio books, seek to beginning
|
||||
# For audio books, we need to restart playback from position 0
|
||||
# We can't just seek when stopped - mpv won't load the file metadata when idle
|
||||
if hasattr(self.book, 'isAudioBook') and self.book.isAudioBook:
|
||||
if hasattr(self.book, 'isMultiFile') and self.book.isMultiFile:
|
||||
# Multi-file: seek to first file in playlist
|
||||
# Multi-file: Start playing first file from beginning
|
||||
if self.audioPlayer.is_audio_file_loaded():
|
||||
self.audioPlayer.seek_to_playlist_index(0)
|
||||
self.audioPlayer.seek_audio(0.0)
|
||||
# Stop completely to reset state
|
||||
self.audioPlayer.stop_audio_file()
|
||||
# Set playlist to first file (don't wait for load - play will trigger it)
|
||||
self.audioPlayer.seek_to_playlist_index(0, waitForLoad=False)
|
||||
# Start playback from position 0
|
||||
self.audioPlayer.play_audio_file(startPosition=0.0)
|
||||
else:
|
||||
# Single-file: seek to time 0
|
||||
# Single-file: restart from beginning
|
||||
if self.audioPlayer.is_audio_file_loaded():
|
||||
self.audioPlayer.seek_audio(0.0)
|
||||
self.audioPlayer.stop_audio_file()
|
||||
self.audioPlayer.play_audio_file(startPosition=0.0)
|
||||
|
||||
self.speechEngine.speak("Bookmark cleared. Jumped to beginning of book.")
|
||||
|
||||
# Resume playback if it was playing
|
||||
if wasPlaying:
|
||||
# Mark as playing
|
||||
self.isPlaying = True
|
||||
self._start_paragraph_playback()
|
||||
self.isAudioBook = True
|
||||
|
||||
# Update display
|
||||
if self.config.get_show_text():
|
||||
self._render_screen()
|
||||
|
||||
self.speechEngine.speak("All bookmarks cleared. Playing from beginning of book.")
|
||||
|
||||
# Note: For audio books, we auto-start playback from the beginning
|
||||
# For text books, this is just a position reset and user needs to press space
|
||||
|
||||
elif event.key == pygame.K_LEFT:
|
||||
# Left arrow: Seek backward (audio books) or previous paragraph (text books)
|
||||
@@ -1479,20 +1493,36 @@ class BookReader:
|
||||
audioPosition = bookmark.get('audioPosition', 0.0)
|
||||
bookmarkName = bookmark['name']
|
||||
|
||||
# Stop current playback
|
||||
self.isPlaying = False
|
||||
if self.ttsEngine:
|
||||
self.audioPlayer.stop()
|
||||
else:
|
||||
self.readingEngine.stop()
|
||||
self.audioPlayer.stop_audio_file()
|
||||
# Check if this is an audio book
|
||||
isAudioBook = hasattr(self.book, 'isAudioBook') and self.book.isAudioBook
|
||||
|
||||
# For text books, stop playback before jumping
|
||||
# For audio books, we'll pause and seek without stopping (to keep mpv active)
|
||||
if not isAudioBook:
|
||||
self.isPlaying = False
|
||||
if self.ttsEngine:
|
||||
self.audioPlayer.stop()
|
||||
else:
|
||||
self.readingEngine.stop()
|
||||
self.audioPlayer.stop_audio_file()
|
||||
|
||||
# Update position
|
||||
self.currentChapter = chapterIndex
|
||||
self.currentParagraph = paragraphIndex
|
||||
|
||||
# For audio books, seek to audio position
|
||||
if hasattr(self.book, 'isAudioBook') and self.book.isAudioBook:
|
||||
# For audio books, we need to seek to the bookmark position
|
||||
if isAudioBook:
|
||||
# Check if audio is currently playing or has been played before
|
||||
wasPlaying = self.isPlaying
|
||||
hasBeenPlayed = self.audioPlayer.is_audio_file_playing() or self.audioPlayer.is_paused()
|
||||
|
||||
# If never played, we'll start playback at the bookmark position
|
||||
# If already playing/paused, we'll seek to the position
|
||||
if hasBeenPlayed:
|
||||
# Pause if playing (keeps mpv active for seeking)
|
||||
if self.audioPlayer.is_audio_file_playing():
|
||||
self.audioPlayer.pause_audio_file()
|
||||
|
||||
# Find chapter that contains this audio position
|
||||
for i, chapter in enumerate(self.book.chapters):
|
||||
if hasattr(chapter, 'startTime'):
|
||||
@@ -1505,15 +1535,32 @@ class BookReader:
|
||||
# For multi-file audiobooks, seek to correct file in playlist
|
||||
if hasattr(self.book, 'isMultiFile') and self.book.isMultiFile:
|
||||
if self.audioPlayer.is_audio_file_loaded():
|
||||
if self.audioPlayer.seek_to_playlist_index(self.currentChapter):
|
||||
# Seek to position within the file
|
||||
self.audioPlayer.seek_audio(positionInChapter)
|
||||
if hasBeenPlayed:
|
||||
# Already playing/paused - just seek
|
||||
if self.audioPlayer.seek_to_playlist_index(self.currentChapter, waitForLoad=False):
|
||||
self.audioPlayer.seek_audio(positionInChapter)
|
||||
else:
|
||||
# Never played - start playback at the bookmark position
|
||||
self.audioPlayer.seek_to_playlist_index(self.currentChapter, waitForLoad=False)
|
||||
self.audioPlayer.play_audio_file(startPosition=positionInChapter)
|
||||
self.isPlaying = True
|
||||
else:
|
||||
# Single-file audiobook: seek to absolute position
|
||||
# Single-file audiobook
|
||||
if self.audioPlayer.is_audio_file_loaded():
|
||||
self.audioPlayer.seek_audio(audioPosition)
|
||||
if hasBeenPlayed:
|
||||
# Already playing/paused - just seek
|
||||
self.audioPlayer.seek_audio(audioPosition)
|
||||
else:
|
||||
# Never played - start playback at the bookmark position
|
||||
self.audioPlayer.play_audio_file(startPosition=audioPosition)
|
||||
self.isPlaying = True
|
||||
break
|
||||
|
||||
# Resume playback if it was playing before (but not if we just started it)
|
||||
if hasBeenPlayed and wasPlaying:
|
||||
self.audioPlayer.resume_audio_file()
|
||||
self.isPlaying = True
|
||||
|
||||
# Speak feedback
|
||||
if self.speechEngine:
|
||||
chapter = self.book.get_chapter(self.currentChapter)
|
||||
@@ -1526,17 +1573,11 @@ class BookReader:
|
||||
|
||||
def _create_named_bookmark(self):
|
||||
"""Create a new named bookmark"""
|
||||
import getpass
|
||||
|
||||
if self.speechEngine:
|
||||
self.speechEngine.speak("Enter bookmark name. Check terminal.")
|
||||
|
||||
print("\n=== Create Bookmark ===")
|
||||
bookmarkName = input("Bookmark name: ").strip()
|
||||
# Use accessible text input dialog
|
||||
bookmarkName = get_input(self.speechEngine, prompt="Enter bookmark name")
|
||||
|
||||
if not bookmarkName:
|
||||
if self.speechEngine:
|
||||
self.speechEngine.speak("Cancelled")
|
||||
# User cancelled or entered empty name
|
||||
return
|
||||
|
||||
# Calculate audio position if audio book
|
||||
|
||||
Reference in New Issue
Block a user