Beispiel #1
0
def load_last_book(filesystem_monitor: FilesystemMonitor):
    """
    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 filesystem_monitor.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)
Beispiel #2
0
def test_insert_track_inserts_all_rows_expected():
    from cozy.model.database_importer import DatabaseImporter, TrackInsertRequest
    from cozy.db.book import Book
    from cozy.db.file import File
    from cozy.db.track_to_file import TrackToFile

    database_importer = DatabaseImporter()

    file = File.create(path="New File", modified=1234567)
    track_data = {
        "name": "Test",
        "number": 2,
        "disk": 2,
        "book": Book.select().where(Book.name == "Test Book").get(),
        "length": 123,
        "position": 0
    }

    track = TrackInsertRequest(track_data, file, 1234)

    database_importer._insert_tracks([track])
    track_to_file_query = TrackToFile.select().join(File).where(
        TrackToFile.file == file.id)
    assert track_to_file_query.count() == 1

    track_to_file: TrackToFile = track_to_file_query.get()

    assert track_to_file.track.name == track_data["name"]
    assert track_to_file.track.number == track_data["number"]
    assert track_to_file.track.disk == track_data["disk"]
    assert track_to_file.track.book.id == Book.select().where(
        Book.name == "Test Book").get().id
    assert track_to_file.track.length == track_data["length"]
    assert track_to_file.track.position == track_data["position"]
Beispiel #3
0
def test_current_track_is_actually_current_track(peewee_database):
    from cozy.model.book import Book
    from cozy.db.book import Book as BookModel

    book = Book(peewee_database, 9)

    assert book.current_chapter.id == BookModel.get_by_id(9).position
Beispiel #4
0
def test_removing_book_with_missing_file_removes_all_traces_in_db(
        peewee_database):
    from cozy.model.book import Book
    from cozy.db.book import Book as BookDB
    from cozy.db.track import Track
    from cozy.db.file import File
    from cozy.db.track_to_file import TrackToFile

    book = Book(peewee_database, 1)
    track_ids = [chapter.id for chapter in book.chapters]
    track_to_file_ids = [
        track_to_file.id for track_to_file in TrackToFile.select().join(
            Track).where(TrackToFile.track.id << track_ids)
    ]
    file_ids = [
        track_to_file.file.id for track_to_file in TrackToFile.select().join(
            Track).where(TrackToFile.track.id << track_ids)
    ]

    assert len(track_ids) > 0
    assert len(track_to_file_ids) > 0
    assert len(file_ids) > 0

    File.get_by_id(file_ids[0]).delete_instance()

    book.remove()

    assert BookDB.select().where(BookDB.id == 1).count() == 0
    assert Track.select().where(Track.id << track_ids).count() == 0
    assert TrackToFile.select().where(
        TrackToFile.id << track_to_file_ids).count() == 0
    assert File.select().where(File.id << file_ids).count() == 0
Beispiel #5
0
def test_progress_should_be_100_for_finished_book(peewee_database):
    from cozy.model.book import Book

    book = Book(peewee_database, 1)
    book.position = -1

    assert book.progress == book.duration
Beispiel #6
0
def test_progress_should_be_zero_for_unstarted_book(peewee_database):
    from cozy.model.book import Book

    book = Book(peewee_database, 1)
    book.position = 0

    assert book.progress == 0
Beispiel #7
0
def load_file(track, filesystem_monitor: FilesystemMonitor):
    """
    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 filesystem_monitor.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)
Beispiel #8
0
def peewee_database():
    from cozy.db.track import Track
    from cozy.db.book import Book
    from cozy.db.settings import Settings
    from cozy.db.storage_blacklist import StorageBlackList
    from cozy.db.storage import Storage

    db_path, models, test_db = prepare_db()

    path_of_test_folder = os.path.dirname(os.path.realpath(__file__)) + '/'

    with open(path_of_test_folder + 'books.json') as json_file:
        book_data = json.load(json_file)

    with open(path_of_test_folder + 'tracks.json') as json_file:
        track_data = json.load(json_file)

    Book.insert_many(book_data).execute()
    for chunk in chunks(track_data, 25):
        Track.insert_many(chunk).execute()

    with open(path_of_test_folder + 'storages.json') as json_file:
        storage_data = json.load(json_file)

    Storage.insert_many(storage_data).execute()

    Settings.create(path="", last_played_book=Book.get())
    StorageBlackList.create(path="/path/to/replace/test1.mp3")
    StorageBlackList.create(path="/path/to/not/replace/test2.mp3")

    print("Provide database...")
    yield test_db

    teardown_db(db_path, models, test_db)
Beispiel #9
0
    def _process_queue(self):
        log.info("Startet processing queue")
        self.filecopy_cancel = Gio.Cancellable()

        self._fill_queue_from_db()
        self.total_batch_count = len(self.queue)
        self.current_batch_count = 0
        if len(self.queue) > 0:
            self.current_book_processing = self.queue[0].track.book.id

        while len(self.queue) > 0:
            log.info("Processing item")
            self.current_batch_count += 1
            item = self.queue[0]
            if self.thread.stopped():
                break

            new_item = OfflineCacheModel.get(OfflineCacheModel.id == item.id)

            if self.current_book_processing != new_item.track.book.id:
                self.update_book_download_status(
                    Book.get(Book.id == self.current_book_processing))
                self.current_book_processing = new_item.track.book.id

            if not new_item.copied and os.path.exists(new_item.track.file):
                log.info("Copying item")
                Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE, self.ui.switch_to_working,
                                     _("Copying") + " " + tools.shorten_string(new_item.track.book.name, 30), False,
                                     False)
                self.current = new_item

                destination = Gio.File.new_for_path(os.path.join(self.cache_dir, new_item.file))
                source = Gio.File.new_for_path(new_item.track.file)
                flags = Gio.FileCopyFlags.OVERWRITE
                try:
                    copied = source.copy(destination, flags, self.filecopy_cancel, self.__update_copy_status, None)
                except Exception as e:
                    if e.code == Gio.IOErrorEnum.CANCELLED:
                        log.info("Download of book was cancelled.")
                        self.thread.stop()
                        break
                    reporter.exception("offline_cache", e)
                    log.error("Could not copy file to offline cache: " + new_item.track.file)
                    log.error(e)
                    self.queue.remove(item)
                    continue

                if copied:
                    OfflineCacheModel.update(copied=True).where(
                        OfflineCacheModel.id == new_item.id).execute()

            self.queue.remove(item)

        if self.current_book_processing:
            self.update_book_download_status(
                Book.get(Book.id == self.current_book_processing))

        self.current = None
        Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE, self.ui.switch_to_playing)
Beispiel #10
0
def test_setting_last_played_updates_in_book_object_and_database(peewee_database):
    from cozy.db.book import Book as BookModel
    from cozy.model.book import Book

    book = Book(peewee_database, 1)
    book.last_played = 42
    assert book.last_played == 42
    assert BookModel.get_by_id(1).last_played == 42
Beispiel #11
0
def test_setting_offline_updates_in_book_object_and_database(peewee_database):
    from cozy.db.book import Book as BookModel
    from cozy.model.book import Book

    book = Book(peewee_database, 1)
    book.offline = True
    assert book.offline is True
    assert BookModel.get_by_id(1).offline is True
Beispiel #12
0
def test_setting_downloaded_updates_in_book_object_and_database(peewee_database):
    from cozy.db.book import Book as BookModel
    from cozy.model.book import Book

    book = Book(peewee_database, 1)
    book.downloaded = True
    assert book.downloaded is True
    assert BookModel.get_by_id(1).downloaded is True
Beispiel #13
0
def test_setting_rating_updates_in_book_object_and_database(peewee_database):
    from cozy.db.book import Book as BookModel
    from cozy.model.book import Book

    book = Book(peewee_database, 1)
    book.rating = 5
    assert book.rating == 5
    assert BookModel.get_by_id(1).rating == 5
Beispiel #14
0
def test_setting_reader_updates_in_book_object_and_database(peewee_database):
    from cozy.db.book import Book as BookModel
    from cozy.model.book import Book

    book = Book(peewee_database, 1)
    book.reader = "Altered"
    assert book.reader == "Altered"
    assert BookModel.get_by_id(1).reader == "Altered"
Beispiel #15
0
def test_setting_position_updates_in_book_object_and_database(peewee_database):
    from cozy.db.book import Book as BookModel
    from cozy.model.book import Book

    book = Book(peewee_database, 1)
    book.position = 42
    assert book.position == 42
    assert BookModel.get_by_id(1).position == 42
Beispiel #16
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)
Beispiel #17
0
def test_setting_cover_updates_in_book_object_and_database(peewee_database):
    from cozy.db.book import Book as BookModel
    from cozy.model.book import Book

    book = Book(peewee_database, 1)
    book.cover = b"42"
    assert book.cover == b"42"
    assert BookModel.get_by_id(1).cover == b"42"
Beispiel #18
0
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()
Beispiel #19
0
def test_progress_return_progress_for_started_book(peewee_database):
    from cozy.model.book import Book

    book = Book(peewee_database, 1)
    chapter = book.chapters[0]
    chapter.position = 42 * 1000000000
    book.position = chapter.id

    assert book.progress == 42
Beispiel #20
0
 def _update_book_db_object(self, media_file: MediaFile) -> BookModel:
     BookModel.update(name=media_file.book_name,
                      author=media_file.author,
                      reader=media_file.reader,
                      cover=media_file.cover) \
         .where(BookModel.name == media_file.book_name) \
         .execute()
     return BookModel.select().where(
         BookModel.name == media_file.book_name).get()
Beispiel #21
0
Datei: db.py Projekt: geigi/cozy
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 and Settings.get().last_played_book.id == book.id:
                Settings.update(last_played_book=None).execute()
            book.delete_instance()
Beispiel #22
0
def test_delete_deletes_book_from_db(peewee_database, mocker):
    from cozy.model.book import Book
    from cozy.db.book import Book as BookModel

    book = Book(peewee_database, 1)
    spy = mocker.spy(book, "emit_event")
    book._on_chapter_event("chapter-deleted", book.chapters[0])

    assert BookModel.select().where(BookModel.id == 1).count() < 1
    spy.assert_called_once_with("book-deleted", book)
    assert len(book._listeners) < 1
Beispiel #23
0
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()
Beispiel #24
0
def test_update_book_position_sets_position_for_multi_chapter_file_correctly():
    from cozy.model.database_importer import DatabaseImporter
    from cozy.db.book import Book
    from cozy.db.track import Track

    database_importer = DatabaseImporter()

    book = Book.get_by_id(11)
    database_importer._update_book_position(book, 4251)

    book = Book.get_by_id(11)
    assert book.position == 232
    assert Track.get_by_id(232).position == 4251000000000
Beispiel #25
0
def test_deleted_book_removed_from_last_played_book_if_necessary(
        peewee_database):
    from cozy.model.book import Book
    from cozy.model.settings import Settings

    settings = Settings()
    inject.clear_and_configure(lambda binder: binder.bind(
        SqliteDatabase, peewee_database) and binder.bind(Settings, settings))
    book = Book(peewee_database, 1)

    settings.last_played_book = book.db_object
    book._on_chapter_event("chapter-deleted", book.chapters[0])

    assert settings.last_played_book == None
Beispiel #26
0
def test_update_book_position_resets_position_if_it_is_longer_than_the_duration(
):
    from cozy.model.database_importer import DatabaseImporter
    from cozy.db.book import Book

    database_importer = DatabaseImporter()

    book = Book.get_by_id(11)
    book.position = 1
    book.save(only=book.dirty_fields)
    database_importer._update_book_position(book, 42510)

    book = Book.get_by_id(11)
    assert book.position == 0
Beispiel #27
0
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 not track:
        log.error("Could not save book position because the given track is NULL")
        reporter.error("control/player", "Could not save book position because the given track is NULL")
        return

    if pos is None:
        pos = track.id
    Book.update(position=pos).where(
        Book.id == track.book.id).execute()
Beispiel #28
0
 def _create_book_db_object(self, media_file: MediaFile) -> BookModel:
     return BookModel.create(name=media_file.book_name,
                             author=media_file.author,
                             reader=media_file.reader,
                             cover=media_file.cover,
                             position=0,
                             rating=-1)
Beispiel #29
0
 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
Beispiel #30
0
 def _import_or_update_book(self, media_file):
     if BookModel.select(BookModel.name).where(
             BookModel.name == media_file.book_name).count() < 1:
         book = self._create_book_db_object(media_file)
     else:
         book = self._update_book_db_object(media_file)
     return book