예제 #1
0
파일: player.py 프로젝트: aembleton/cinamp
 def set_next(self):
     """
         Play next track
     """
     if self._current_track.id is None:
         return
     if self._current_track.id == self.__stop_after_track_id:
         self._next_track = Track()
         return
     try:
         next_track = QueuePlayer.next(self)
         if next_track.id is None:
             # Diverge current track to restore playback from queue
             diverge_current_track = None
             if self._queue_current_track is not None:
                 diverge_current_track = self._current_track
                 self._current_track = self._queue_current_track
             if App().settings.get_value("shuffle") or self.is_party:
                 next_track = ShufflePlayer.next(self)
             else:
                 next_track = LinearPlayer.next(self)
             # Restore current track
             if diverge_current_track is not None:
                 self._current_track = diverge_current_track
                 self._queue_current_track = None
         self._next_track = next_track
         emit_signal(self, "next-changed")
     except Exception as e:
         Logger.error("Player::set_next(): %s" % e)
예제 #2
0
 def clear_albums(self):
     """
         Clear all albums
     """
     self._albums = []
     emit_signal(self, "playback-setted", [])
     self.update_next_prev()
    def show_menu(self, widget):
        """
            Show menu widget
            @param widget as Gtk.Widget
        """
        def on_hidden(widget, hide, view):
            if hide:
                self._stack.set_transition_type(
                    Gtk.StackTransitionType.SLIDE_UP)
                self.go_back()
                self._stack.set_transition_type(
                    Gtk.StackTransitionType.CROSSFADE)
                App().enable_special_shortcuts(True)
                if App().lookup_action("reload").get_state():
                    self.reload_view()
            if self.can_go_back:
                emit_signal(self, "can-go-back-changed", True)

        from lollypop.view_menu import MenuView
        view = MenuView(widget)
        view.show()
        widget.connect("hidden", on_hidden, view)
        self._stack.add(view)
        self._stack.set_transition_type(Gtk.StackTransitionType.SLIDE_DOWN)
        self._stack.set_visible_child(view)
        self._stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE)
        emit_signal(self, "can-go-back-changed", False)
        App().enable_special_shortcuts(False)
예제 #4
0
 def get(self, search, storage_type, cancellable):
     """
         Get albums for search
         We need a thread because we are going to populate DB
         @param search as str
         @param storage_type as StorageType
         @param cancellable as Gio.Cancellable
     """
     if not get_network_available("MUSICBRAINZ"):
         emit_signal(self, "finished")
         return
     try:
         uri = "http://musicbrainz.org/ws/2/release/?fmt=json&query=%s" %\
             search
         (status, data) = App().task_helper.load_uri_content_sync(
             uri, cancellable)
         if status:
             decode = json.loads(data.decode("utf-8"))
             for release in decode["releases"]:
                 payload = self.lollypop_album_payload(release)
                 self.save_album_payload_to_db(payload,
                                               storage_type,
                                               True,
                                               cancellable)
     except Exception as e:
         Logger.warning("MusicBrainzSearch::get(): %s", e)
     if not cancellable.is_cancelled():
         emit_signal(self, "finished")
예제 #5
0
    def __on_load_startpage_content(self, uri, loaded, content):
        """
            Extract uris from content
            @param uri as str
            @param loaded as bool
            @param content as bytes
        """
        import re

        def search_in_data(lines, found_uris=[]):
            if lines:
                line = lines.pop(0)
                # Do not call findall if nothing to find
                if line.find("oiu=") != -1:
                    res = re.findall(r'.*oiu=([^&]*).*', line)
                    for data in res:
                        uri = GLib.uri_unescape_string(data, "")
                        if uri in found_uris or uri is None:
                            continue
                        found_uris.append(uri)
                GLib.idle_add(search_in_data, lines, found_uris)
            else:
                results = [(uri, "Startpage") for uri in found_uris]
                emit_signal(self, "uri-artwork-found", results)

        try:
            if not loaded:
                emit_signal(self, "uri-artwork-found", None)
                return
            lines = content.decode("utf-8").splitlines()
            search_in_data(lines)
        except Exception as e:
            emit_signal(self, "uri-artwork-found", None)
            Logger.error("DownloaderArt::__on_load_startpage_content(): %s"
                         % e)
예제 #6
0
 def load_similars(self, artist_ids, storage_type, cancellable):
     """
         Load similar artists for artist ids
         @param artist_ids as int
         @param storage_type as StorageType
         @param cancellable as Gio.Cancellable
     """
     names = [App().artists.get_name(artist_id) for artist_id in artist_ids]
     spotify_ids = self.get_similar_artist_ids(names, cancellable)
     track_ids = []
     for spotify_id in spotify_ids:
         spotify_ids = self.get_artist_top_tracks(spotify_id, cancellable)
         # We want some randomizing so keep tracks for later usage
         spotify_id = choice(spotify_ids)
         track_ids += spotify_ids
         payload = self.get_track_payload(spotify_id, cancellable)
         lollypop_payload = self.lollypop_album_payload(payload["album"])
         item = self.save_album_payload_to_db(lollypop_payload,
                                              storage_type, True,
                                              cancellable)
         lollypop_payload = self.lollypop_track_payload(payload)
         self.save_track_payload_to_db(lollypop_payload, item, storage_type,
                                       True, cancellable)
     shuffle(track_ids)
     for spotify_id in track_ids:
         payload = self.get_track_payload(spotify_id, cancellable)
         lollypop_payload = self.lollypop_album_payload(payload["album"])
         item = self.save_album_payload_to_db(lollypop_payload,
                                              storage_type, True,
                                              cancellable)
         lollypop_payload = self.lollypop_track_payload(payload)
         self.save_track_payload_to_db(lollypop_payload, item, storage_type,
                                       True, cancellable)
     emit_signal(self, "finished")
예제 #7
0
 def __on_uri_content_loaded(self, helper, uri):
     """
         Emit loaded signal with content
         @param helper as BaseWebHelper
         @param uri as str
     """
     emit_signal(self, "loaded", uri)
예제 #8
0
 def populate(self):
     """
         Populate tracks lazy
     """
     self._init()
     if self.__discs_to_load:
         disc = self.__discs_to_load.pop(0)
         disc_number = disc.number
         tracks = disc.tracks
         items = []
         if self.view_type & ViewType.SINGLE_COLUMN:
             items.append((self._tracks_widget_left[0], tracks))
         else:
             mid_tracks = int(0.5 + len(tracks) / 2)
             items.append((self._tracks_widget_left[disc_number],
                           tracks[:mid_tracks]))
             items.append((self._tracks_widget_right[disc_number],
                           tracks[mid_tracks:]))
         self.__load_disc(items, disc_number)
     else:
         self.__populated = True
         emit_signal(self, "populated")
         if not self.children:
             label = Gtk.Label.new(_("All tracks skipped"))
             label.show()
             self._responsive_widget.insert_row(0)
             self._responsive_widget.attach(label, 0, 0, 2, 1)
예제 #9
0
    def set_party(self, party):
        """
            Set party mode on if party is True
            Play a new random track if not already playing
            @param party as bool
        """
        def start_party(*ignore):
            if self._albums:
                # Start a new song if not playing
                if self._current_track.id is None:
                    track = self.__get_tracks_random()
                    self.load(track)
                elif not self.is_playing:
                    self.play()
            emit_signal(self, "loading-changed", False, Track())

        if party == self._is_party:
            return
        self._is_party = party

        if party:
            App().task_helper.run(self.set_party_ids, callback=(start_party, ))
        else:
            # We want current album to continue playback
            self._albums = [self._current_track.album]
            emit_signal(self, "playback-setted", [])
            emit_signal(self, "playback-added", self._current_track.album)
        if self._current_track.id is not None:
            self.set_next()
            self.set_prev()
예제 #10
0
 def _on_activated(self, widget, track):
     """
         Handle playback if album or pass signal
         @param widget as TracksWidget
         @param track as Track
     """
     if self.view_type & (ViewType.ALBUM | ViewType.ARTIST):
         tracks = []
         for child in self.children:
             if child.track.loved != -1 or track.id == child.track.id:
                 tracks.append(child.track)
             child.set_state_flags(Gtk.StateFlags.NORMAL, True)
         # Do not update album list if in party or album already available
         playback_track = App().player.track_in_playback(track)
         if playback_track is not None:
             App().player.load(playback_track)
         elif not App().player.is_party:
             album = Album(track.album.id, [], [])
             album.set_tracks(tracks)
             if not App().settings.get_value("append-albums"):
                 App().player.clear_albums()
             App().player.add_album(album)
             App().player.load(album.get_track(track.id))
         else:
             App().player.load(track)
     else:
         emit_signal(self, "activated", track)
예제 #11
0
 def load_similars(self, artist_ids, storage_type, cancellable):
     """
         Load similar artists for artist ids
         @param artist_ids as int
         @param storage_type as StorageType
         @param cancellable as Gio.Cancellable
     """
     for artist_id in artist_ids:
         artist_name = App().artists.get_name(artist_id)
         deezer_id = self.get_artist_id(artist_name, cancellable)
         try:
             uri = "https://api.deezer.com/artist/%s/radio" % deezer_id
             (status, data) = App().task_helper.load_uri_content_sync(
                 uri, cancellable)
             if status:
                 decode = json.loads(data.decode("utf-8"))
                 for payload in decode["data"]:
                     track_payload = self.get_track_payload(
                         payload["id"], cancellable)
                     album_payload = self.get_album_payload(
                         payload["album"]["id"], cancellable)
                     lollypop_payload = self.lollypop_album_payload(
                         album_payload)
                     item = self.save_album_payload_to_db(
                         lollypop_payload, storage_type, True, cancellable)
                     lollypop_payload = self.lollypop_track_payload(
                         track_payload)
                     self.save_track_payload_to_db(lollypop_payload, item,
                                                   storage_type, True,
                                                   cancellable)
         except Exception as e:
             Logger.error("DeezerSimilars::load_similars(): %s", e)
     emit_signal(self, "finished")
예제 #12
0
 def set_artwork(self):
     """
         set_artwork widget
     """
     if self.__artwork is None:
         return
     if self.__rowid == Type.SEPARATOR:
         pass
     elif self.__mask & SelectionListMask.ARTISTS and\
             self.__rowid >= 0 and\
             App().settings.get_value("artist-artwork"):
         App().art_helper.set_artist_artwork(
             self.__name, ArtSize.SMALL, ArtSize.SMALL,
             self.get_scale_factor(), ArtBehaviour.ROUNDED
             | ArtBehaviour.CROP_SQUARE | ArtBehaviour.CACHE,
             self.__on_artist_artwork)
         self.__artwork.show()
     elif self.__rowid < 0:
         icon_name = get_icon_name(self.__rowid)
         self.__artwork.set_from_icon_name(icon_name, Gtk.IconSize.INVALID)
         self.__artwork.set_pixel_size(20)
         self.__artwork.show()
         emit_signal(self, "populated")
     else:
         self.__artwork.hide()
         emit_signal(self, "populated")
예제 #13
0
 def go_home(self):
     """
         Go back to first page
     """
     self.__widget.set_visible_child(self.sidebar)
     self._stack.clear()
     emit_signal(self, "can-go-back-changed", False)
예제 #14
0
 def get(self, search, storage_type, cancellable):
     """
         Get albums for search
         We need a thread because we are going to populate DB
         @param search as str
         @param storage_type as StorageType
         @param cancellable as Gio.Cancellable
     """
     if not get_network_available("DEEZER"):
         emit_signal(self, "finished")
         return
     try:
         uri = "https://api.deezer.com/search/album?q=%s" %\
             search
         (status, data) = App().task_helper.load_uri_content_sync(
             uri, cancellable)
         if status:
             decode = json.loads(data.decode("utf-8"))
             for albums in decode["data"]:
                 payload = self.lollypop_album_payload(albums)
                 self.save_album_payload_to_db(payload,
                                               storage_type,
                                               True,
                                               cancellable)
     except Exception as e:
         Logger.warning("DeezerSearch::get(): %s", e)
     if not cancellable.is_cancelled():
         emit_signal(self, "finished")
예제 #15
0
 def __on_closed(self, popover):
     """
         Destroy self
     """
     emit_signal(self, "hidden", True)
     if self.__auto_destroy:
         GLib.idle_add(self.destroy)
예제 #16
0
    def __lazy_loading(self):
        """
            Load the view in a lazy way
        """
        widget = None
        if self.__priority_queue:
            widget = self.__priority_queue.pop(0)
            self.__lazy_queue.remove(widget)
        elif self.__lazy_queue:
            widget = self.__lazy_queue.pop(0)

        if widget is not None:
            widget.connect("populated", self._on_populated)
            widget.populate()
        else:
            self.__loading_state = LoadingState.FINISHED
            emit_signal(self, "populated")
            # Apply filtering
            if App().window.container.type_ahead.get_reveal_child():
                text = App().window.container.type_ahead.entry.get_text()
                if text:
                    self.search_for_child(text)
                else:
                    GLib.idle_add(
                        App().window.container.type_ahead.entry.grab_focus)
            Logger.debug("LazyLoadingView::lazy_loading(): %s",
                         time() - self.__start_time)
예제 #17
0
 def _on_album_artwork(self, surface):
     """
         Set album artwork
         @param surface as str
     """
     emit_signal(self, "populated")
     CoverWidgetBase._on_album_artwork(self, surface)
예제 #18
0
 def __play_radio_common(self):
     """
         Emit signal and reset cancellable
     """
     emit_signal(self, "loading-changed", True, Track())
     self.__radio_cancellable.cancel()
     self.__radio_cancellable = Gio.Cancellable()
예제 #19
0
 def album_artwork_update(self, album_id):
     """
         Announce album cover update
         @param album_id as int
     """
     if album_id is not None:
         emit_signal(self, "album-artwork-changed", album_id)
예제 #20
0
 def save_album_payload_to_db(self, payload, storage_type,
                              notify, cancellable):
     """
         Save album to DB
         @param payload as {}
         @param storage_type as StorageType
         @param notify as bool
         @param cancellable as Gio.Cancellable
         @return CollectionItem/None
     """
     lp_album_id = get_lollypop_album_id(payload["name"],
                                         payload["artists"])
     album_id = App().albums.get_id_for_lp_album_id(lp_album_id)
     if album_id >= 0:
         album = Album(album_id)
         if notify:
             emit_signal(self, "match-album", album_id, storage_type)
         return album.collection_item
     item = self.__save_album(payload, storage_type)
     album = Album(item.album_id)
     if notify:
         self.save_artwork(album,
                           payload["artwork-uri"],
                           cancellable)
         emit_signal(self, "match-album", album.id, storage_type)
     return item
예제 #21
0
 def populate(self):
     """
         Populate widget
     """
     if self.__rowid == Type.SEPARATOR:
         separator = Gtk.Separator.new(Gtk.Orientation.HORIZONTAL)
         separator.show()
         self.add(separator)
         self.set_sensitive(False)
         emit_signal(self, "populated")
     else:
         self.__grid = Gtk.Grid()
         self.__grid.set_column_spacing(7)
         self.__grid.show()
         self.__artwork = Gtk.Image.new()
         self.__grid.add(self.__artwork)
         self.__label = Gtk.Label.new()
         self.__label.set_markup(GLib.markup_escape_text(self.__name))
         self.__label.set_property("has-tooltip", True)
         self.__label.connect("query-tooltip", on_query_tooltip)
         self.__label.set_xalign(0)
         self.__grid.add(self.__label)
         if self.__mask & SelectionListMask.ARTISTS:
             self.__grid.set_margin_end(20)
         self.add(self.__grid)
         self.set_artwork()
         self.set_mask()
예제 #22
0
 def _on_primary_press_gesture(self, x, y, event):
     """
         Activate current row
         @param x as int
         @param y as int
         @param event as Gdk.Event
     """
     row = self.get_row_at_y(y)
     if row is None:
         return
     if event.state & Gdk.ModifierType.CONTROL_MASK and\
             self.__view_type & ViewType.DND:
         self.set_selection_mode(Gtk.SelectionMode.MULTIPLE)
     elif event.state & Gdk.ModifierType.SHIFT_MASK:
         if self.__view_type & ViewType.DND:
             self.set_selection_mode(Gtk.SelectionMode.MULTIPLE)
             do_shift_selection(self, row)
         elif App().player.is_in_queue(row.track.id):
             App().player.remove_from_queue(row.track.id, True)
         else:
             App().player.append_to_queue(row.track.id, True)
     elif event.state & Gdk.ModifierType.MOD1_MASK:
         self.set_selection_mode(Gtk.SelectionMode.NONE)
         App().player.clear_albums()
         App().player.load(row.track)
     else:
         self.set_selection_mode(Gtk.SelectionMode.NONE)
         emit_signal(self, "activated", row.track)
예제 #23
0
 def __on_finished(self, search):
     """
         Emit finished signals if all search are finished
         @param search as Search provider
     """
     self.__search_count -= 1
     emit_signal(self, "finished", self.__search_count == 0)
예제 #24
0
파일: objects.py 프로젝트: aembleton/cinamp
 def set_rate(self, rate):
     """
         Set rate
         @param rate as int between -1 and 5
     """
     self.db.set_rate(self.id, rate)
     self.reset("rate")
     emit_signal(App().player, "rate-changed", self.id, rate)
예제 #25
0
 def __remove_from_queue(self, action, variant):
     """
         Delete track id from queue
         @param Gio.SimpleAction
         @param GLib.Variant
     """
     App().player.remove_from_queue(self.__track.id, False)
     emit_signal(App().player, "queue-changed")
예제 #26
0
 def __append_to_queue(self, action, variant):
     """
         Append track to queue
         @param Gio.SimpleAction
         @param GLib.Variant
     """
     App().player.append_to_queue(self.__track.id, False)
     emit_signal(App().player, "queue-changed")
예제 #27
0
 def __on_scroll(self, event_controller, x, y):
     """
         Pass scroll
         @param event_controller as Gtk.EventControllerScroll
         @param x as int
         @param y as int
     """
     emit_signal(self, "scroll", x, y)
예제 #28
0
 def __on_volume_changed(self, playbin, sink):
     """
         Emit volume-changed signal
         @param playbin as Gst.Bin
         @param sink as Gst.Sink
     """
     App().settings.set_value("volume-rate", GLib.Variant("d", self.volume))
     emit_signal(self, "volume-changed")
 def __on_clear_button_clicked(self, button):
     """
         Clear albums
         @param button as Gtk.Button
     """
     self.__view.clear()
     self.__view.populate()
     emit_signal(App().player, "status-changed")
예제 #30
0
 def __on_tracks_view_track_removed(self, view, row):
     """
         Remove row
         @param view as TracksView
         @param row as TrackRow
     """
     row.destroy()
     emit_signal(self, "track-removed", row.track)