Exemple #1
0
    def on_method_call(self,
                       connection,
                       sender,
                       object_path,
                       interface_name,
                       method_name,
                       parameters,
                       invocation):

        args = list(parameters.unpack())
        for i, sig in enumerate(self.method_inargs[method_name]):
            if sig == "h":
                msg = invocation.get_message()
                fd_list = msg.get_unix_fd_list()
                args[i] = fd_list.get(args[i])

        try:
            result = getattr(self, method_name)(*args)

            # out_args is atleast (signature1).
            # We therefore always wrap the result as a tuple.
            # Refer to https://bugzilla.gnome.org/show_bug.cgi?id=765603
            result = (result,)

            out_args = self.method_outargs[method_name]
            if out_args and out_args != "()" and result:
                variant = GLib.Variant(out_args, result)
                invocation.return_value(variant)
            else:
                invocation.return_value(None)
        except Exception as e:
            log.error(e)
            reporter.exception("mpris", e)
            reporter.error("mrpis", "MPRIS method call failed with method name: {}".format(method_name))
            invocation.return_value(None)
Exemple #2
0
def __load_pixbuf_from_cache(book, size):
    """
    """
    pixbuf = None

    query = ArtworkCache.select().where(ArtworkCache.book == book.id)
    if query.exists():
        try:
            uuid = query.first().uuid
        except Exception as e:
            reporter.error(
                "artwork_cache",
                "load_pixbuf_from_cache: query exists but query.first().uuid crashed."
            )
            return None
    else:
        return None

    cache_dir = os.path.join(get_cache_dir(), "artwork")
    cache_dir = os.path.join(cache_dir, uuid)

    try:
        if os.path.exists(cache_dir):
            file_path = os.path.join(cache_dir, str(size) + ".jpg")
            if os.path.exists(file_path):
                pixbuf = GdkPixbuf.Pixbuf.new_from_file(
                    os.path.join(cache_dir,
                                 str(size) + ".jpg"))
            else:
                return None
    except Exception as e:
        log.warning(e)
        return None

    return pixbuf
Exemple #3
0
    def get_album_art_path(self, book, size):
        query = ArtworkCacheModel.select().where(
            ArtworkCacheModel.book == book.id)
        if query.exists():
            try:
                uuid = query.first().uuid
            except Exception as e:
                reporter.error(
                    "artwork_cache",
                    "load_pixbuf_from_cache: query exists but query.first().uuid crashed."
                )
                return None
        else:
            return None

        cache_dir = os.path.join(get_cache_dir(), "artwork")
        cache_dir = os.path.join(cache_dir, uuid)

        try:
            if os.path.exists(cache_dir):
                file_path = os.path.join(cache_dir, str(size) + ".jpg")
                if os.path.exists(file_path):
                    return file_path
                else:
                    return None
        except Exception as e:
            log.warning(e)
            return None

        return None
Exemple #4
0
    def play_pause_book(self, book: Book):
        if not book:
            log.error("Cannot play book which is None.")
            reporter.error("player", "Cannot play book which is None.")
            return

        self._play_chapter(book, book.current_chapter)
Exemple #5
0
    def _forward_in_book(self):
        if not self._book:
            log.error(
                "Forward in book not possible because no book is loaded.")
            reporter.error(
                "player",
                "Forward in book not possible because no book is loaded.")
            return

        current_position = self._gst_player.position
        current_position_relative = max(
            current_position - self.loaded_chapter.start_position, 0)
        old_chapter = self._book.current_chapter
        chapter_number = self._book.chapters.index(self._book.current_chapter)
        forward_seconds = self._app_settings.forward_duration * self.playback_speed

        if current_position_relative / NS_TO_SEC + forward_seconds < self._book.current_chapter.length:
            self._gst_player.position = current_position + (NS_TO_SEC *
                                                            forward_seconds)
        elif chapter_number < len(self._book.chapters) - 1:
            next_chapter = self._book.chapters[chapter_number + 1]
            self._load_chapter(next_chapter)
            self._gst_player.position = next_chapter.start_position + (
                NS_TO_SEC * forward_seconds -
                (old_chapter.length * NS_TO_SEC - current_position_relative))
        else:
            self._next_chapter()
Exemple #6
0
    def _load_chapter(self, chapter: Chapter):
        file_changed = False

        if not self._book:
            log.error("There is no book loaded but there should be.")
            reporter.error("player",
                           "There is no book loaded but there should be.")
            return

        self._library.last_played_book = self._book
        media_file_path = self._get_playback_path(chapter)

        if self._gst_player.loaded_file_path == media_file_path:
            log.info(
                "Not loading a new file because the new chapter is within the old file."
            )
        else:
            log.info("Loading new file for chapter.")
            try:
                self._gst_player.load_file(media_file_path)
                file_changed = True
            except FileNotFoundError:
                self._handle_file_not_found()
                return

        if file_changed or self._should_jump_to_chapter_position(
                chapter.position):
            self._gst_player.position = chapter.position
            self._gst_player.playback_speed = self._book.playback_speed

        if file_changed or self._book.position != chapter.id:
            self._book.position = chapter.id
            self.emit_event_main_thread("chapter-changed", self._book)
Exemple #7
0
    def is_external(self, directory: str) -> bool:
        mounts: List[Gio.Mount] = self.volume_monitor.get_mounts()

        for mount in mounts:
            root = mount.get_root()
            if not root:
                log.error(
                    "Failed to test for external drive. Mountpoint has no root object."
                )
                reporter.error(
                    "fs_monitor",
                    "Failed to test for external drive. Mountpoint has no root object."
                )
                return False

            path = root.get_path()
            if not path:
                log.error(
                    "Failed to test for external drive. Root object has no path."
                )
                reporter.error(
                    "fs_monitor",
                    "Failed to test for external drive. Root object has no path."
                )
                return False

            if path in directory and mount.can_unmount():
                return True

        return False
Exemple #8
0
    def play_pause_chapter(self, book: Book, chapter: Chapter):
        if not book or not chapter:
            log.error("Cannot play chapter which is None.")
            reporter.error("player", "Cannot play chapter which is None.")
            return

        self._play_chapter(book, chapter)
        book.position = chapter.id
Exemple #9
0
 def play_pause(self):
     if self._gst_player.state == GstPlayerState.PAUSED:
         self._gst_player.play()
     elif self._gst_player.state == GstPlayerState.PLAYING:
         self._gst_player.pause()
     else:
         log.error("Trying to play/pause although player is in STOP state.")
         reporter.error(
             "player",
             "Trying to play/pause although player is in STOP state.")
Exemple #10
0
    def play_pause_book(self, book: Book):
        if not book:
            log.error("Cannot play book which is None.")
            reporter.error("player", "Cannot play book which is None.")
            return

        if self._book == book:
            self.play_pause()
        else:
            self._continue_book(book)
            self._gst_player.play()
Exemple #11
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()
Exemple #12
0
    def _on_play_changed(self):
        playing = self._view_model.playing

        play_button_img = "media-playback-pause-symbolic" if playing else "media-playback-start-symbolic"
        self.play_img.set_from_icon_name(play_button_img,
                                         Gtk.IconSize.LARGE_TOOLBAR)

        if self._current_selected_chapter:
            self._current_selected_chapter.set_playing(playing)
        else:
            log.error("_current_selected_chapter is null. Skipping...")
            reporter.error(
                "book_detail_view",
                "_current_selected_chapter was NULL. No ply/pause chapter icon was changed"
            )
Exemple #13
0
    def play_pause_chapter(self, book: Book, chapter: Chapter):
        if not book or not chapter:
            log.error("Cannot play chapter which is None.")
            reporter.error("player", "Cannot play chapter which is None.")
            return

        if self._book and self._book.current_chapter == chapter:
            self.play_pause()
            return

        if self._book != book:
            self._load_book(book)

        self._load_chapter(chapter)
        self._gst_player.play()

        book.position = chapter.id
Exemple #14
0
    def remove_bind(self, prop: str, callback: Callable):
        if not prop:
            log.error("Cannot remove bind for empty prop.")
            reporter.error("observable", "Cannot remove bind for empty prop.")
            return

        if not callback:
            log.error("Cannot remove bind for empty callback.")
            reporter.error("observable", "Cannot remove bind for empty callback.")
            return

        if prop in self._observers:
            if callback in self._observers[prop]:
                self._observers[prop].remove(callback)
            else:
                log.info("Callback not found in prop's {} observers. Skipping remove bind...".format(prop))
        else:
            log.info("Prop not found in observers. Skipping remove bind...")
Exemple #15
0
def __on_gst_message(bus, message: Gst.Message):
    """
    Handle messages from gst.
    """
    global __speed
    global __set_speed

    t = message.type
    if t == Gst.MessageType.BUFFERING:
        if (message.percentage < 100):
            __player.set_state(Gst.State.PAUSED)
            log.info("Buffering…")
        else:
            __player.set_state(Gst.State.PLAYING)
            log.info("Buffering finished.")
    elif t == Gst.MessageType.EOS:
        next_track()
    elif t == Gst.MessageType.ERROR:
        error, debug_msg = message.parse_error()

        if error.code == Gst.ResourceError.NOT_FOUND:
            track = get_current_track()
            stop()
            unload()
            emit_event("stop")

            log.warning("gst: Resource not found. Stopping player.")
            reporter.warning("player",
                             "gst: Resource not found. Stopping player.")
            emit_event("resource-not-found", track)
            return

        reporter.error("player", error)
        log.error(error)
        log.debug(debug_msg)
        emit_event("error", error)
    elif t == Gst.MessageType.STATE_CHANGED:
        state = get_gst_player_state()
        if state == Gst.State.PLAYING or state == Gst.State.PAUSED:
            auto_jump()
Exemple #16
0
    def _next_chapter(self):
        if not self._book:
            log.error(
                "Cannot play next chapter because no book reference is stored."
            )
            reporter.error(
                "player",
                "Cannot play next chapter because no book reference is stored."
            )

        index_current_chapter = self._book.chapters.index(
            self._book.current_chapter)

        self._book.current_chapter.position = self._book.current_chapter.start_position
        if len(self._book.chapters) <= index_current_chapter + 1:
            log.info("Book finished, stopping playback.")
            self._finish_book()
            self._gst_player.stop()
        else:
            chapter = self._book.chapters[index_current_chapter + 1]
            chapter.position = chapter.start_position
            self.play_pause_chapter(self._book, chapter)
Exemple #17
0
    def _rewind_in_book(self):
        if not self._book:
            log.error("Rewind in book not possible because no book is loaded.")
            reporter.error(
                "player",
                "Rewind in book not possible because no book is loaded.")
            return

        current_position = self._gst_player.position
        current_position_relative = max(
            current_position - self.loaded_chapter.start_position, 0)
        chapter_number = self._book.chapters.index(self._book.current_chapter)
        rewind_seconds = self._app_settings.rewind_duration * self.playback_speed

        if current_position_relative / NS_TO_SEC - rewind_seconds > 0:
            self._gst_player.position = current_position - NS_TO_SEC * rewind_seconds
        elif chapter_number > 0:
            previous_chapter = self._book.chapters[chapter_number - 1]
            self._load_chapter(previous_chapter)
            self._gst_player.position = previous_chapter.end_position + (
                current_position_relative - NS_TO_SEC * rewind_seconds)
        else:
            self._gst_player.position = 0
Exemple #18
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