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 __init__(self): self.ui = cozy.ui.main_view.CozyUI() builder = self.ui.window_builder self.name_label = builder.get_object("info_book_label") self.author_label = builder.get_object("info_author_label") self.download_box = builder.get_object("info_download_box") self.download_label = builder.get_object("info_download_label") self.download_image = builder.get_object("info_download_image") self.download_switch = builder.get_object("info_download_switch") self.published_label = builder.get_object("info_published_label") self.last_played_label = builder.get_object("info_last_played_label") self.total_label = builder.get_object("info_total_label") self.remaining_label = builder.get_object("info_remaining_label") self.progress_bar = builder.get_object("book_progress_bar") self.cover_img = builder.get_object("info_cover_image") self.track_list_container = builder.get_object("track_list_container") self.published_text = builder.get_object("info_published_text") self.remaining_text = builder.get_object("info_remaining_text") self.play_book_button = builder.get_object("play_book_button") self.play_book_button.connect("clicked", self.__on_play_clicked) self.play_img = builder.get_object("play_img1") self.pause_img = builder.get_object("pause_img1") self.scroller = builder.get_object("book_overview_scroller") if Gtk.get_minor_version() > 20: self.scroller.props.propagate_natural_height = True self.ui.speed.add_listener(self.__ui_changed) player.add_player_listener(self.__player_changed) self._settings.add_listener(self.__settings_changed) OfflineCache().add_listener(self.__on_offline_cache_changed)
def load_last_book(): """ Load the last played book into the player. """ global __current_track global __player last_book = cozy.control.db.Settings.get().last_played_book if last_book and last_book.position != 0: query = cozy.control.db.Track.select().where(cozy.control.db.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: path = last_track.file __player.set_property("uri", "file://" + path) __player.set_state(Gst.State.PAUSED) __current_track = last_track cozy.control.db.Book.update(last_played=int(time.time())).where( cozy.control.db.Book.id == last_book.id).execute() emit_event("track-changed", last_track)
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) cozy.control.db.Settings.update(last_played_book=__current_track.book).execute() cozy.control.db.Book.update(last_played=int(time.time())).where( cozy.control.db.Book.id == __current_track.book.id).execute() emit_event("track-changed", track)
def configure_inject(self, binder): binder.bind_to_provider(SqliteDatabase, get_db) binder.bind("MainWindow", self.main_window) binder.bind_to_constructor( Gio.Settings, lambda: Gio.Settings("com.github.geigi.cozy")) binder.bind_to_constructor(ApplicationSettings, lambda: ApplicationSettings()) binder.bind_to_constructor(Settings, lambda: Settings()) binder.bind_to_constructor("FilesystemMonitor", lambda: FilesystemMonitor()) binder.bind_to_constructor(OfflineCache, lambda: OfflineCache()) binder.bind_to_constructor(Player, lambda: Player()) binder.bind_to_constructor(Library, lambda: Library()) binder.bind_to_constructor(LibraryViewModel, lambda: LibraryViewModel()) binder.bind_to_constructor(SearchViewModel, lambda: SearchViewModel()) binder.bind_to_constructor(UISettings, lambda: UISettings()) binder.bind_to_constructor(StorageBlockList, lambda: StorageBlockList()) binder.bind_to_constructor(Files, lambda: Files()) binder.bind_to_constructor(BookDetailViewModel, lambda: BookDetailViewModel()) binder.bind_to_constructor(PlaybackControlViewModel, lambda: PlaybackControlViewModel()) binder.bind_to_constructor(HeaderbarViewModel, lambda: HeaderbarViewModel()) binder.bind_to_constructor(PlaybackSpeedViewModel, lambda: PlaybackSpeedViewModel()) binder.bind_to_constructor(SleepTimerViewModel, lambda: SleepTimerViewModel())
def load_last_book(filesystem_monitor: FilesystemMonitor, offline_cache: OfflineCache): """ Load the last played book into the player. """ global __current_track global __player global __wait_to_seek 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 filesystem_monitor.is_track_online(last_track): path = last_track.file else: path = offline_cache.get_cached_path(last_track) if not path: return __player.set_property("uri", "file://" + path) __wait_to_seek = True __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 __on_storage_changed(event, message): """ """ global __player if event == "storage-offline": if get_current_track() and message in get_current_track().file: cached_path = OfflineCache().get_cached_path(get_current_track()) if not cached_path: stop() unload() emit_event("stop")
def configure_inject(binder): binder.bind_to_provider(SqliteDatabase, get_db) binder.bind_to_constructor( Gio.Settings, lambda: Gio.Settings("com.github.geigi.cozy")) binder.bind_to_constructor(ApplicationSettings, lambda: ApplicationSettings()) binder.bind_to_constructor(Settings, lambda: Settings()) binder.bind_to_constructor("FilesystemMonitor", lambda: FilesystemMonitor()) binder.bind_to_constructor(OfflineCache, lambda: OfflineCache()) binder.bind_to_constructor(Player, lambda: Player()) binder.bind_to_constructor(Library, lambda: Library()) binder.bind_to_constructor(LibraryViewModel, lambda: LibraryViewModel()) binder.bind_to_constructor(SearchViewModel, lambda: SearchViewModel()) binder.bind_to_constructor(UISettings, lambda: UISettings()) binder.bind_to_constructor(StorageBlockList, lambda: StorageBlockList()) binder.bind_to_constructor(Files, lambda: Files()) binder.bind_to_constructor(BookDetailViewModel, lambda: BookDetailViewModel())
def update_database(ui, force=False): """ Scans the audio book directory for changes and new files. Also removes entries from the db that are no longer existent. """ paths = [] for location in Storage.select(): if os.path.exists(location.path): paths.append(location.path) # clean artwork cache artwork_cache.delete_artwork_cache() # are UI buttons currently blocked? player_blocked, importer_blocked = ui.get_ui_buttons_blocked() i = 0 percent_counter = 0 file_count = 0 for path in paths: file_count += sum([len(files) for r, d, files in os.walk(path)]) percent_threshold = file_count / 1000 failed = "" tracks_to_import = [] # Tracks which changed and need to be updated if they are cached tracks_cache_update = [] start = time.time() for path in paths: for directory, subdirectories, files in os.walk(path): for file in files: if file.lower().endswith(('.mp3', '.ogg', '.flac', '.m4a', '.m4b', '.wav', '.opus')): path = os.path.join(directory, file) imported = True try: if force: imported, ignore = import_file( file, directory, path, True) tracks_cache_update.append(path) # Is the track already in the database? elif Track.select().where( Track.file == path).count() < 1: imported, track_data = import_file( file, directory, path) if track_data: tracks_to_import.append(track_data) # Has the modified date changed? elif (Track.select().where( Track.file == path).first().modified < os.path.getmtime(path)): imported, ignore = import_file(file, directory, path, update=True) tracks_cache_update.append(path) if not imported: failed += path + "\n" except UnicodeEncodeError as e: log.warning( "Could not import file because of invalid path or filename: " + path) reporter.exception("importer", e) failed += path + "\n" except Exception as e: log.warning("Could not import file: " + path) log.warning(traceback.format_exc()) reporter.exception("importer", e) failed += path + "\n" i = i + 1 if len(tracks_to_import) > 100: write_tracks_to_db(tracks_to_import) tracks_to_import = [] # don't flood gui updates if percent_counter < percent_threshold: percent_counter = percent_counter + 1 else: percent_counter = 1 Gdk.threads_add_idle( GLib.PRIORITY_DEFAULT_IDLE, ui.titlebar.progress_bar.set_fraction, i / file_count) Gdk.threads_add_idle( GLib.PRIORITY_DEFAULT_IDLE, ui.titlebar.update_progress_bar.set_fraction, i / file_count) write_tracks_to_db(tracks_to_import) end = time.time() log.info("Total import time: " + str(end - start)) # remove entries from the db that are no longer existent remove_invalid_entries() artwork_cache.generate_artwork_cache() Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE, importer.emit_event, "import-finished") Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE, ui.switch_to_playing) Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE, ui.check_for_tracks) if len(failed) > 0: Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE, ui.display_failed_imports, failed) OfflineCache().update_cache(tracks_cache_update) OfflineCache()._process_queue()