def remove_book(self, book: Book): book.blacklist() self._model.invalidate() self._notify("authors") self._notify("readers") self._notify("books") self._notify("books-filter")
def load_file(track): """ Loads a given track into the player. :param track: track to be loaded """ global __current_track global __player if get_gst_player_state() == Gst.State.PLAYING: save_current_track_position() save_current_book_position(__current_track) __current_track = track emit_event("stop") __player.set_state(Gst.State.NULL) init() if cozy.control.filesystem_monitor.FilesystemMonitor().is_track_online( track): path = track.file else: path = OfflineCache().get_cached_path(track) if not path: path = track.file __player.set_property("uri", "file://" + path) __player.set_state(Gst.State.PAUSED) save_current_book_position(__current_track) Settings.update(last_played_book=__current_track.book).execute() Book.update(last_played=int(time.time())).where( Book.id == __current_track.book.id).execute() emit_event("track-changed", track)
def load_last_book(): """ Load the last played book into the player. """ global __current_track global __player last_book = Settings.get().last_played_book if last_book and last_book.position != 0: query = Track.select().where(Track.id == last_book.position) if query.exists(): last_track = query.get() if last_track: __player.set_state(Gst.State.NULL) if cozy.control.filesystem_monitor.FilesystemMonitor( ).is_track_online(last_track): path = last_track.file else: path = OfflineCache().get_cached_path(last_track) if not path: return __player.set_property("uri", "file://" + path) __player.set_state(Gst.State.PAUSED) __current_track = last_track Book.update(last_played=int(time.time())).where( Book.id == last_book.id).execute() emit_event("track-changed", last_track)
def _load_all_books(self): for book_db_obj in BookModel.select(BookModel.id): try: book = Book(self._db, book_db_obj.id) book.add_listener(self._on_book_event) self._books.append(book) except BookIsEmpty: pass
def save_current_book_position(track, pos=None): """ Saves the given track to it's book as the current position to the cozy.db. :param track: track object """ if pos is None: pos = track.id Book.update(position=pos).where(Book.id == track.book.id).execute()
def __on_download_switch_changed(self, switch, state): if self.download_switch.get_active(): Book.update(offline=True).where(Book.id == self.book.id).execute() OfflineCache().add(self.book) else: Book.update( offline=False, downloaded=False).where(Book.id == self.book.id).execute() OfflineCache().remove(self.book) self._set_book_download_status(False)
def clean_books(): """ Remove all books that have no tracks """ for book in Book.select(): if not get_track_for_playback(book): Book.update(position=0).where(Book.id == book.id).execute() if Track.select().where(Track.book == book).count() < 1: if Settings.get().last_played_book.id == book.id: Settings.update(last_played_book=None).execute() book.delete_instance()
def save_current_playback_speed(book=None, speed=None): """ Save the current or given playback speed to the cozy.db. :param book: Optional: Save for the given book :param speed: Optional: Save the given speed """ global __speed if book is None: book = get_current_track().book if speed is None: speed = __speed Book.update(playback_speed=speed).where(Book.id == book.id).execute()
def readers(): """ Find all readers in the database :return: all readers """ return Book.select(Book.reader).distinct().order_by(Book.reader)
def _load_all_books(self): with self._db: for book_db_obj in BookModel.select(BookModel.id): try: self._books.append(Book(self._db, book_db_obj.id)) except BookIsEmpty: pass
def update_time(self): if self.book is None: return # update book object # TODO: optimize usage by only asking from the db on track change query = Book.select().where(Book.id == self.book.id) if (query.exists()): self.book = query.get() else: self.book = None return if self.ui.titlebar.current_book and self.book.id == self.ui.titlebar.current_book.id: progress = get_book_progress(self.book, False) progress += (player.get_current_duration() / 1000000000) remaining = (self.duration - progress) else: progress = get_book_progress(self.book) remaining = get_book_remaining(self.book) percentage = progress / self.duration self.total_label.set_text( tools.seconds_to_human_readable(self.duration / self.speed)) if percentage > 0.005: self.remaining_text.set_visible(True) self.remaining_label.set_visible(True) self.remaining_label.set_text( tools.seconds_to_human_readable(remaining / self.speed)) else: self.remaining_text.set_visible(False) self.remaining_label.set_visible(False) self.progress_bar.set_fraction(percentage)
def __filter_books(self, book, data, notify_destroy): """ Filter the books in the book view according to the selected author/reader or "All". """ selected_stack = self.sort_stack.props.visible_child_name if tools.get_glib_settings().get_boolean("hide-offline"): if not self.fs_monitor.is_book_online(book.book): offline_available = Book.get( Book.id == book.book.id).downloaded else: offline_available = True else: offline_available = True if selected_stack == "author": row = self.author_box.get_selected_row() elif selected_stack == "reader": row = self.reader_box.get_selected_row() if selected_stack == "author" or selected_stack == "reader": if row is None: return True and offline_available field = row.data if field is None or field == _("All"): return True and offline_available else: if selected_stack == "author": return True and offline_available if book.book.author == field else False if selected_stack == "reader": return True and offline_available if book.book.reader == field else False elif selected_stack == "recent": return True and offline_available if book.book.last_played > 0 else False
def remove(self, book: Book): """ Remove all tracks of the given book from the cache. """ self._stop_processing() ids = {t.file_id for t in book.chapters} offline_elements = OfflineCacheModel.select().join(File).where( OfflineCacheModel.original_file.id << ids) for element in offline_elements: file_path = os.path.join(self.cache_dir, element.cached_file) if file_path == self.cache_dir: continue file = Gio.File.new_for_path(file_path) if file.query_exists(): file.delete() for item in self.queue: if self.current and item.id == self.current.id: self.filecopy_cancel.cancel() entries_to_delete = OfflineCacheModel.select().join(File).where( OfflineCacheModel.original_file.id << ids) ids_to_delete = [t.id for t in entries_to_delete] OfflineCacheModel.delete().where( OfflineCacheModel.id << ids_to_delete).execute() book.downloaded = False self.emit_event("book-offline-removed", book) self.queue = [] self._start_processing()
def authors(): """ Find all authors in the database :return: all authors """ return Book.select(Book.author).distinct().order_by(Book.author)
def _mark_current_track(self): """ Mark the current track position. """ book = Book.get(Book.id == self.book.id) if book.position == -1: self.deselect_track_element() self.current_track_element = None return for track_element in self.track_box.get_children(): if isinstance(track_element, DiskElement): continue elif track_element.track.id == book.position: self.current_track_element = track_element track_element.select() else: track_element.deselect() if book.position == 0: self.current_track_element = self.track_box.get_children()[1] self.current_track_element.select() if self.ui.titlebar.current_book and self.ui.titlebar.current_book.id == self.book.id: self.current_track_element.set_playing(player.is_playing())
def books(): """ Find all books in the database :return: all books """ return Book.select()
def __on_button_press(self, eventbox, event): """ Play the selected track. """ current_track = player.get_current_track() if current_track and current_track.id == self.track.id: player.play_pause(None) if player.get_gst_player_state() == Gst.State.PLAYING: player.jump_to_ns(Track.select().where( Track.id == self.track.id).get().position) else: player.load_file( Track.select().where(Track.id == self.track.id).get()) player.play_pause(None, True) Book.update(position=self.track).where( Book.id == self.track.book.id).execute()
def refresh_book_object(self): """ Refresh the internal book object from the database. """ try: self.book = Book.get(Book.id == self.book.id) except Exception as e: reporter.exception("book_element", e)
def play_pause_chapter(self, book: Book, chapter: Chapter): if not book or not chapter: log.error("Cannot play chapter which is None.") reporter.error("player", "Cannot play chapter which is None.") return self._play_chapter(book, chapter) book.position = chapter.id
def refresh_book_object(self): """ Refresh the internal book object from the database. """ try: self.book = Book.get(Book.id == self.book.id) except: pass
def search_readers(search_string): """ Search all readers in the db with the given substring. This ignores upper/lowercase and returns each reader only once. :param search_string: substring to search for :return: readers matching the substring """ return Book.select(Book.reader).where( Book.reader.contains(search_string)).distinct().order_by(Book.reader)
def _play_chapter(self, book: Book, chapter: Chapter): current_track = player.get_current_track() book.last_played = int(time.time()) if current_track and current_track.file == chapter.file: player.play_pause(None) else: player.load_file(chapter._db_object) player.play_pause(None, True)
def clean_db(): """ Delete everything from the database except settings. """ q = Track.delete() q.execute() q = Book.delete() q.execute() q = ArtworkCache.delete() q.execute()
def _update_book_position(self, book: BookModel, progress: int): try: book_model = Book(self._db, book.id) except BookIsEmpty: log.error("Could not restore book position because book is empty") return completed_chapter_length = 0 for chapter in book_model.chapters: old_position = progress if completed_chapter_length + chapter.length > old_position: chapter.position = chapter.start_position + ( (old_position - completed_chapter_length) * 10**9) book_model.position = chapter.id return else: completed_chapter_length += chapter.length book_model.position = 0
def search_books(search_string): """ Search all book names in the db with the given substring. This ignores upper/lowercase and returns each book name only once. :param search_string: substring to search for :return: book names matching the substring """ return Book.select(Book.name, Book.cover, Book.id).where( Book.name.contains(search_string) | Book.author.contains(search_string) | Book.reader.contains(search_string)).distinct().order_by(Book.name)
def update_book_download_status(self, book): """ Updates the downloaded status of a book. """ downloaded = True tracks = get_tracks(book) offline_tracks = OfflineCacheModel.select().where( OfflineCacheModel.track in tracks) if offline_tracks.count() < 1: downloaded = False else: for track in offline_tracks: if not track.copied: downloaded = False Book.update(downloaded=downloaded).where(Book.id == book.id).execute() if downloaded: self.emit_event("book-offline", book) else: self.emit_event("book-offline-removed", book)
def __ui_changed(self, event, message): """ Handler for events that occur in the main ui. """ if self.book is None or self.ui.titlebar.current_book is None or self.ui.titlebar.current_book.id != self.book.id: return if event == "playback-speed-changed": self.speed = Book.select().where( Book.id == self.book.id).get().playback_speed if self.ui.main_stack.props.visible_child_name == "book_overview": self.update_time()
def jump_to_book(self, book): """ Open book overview with the given book. """ # first update track ui book = Book.select().where(Book.id == book.id).get() self.book_overview.set_book(book) # then switch the stacks self.main_stack.props.visible_child_name = "book_overview" self.toolbar_revealer.set_reveal_child(False) self.search.close()
def __on_sort_stack_changed(self, widget, page): """ Switch to author selection """ page = self.sort_stack.props.visible_child_name if page == "recent": self.sort_stack_revealer.set_reveal_child(False) if Book.select().where(Book.last_played > 0).count() < 1: self.main_stack.props.visible_child_name = "nothing_here" else: self.sort_stack_revealer.set_reveal_child(True) self.main_stack.props.visible_child_name = "main" self.__on_listbox_changed(None, None)
def play_pause_chapter(self, book: Book, chapter: Chapter): if not book or not chapter: log.error("Cannot play chapter which is None.") reporter.error("player", "Cannot play chapter which is None.") return if self._book and self._book.current_chapter == chapter: self.play_pause() return if self._book != book: self._load_book(book) self._load_chapter(chapter) self._gst_player.play() book.position = chapter.id