Exemple #1
0
 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)
Exemple #2
0
    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)
Exemple #3
0
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)
Exemple #4
0
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)
Exemple #5
0
 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())
Exemple #6
0
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)
Exemple #7
0
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")
Exemple #8
0
 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())
Exemple #9
0
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()