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)
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"]
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
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
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
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
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)
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)
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)
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
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
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
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
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"
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
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 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"
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 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
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()
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()
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
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 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
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
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
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()
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)
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 _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