def __on_storage_changed(self, event, message): """ """ if (event == "storage-online" and not super().get_sensitive() ) or event == "external-storage-removed": if message in get_tracks(self.book).first().file: super().set_sensitive(True) self.box.set_tooltip_text(self.ONLINE_TOOLTIP_TEXT) elif (event == "storage-offline" and super().get_sensitive()): self.refresh_book_object() if message in get_tracks( self.book).first().file and not self.book.offline: super().set_sensitive(False) self.box.set_tooltip_text(self.OFFLINE_TOOLTIP_TEXT) elif event == "external-storage-added": self.refresh_book_object() if FilesystemMonitor().is_book_online(self.book): super().set_sensitive(True) else: super().set_sensitive(False) self.box.set_tooltip_text(self.OFFLINE_TOOLTIP_TEXT) if event == "external-storage-removed": first_track = get_tracks(self.book).first() if first_track and message in first_track.file: self.box.set_tooltip_text(self.ONLINE_TOOLTIP_TEXT)
def remove(self, book): """ Remove all tracks of the given book from the cache. """ #self._stop_processing() tracks = get_tracks(book) ids = [t.id for t in tracks] offline_elements = OfflineCacheModel.select().where( OfflineCacheModel.track << ids) for element in offline_elements: file_path = os.path.join(self.cache_dir, element.file) if file_path == self.cache_dir: continue file = Gio.File.new_for_path(file_path) if file.query_exists(): file.delete() for item in self.queue: if self.current and item.id == self.current.id: self.filecopy_cancel.cancel() OfflineCacheModel.delete().where( OfflineCacheModel.track in ids).execute() if len(self.queue) > 0: self._start_processing()
def is_book_online(self, book): """ """ result = next( (storage.online for storage in self.external_storage if storage.storage.path in get_tracks(book).first().file), True) return (result)
def __jump_to_folder(self, widget, parameter): """ Opens the folder containing this books files in the default file explorer. """ track = get_tracks(self.book).first() path = os.path.dirname(track.file) subprocess.Popen(['xdg-open', path])
def prev_track(): """ Play the previous track of the current book. Plays the same track again when it is the first of the book. """ global __player global __current_track album_tracks = get_tracks(get_current_track().book) current = get_current_track() index = list(album_tracks).index(current) previous = None if index > -1: previous = album_tracks[index - 1] save_current_track_position() if previous: play_pause(previous) save_current_track_position(track=current, pos=0) save_current_book_position(previous) else: first_track = __current_track __player.set_state(Gst.State.NULL) __current_track = None play_pause(first_track) save_current_book_position(current, 0)
def next_track(): """ Play the next track of the current book. Stops playback if there isn't any. """ global __current_track global __play_next album_tracks = get_tracks(get_current_track().book) current = get_current_track() index = list(album_tracks).index(current) next_track = None if index + 1 < len(album_tracks): next_track = album_tracks[index + 1] play_pause(None) save_current_track_position(0) if next_track: save_current_book_position(next_track) save_current_track_position(0, next_track) if __play_next: play_pause(next_track) else: load_file(next_track) __play_next = True else: stop() save_current_book_position(current, -1) unload() Settings.update(last_played_book=None).execute() emit_event("stop")
def __settings_changed(self, event, message): """ React to changes in user settings. """ if not self.book: return if event == "storage-removed" or event == "external-storage-removed": if message in get_tracks(self.book).first().file: self.download_box.set_visible(False) self.download_switch.set_visible(False) elif "external-storage-added" or event == "storage-changed" or event == "storage-added": self.update_offline_status()
def add(self, book): """ Add all tracks of a book to the offline cache and start copying. """ tracks = [] for track in get_tracks(book): file = str(uuid.uuid4()) tracks.append((track, file)) chunks = [tracks[x:x + 500] for x in range(0, len(tracks), 500)] for chunk in chunks: query = OfflineCacheModel.insert_many(chunk, fields=[OfflineCacheModel.track, OfflineCacheModel.file]) self.total_batch_count += len(chunk) query.execute() self._start_processing()
def __load_pixbuf_from_file(book): """ Try to load the artwork from a book from image files. :param book: The book to load the artwork from. :return: Artwork as pixbuf object. """ pixbuf = None directory = os.path.dirname(os.path.normpath(get_tracks(book)[0].file)) cover_files = [] try: cover_files = [ f for f in os.listdir(directory) if f.lower().endswith('.png') or f.lower().endswith(".jpg") or f.lower().endswith(".gif") ] except Exception as e: log.warning( "Could not open audiobook directory and look for cover files.") log.warning(e) for elem in (x for x in cover_files if os.path.splitext(x.lower())[0] == "cover"): # find cover.[jpg,png,gif] try: pixbuf = GdkPixbuf.Pixbuf.new_from_file( os.path.join(directory, elem)) except Exception as e: log.debug(e) if pixbuf: break if pixbuf is None: # find other cover file (sort alphabet) cover_files.sort(key=str.lower) for elem in cover_files: try: pixbuf = GdkPixbuf.Pixbuf.new_from_file( os.path.join(directory, elem)) except Exception as e: log.debug(e) if pixbuf: break return pixbuf
def update_book_download_status(self, book): """ Updates the downloaded status of a book. """ downloaded = True tracks = get_tracks(book) offline_tracks = OfflineCacheModel.select().where(OfflineCacheModel.track in tracks) if offline_tracks.count() < 1: downloaded = False else: for track in offline_tracks: if not track.copied: downloaded = False Book.update(downloaded=downloaded).where(Book.id == book.id).execute() if downloaded: self.emit_event("book-offline", book) else: self.emit_event("book-offline-removed", book)
def set_book(self, book): """ Display the given book in the book overview. """ if self.book and self.book.id == book.id: self.update_time() return self.book = Book.get(Book.id == book.id) if player.is_playing( ) and self.ui.titlebar.current_book and self.book.id == self.ui.titlebar.current_book.id: self.play_book_button.set_image(self.pause_img) else: self.play_book_button.set_image(self.play_img) self.name_label.set_text(book.name) self.author_label.set_text(book.author) self.update_offline_status() pixbuf = self._artwork_cache.get_cover_pixbuf( book, self.ui.window.get_scale_factor(), 250) if pixbuf: surface = Gdk.cairo_surface_create_from_pixbuf( pixbuf, self.ui.window.get_scale_factor(), None) self.cover_img.set_from_surface(surface) else: self.cover_img.set_from_icon_name("book-open-variant-symbolic", Gtk.IconSize.DIALOG) self.cover_img.props.pixel_size = 250 self.duration = get_book_duration(book) self.speed = self.book.playback_speed self.total_label.set_text( tools.seconds_to_human_readable(self.duration / self.speed)) self.last_played_label.set_text( tools.past_date_to_human_readable(book.last_played)) self.published_label.set_visible(False) self.published_text.set_visible(False) # track list # This box contains all track content self.track_box = Gtk.Box() self.track_box.set_orientation(Gtk.Orientation.VERTICAL) self.track_box.set_halign(Gtk.Align.START) self.track_box.set_valign(Gtk.Align.START) self.track_box.props.margin = 8 disk_number = -1 first_disk_element = None disk_count = 0 for track in get_tracks(book): # Insert disk headers if track.disk != disk_number: disc_element = DiskElement(track.disk) self.track_box.add(disc_element) if disk_number == -1: first_disk_element = disc_element if track.disk < 2: first_disk_element.set_hidden(True) else: first_disk_element.show_all() disc_element.show_all() disk_number = track.disk disk_count += 1 track_element = TrackElement(track, self) self.track_box.add(track_element) track_element.show_all() self.track_list_container.remove_all_children() self.track_box.show() self.track_box.set_halign(Gtk.Align.FILL) self.track_list_container.add(self.track_box) self._mark_current_track() self.update_time()