Ejemplo n.º 1
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"]
Ejemplo n.º 2
0
Archivo: db.py Proyecto: leuc/cozy
def books():
    """
    Find all books in the database

    :return: all books
    """
    return Book.select()
Ejemplo n.º 3
0
def test_update_track_db_object_updates_object():
    from cozy.model.library import Library
    from cozy.media.media_file import MediaFile
    from cozy.db.book import Book
    from cozy.media.chapter import Chapter
    from cozy.db.track import Track

    library = Library()

    chapter = Chapter("New Chapter", 0)
    media_file = MediaFile(book_name="New Book Name",
                           author="New Author",
                           reader="New Reader",
                           disk=999,
                           track_number=999,
                           length=1234567,
                           cover=b"cover",
                           path="test.mp3",
                           modified=1234567,
                           chapters=[chapter])

    book = Book.select().get()

    library._update_track_db_object(media_file, book)

    track_in_db: Track = Track.select().where(Track.file == "test.mp3").get()

    assert track_in_db.name == "New Chapter"
    assert track_in_db.disk == 999
    assert track_in_db.number == 999
    assert track_in_db.length == 1234567
    assert track_in_db.modified == 1234567
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
def test_create_track_db_object_creates_object():
    from cozy.model.library import Library
    from cozy.media.media_file import MediaFile
    from cozy.db.book import Book
    from cozy.media.chapter import Chapter

    library = Library()

    chapter = Chapter("New Chapter", 0)
    media_file = MediaFile(book_name="New Book Name",
                           author="New Author",
                           reader="New Reader",
                           disk=999,
                           track_number=999,
                           length=1234567,
                           cover=b"cover",
                           path="New File",
                           modified=1234567,
                           chapters=[chapter])

    book = Book.select().get()

    res_dict = library._get_track_dictionary_for_db(media_file, book)

    assert res_dict["name"] == "New Chapter"
    assert res_dict["disk"] == 999
    assert res_dict["number"] == 999
    assert res_dict["book"] == book
    assert res_dict["file"] == "New File"
    assert res_dict["length"] == 1234567
    assert res_dict["modified"] == 1234567
    assert res_dict["position"] == 0
Ejemplo n.º 6
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
Ejemplo n.º 7
0
def test_create_book_db_object_creates_object():
    from cozy.model.database_importer import DatabaseImporter
    from cozy.media.media_file import MediaFile
    from cozy.db.book import Book
    from cozy.media.chapter import Chapter

    database_importer = DatabaseImporter()

    chapter = Chapter("New Chapter", 0, 1234567, 999)
    media_file = MediaFile(book_name="New Book",
                           author="New Author",
                           reader="New Reader",
                           disk=999,
                           cover=b"cover",
                           path="test.mp3",
                           modified=1234567,
                           chapters=[chapter])

    database_importer._create_book_db_object(media_file)

    book_in_db: Book = Book.select().where(Book.name == "New Book").get()

    assert book_in_db.name == "New Book"
    assert book_in_db.author == "New Author"
    assert book_in_db.reader == "New Reader"
    assert book_in_db.cover == b"cover"
    assert book_in_db.position == 0
    assert book_in_db.rating == -1
Ejemplo n.º 8
0
def test_create_track_db_object_creates_object():
    from cozy.model.database_importer import DatabaseImporter
    from cozy.media.media_file import MediaFile
    from cozy.db.book import Book
    from cozy.media.chapter import Chapter

    database_importer = DatabaseImporter()

    chapter = Chapter("New Chapter", 0, 1234567, 999)
    media_file = MediaFile(book_name="New Book Name",
                           author="New Author",
                           reader="New Reader",
                           disk=999,
                           cover=b"cover",
                           path="New File",
                           modified=1234567,
                           chapters=[chapter])

    book = Book.select().get()

    res_dict = database_importer._get_track_list_for_db(media_file, book)[0]

    assert res_dict["name"] == "New Chapter"
    assert res_dict["disk"] == 999
    assert res_dict["number"] == 999
    assert res_dict["book"] == book
    assert res_dict["length"] == 1234567
    assert res_dict["position"] == 0
Ejemplo n.º 9
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
Ejemplo n.º 10
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
Ejemplo n.º 11
0
def test_create_book_db_object_creates_object():
    from cozy.model.library import Library
    from cozy.media.media_file import MediaFile
    from cozy.db.book import Book
    from cozy.media.chapter import Chapter

    library = Library()

    chapter = Chapter("New Chapter", 0)
    media_file = MediaFile(book_name="New Book",
                           author="New Author",
                           reader="New Reader",
                           disk=999,
                           track_number=999,
                           length=1234567,
                           cover=b"cover",
                           path="test.mp3",
                           modified=1234567,
                           chapters=[chapter])

    library._create_book_db_object(media_file)

    book_in_db: Book = Book.select().where(Book.name == "New Book").get()

    assert book_in_db.name == "New Book"
    assert book_in_db.author == "New Author"
    assert book_in_db.reader == "New Reader"
    assert book_in_db.cover == b"cover"
    assert book_in_db.position == 0
    assert book_in_db.rating == -1
Ejemplo n.º 12
0
 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
Ejemplo n.º 13
0
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)
Ejemplo n.º 14
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()
Ejemplo n.º 15
0
Archivo: db.py Proyecto: 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()
Ejemplo n.º 16
0
    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)
Ejemplo n.º 17
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
Ejemplo n.º 18
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)
Ejemplo n.º 19
0
def test_authors_contains_every_author_from_db(peewee_database):
    from cozy.model.library import Library
    from cozy.db.book import Book

    library = Library(peewee_database)
    books = Book.select(Book.author).distinct().order_by(Book.author)
    authors_from_db = [book.author for book in books]

    # we cannot assert the same content as the library filters books without chapters
    assert len(library.authors) > 0
    assert library.authors.issubset(authors_from_db)
Ejemplo n.º 20
0
    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()
Ejemplo n.º 21
0
def test_readers_contains_every_reader_from_db():
    from cozy.model.library import Library
    from cozy.db.book import Book

    library = Library()
    books = Book.select(Book.reader).distinct().order_by(Book.reader)
    readers_from_db = [book.reader for book in books]
    readers_from_db = list(split_strings_to_set(set(readers_from_db)))

    # we cannot assert the same content as the library filters books without chapters
    assert len(library.readers) > 0
    assert library.readers.issubset(readers_from_db)
Ejemplo n.º 22
0
Archivo: db.py Proyecto: leuc/cozy
def get_track_for_playback(book):
    """
    Finds the current track to playback for a given book.
    :param book: book which the next track is required from
    :return: current track position from book db
    """
    book = Book.select().where(Book.id == book.id).get()
    query = Track.select().where(Track.id == book.position)
    if book.position < 1:
        track_items = get_tracks(book)
        if len(track_items) > 0:
            track = get_tracks(book)[0]
        else:
            track = None
    elif query.exists():
        track = query.get()
    else:
        track = None
    return track
Ejemplo n.º 23
0
def import_file(file, directory, path, update=False):
    """
    Imports all information about a track into the database.
    Note: This creates also a new album object when it doesnt exist yet.
    Note: This does not check whether the file is already imported.
    :return: True if file was imported, otherwise False
    :return: Track object to be imported when everything passed successfully and track is not in the db already.
    """
    if is_blacklisted(path):
        return True, None

    media_type, media_type_human = tools.__get_media_type(path)
    track = TrackContainer(None, path)
    cover = None
    reader = None
    track_number = None
    track_data = None

    # getting the some data is file specific
    ### MP3 ###
    if "audio/mpeg" in media_type:
        track_data = _get_mp3_tags(track, path)

    ### FLAC ###
    elif "audio/flac" in media_type or "audio/x-flac" in media_type:
        track_data = _get_flac_tags(track, path)

    ### OGG ###
    elif "audio/ogg" in media_type or "audio/x-ogg" in media_type:
        track_data = _get_ogg_tags(track, path)

    ### OPUS ###
    elif "audio/opus" in media_type or "audio/x-opus" in media_type or "codecs=opus" in media_type:
        track_data = _get_opus_tags(track, path)

    ### MP4 ###
    elif "audio/mp4" in media_type or "audio/x-m4a" in media_type:
        track_data = _get_mp4_tags(track, path)

    ### WAV ###
    elif "audio/wav" in media_type or "audio/x-wav" in media_type:
        track_data = TrackData(path)
        track_data.length = __get_wav_track_length(path)

    elif "ID3" in media_type_human:
        track_data = _get_mp3_tags(track, path)

    ### File will not be imported ###
    else:
        # don't use _ for ignored return value -> it is reserved for gettext
        ignore, file_extension = os.path.splitext(path)
        log.warning("Skipping file " + path + " because of mime type " +
                    media_type + ".")
        reporter.error(
            "importer", "Mime type not detected as audio: " + media_type +
            " with file ending: " + file_extension)
        return False, None

    track_data.modified = __get_last_modified(path)

    # try to get all the remaining tags
    try:
        if track_data.track_number is None:
            # The track number can contain the total number of tracks
            track_text = str(__get_common_tag(track, "tracknumber"))
            track_data.track_number = int(track_text.split("/")[0])
    except Exception as e:
        log.debug(e)
        track_data.track_number = 0

    if track_data.book_name is None:
        track_data.book_name = __guess_book_name(directory)
    if track_data.author is None or track_data.author == "":
        if track_data.reader and len(track_data.reader) > 0:
            track_data.author = track_data.reader
            track_data.reader = ""
        else:
            track_data.author = _("Unknown Author")
    if track_data.reader is None or track_data.reader == "":
        track_data.reader = _("Unknown Reader")
    if track_data.name is None:
        track_data.name = __guess_title(file)
    if not track_data.disk:
        track_data.disk = 1
    if not track_data.length:
        # Try to get the length by using gstreamer
        success, track_data.length = get_gstreamer_length(path)
        if not success:
            return False, None

    if update:
        if Book.select().where(Book.name == track_data.book_name).count() < 1:
            track_data.book = Book.create(name=track_data.book_name,
                                          author=track_data.author,
                                          reader=track_data.reader,
                                          position=0,
                                          rating=-1,
                                          cover=track_data.cover)
        else:
            track_data.book = Book.select().where(
                Book.name == track_data.book_name).get()
            Book.update(name=track_data.book_name,
                        author=track_data.author,
                        reader=track_data.reader,
                        cover=track_data.cover).where(
                            Book.id == track_data.book.id).execute()

        Track.update(name=track_data.name,
                     number=track_data.track_number,
                     book=track_data.book,
                     disk=track_data.disk,
                     length=track_data.length,
                     modified=track_data.modified).where(
                         Track.file == track_data.file).execute()
    else:
        # create database entries
        if Book.select().where(Book.name == track_data.book_name).count() < 1:
            track_data.book = Book.create(name=track_data.book_name,
                                          author=track_data.author,
                                          reader=track_data.reader,
                                          position=0,
                                          rating=-1,
                                          cover=track_data.cover)
        else:
            track_data.book = Book.select().where(
                Book.name == track_data.book_name).get()

        return True, track_data

    return True, None
Ejemplo n.º 24
0
def generate_artwork_cache():
    """
    Generates the default artwork cache for cover preview.
    """
    for book in Book.select():
        get_cover_pixbuf(book, 180)
Ejemplo n.º 25
0
Archivo: db.py Proyecto: leuc/cozy
def authors():
    return Book.select(Book.author).distinct().order_by(Book.author)
Ejemplo n.º 26
0
Archivo: db.py Proyecto: leuc/cozy
def readers():
    return Book.select(Book.reader).distinct().order_by(Book.reader)