示例#1
0
 def restore_state(self):
     """
         Restore player state
     """
     try:
         if App().settings.get_value("save-state"):
             current_track_id = load(open(LOLLYPOP_DATA_PATH +
                                          "/track_id.bin", "rb"))
             self.set_queue(load(open(LOLLYPOP_DATA_PATH +
                                      "/queue.bin", "rb")))
             albums = load(open(LOLLYPOP_DATA_PATH + "/Albums.bin", "rb"))
             playlist_ids = load(open(LOLLYPOP_DATA_PATH +
                                      "/playlist_ids.bin", "rb"))
             (is_playing, was_party) = load(open(LOLLYPOP_DATA_PATH +
                                                 "/player.bin", "rb"))
             if playlist_ids and playlist_ids[0] == Type.RADIOS:
                 radios = Radios()
                 track = Track()
                 name = radios.get_name(current_track_id)
                 url = radios.get_url(name)
                 track.set_radio(name, url)
                 self.load(track, is_playing)
             elif App().tracks.get_uri(current_track_id) != "":
                 if albums:
                     if was_party:
                         App().lookup_action("party").change_state(
                             GLib.Variant("b", True))
                     else:
                         self._albums = load(open(
                                             LOLLYPOP_DATA_PATH +
                                             "/Albums.bin",
                                             "rb"))
                     # Load track from player albums
                     current_track = Track(current_track_id)
                     index = self.album_ids.index(current_track.album.id)
                     for track in self._albums[index].tracks:
                         if track.id == current_track_id:
                             self._load_track(track)
                             break
                 else:
                     for playlist_id in playlist_ids:
                         tracks = App().playlists.get_tracks(playlist_id)
                         App().player.populate_playlist_by_tracks(
                             tracks, playlist_ids)
                         for track in tracks:
                             if track.id == current_track_id:
                                 self._load_track(track)
                                 break
                 if is_playing:
                     self.play()
                 else:
                     self.pause()
                 position = load(open(LOLLYPOP_DATA_PATH + "/position.bin",
                                 "rb"))
                 self.seek(position / Gst.SECOND)
             else:
                 Logger.info("Player::restore_state(): track missing")
             self.emit("playlist-changed")
     except Exception as e:
         Logger.error("Player::restore_state(): %s" % e)
示例#2
0
 def prepare_to_exit(self, action=None, param=None):
     """
         Save window position and view
     """
     if self._is_fs:
         return
     if self.settings.get_value('save-state'):
         self.window.save_view_state()
         # Save current track
         if self.player.current_track.id is None:
             track_id = -1
         elif self.player.current_track.id == Type.RADIOS:
             radios = Radios()
             track_id = radios.get_id(
                                     self.player.current_track.album_artist)
         else:
             track_id = self.player.current_track.id
         self.settings.set_value('track-id', GLib.Variant('i',
                                                          track_id))
         # Save current playlist
         if self.player.current_track.id == Type.RADIOS:
             playlist_ids = [Type.RADIOS]
         elif not self.player.get_user_playlist_ids():
             playlist_ids = []
         else:
             playlist_ids = self.player.get_user_playlist_ids()
         self.settings.set_value('playlist-ids', GLib.Variant('ai',
                                                              playlist_ids))
     self.player.stop_all()
     if self.window:
         self.window.stop_all()
     self.quit()
示例#3
0
    def prev(self):
        """
            Return prev radio name, uri
            @return Track
        """
        track = Track()
        if self.current_track.id != Type.RADIOS:
            return track

        radios_manager = Radios()
        radios = radios_manager.get()
        i = len(radios) - 1
        for (name, url) in reversed(radios):
            i -= 1
            if self.current_track.album_artist == name:
                break

        # Get prev radio
        if i < 0:
            i = len(radios) - 1

        name = radios[i][0]
        url = radios[i][1]
        if url:
            track.set_radio(name, url)
        return track
示例#4
0
    def next(self):
        """
            Return next radio name, uri
            @return Track
        """
        track = Track()
        if self.current_track.id != Type.RADIOS:
            return track

        radios_manager = Radios()
        radios = radios_manager.get()
        i = 0
        for (name, url) in radios:
            i += 1
            if self.current_track.album_artist == name:
                break

        # Get next radio
        if i >= len(radios):
            i = 0

        name = radios[i][0]
        url = radios[i][1]
        if url:
            track.set_radio(name, url)
        return track
示例#5
0
 def set_popularity(self, new_rate):
     """
         Set popularity
         @param new_rate as int between 0 and 5
     """
     if self.id is None:
         return
     try:
         if self.id >= 0:
             avg_popularity = self.db.get_avg_popularity()
             popularity = int((new_rate * avg_popularity / 5) + 0.5)
             best_popularity = self.db.get_higher_popularity()
             if new_rate == 5:
                 popularity = (popularity + best_popularity) / 2
             self.db.set_popularity(self.id, popularity)
         elif self.id == Type.RADIOS:
             radios = Radios()
             avg_popularity = radios.get_avg_popularity()
             popularity = int((new_rate * avg_popularity / 5) + 0.5)
             best_popularity = self.db.get_higher_popularity()
             if new_rate == 5:
                 popularity = (popularity + best_popularity) / 2
             radios.set_popularity(self._radio_id, popularity)
     except Exception as e:
         Logger.error("Base::set_popularity(): %s" % e)
示例#6
0
 def prepare_to_exit(self, action=None, param=None):
     """
         Save window position and view
     """
     if self._is_fs:
         return
     if self.settings.get_value('save-state'):
         self.window.save_view_state()
         # Save current track
         if self.player.current_track.id is None:
             track_id = -1
         elif self.player.current_track.id == Type.RADIOS:
             radios = Radios()
             track_id = radios.get_id(
                 self.player.current_track.album_artist)
         else:
             track_id = self.player.current_track.id
         self.settings.set_value('track-id', GLib.Variant('i', track_id))
         # Save current playlist
         if self.player.current_track.id == Type.RADIOS:
             playlist_ids = [Type.RADIOS]
         elif not self.player.get_user_playlist_ids():
             playlist_ids = []
         else:
             playlist_ids = self.player.get_user_playlist_ids()
         self.settings.set_value('playlist-ids',
                                 GLib.Variant('ai', playlist_ids))
     self.player.stop_all()
     if self.window:
         self.window.stop_all()
     self.quit()
示例#7
0
    def next(self):
        """
            Return next radio name, uri
            @return Track
        """
        track = Track()
        if self.current_track.id != Type.RADIOS:
            return track

        radios_manager = Radios()
        radios = radios_manager.get()
        i = 0
        for (name, url) in radios:
            i += 1
            if self.current_track.album_artist == name:
                break

        # Get next radio
        if i >= len(radios):
            i = 0

        name = radios[i][0]
        url = radios[i][1]
        if url:
            track.set_radio(name, url)
        return track
示例#8
0
    def prev(self):
        """
            Return prev radio name, uri
            @return Track
        """
        track = Track()
        if self.current_track.id != Type.RADIOS:
            return track

        radios_manager = Radios()
        radios = radios_manager.get()
        i = len(radios) - 1
        for (name, url) in reversed(radios):
            i -= 1
            if self.current_track.album_artist == name:
                break

        # Get prev radio
        if i < 0:
            i = len(radios) - 1

        name = radios[i][0]
        url = radios[i][1]
        if url:
            track.set_radio(name, url)
        return track
示例#9
0
 def restore_state(self):
     """
         Restore player state
     """
     try:
         if Lp().settings.get_value('save-state'):
             track_id = load(open(DataPath + "/track_id.bin", "rb"))
             playlist_ids = load(open(DataPath + "/playlist_ids.bin", "rb"))
             if playlist_ids and playlist_ids[0] == Type.RADIOS:
                 radios = Radios()
                 track = Track()
                 name = radios.get_name(track_id)
                 url = radios.get_url(name)
                 track.set_radio(name, url)
                 self.load(track)
             elif Lp().tracks.get_uri(track_id) != "":
                 track = Track(track_id)
                 if Lp().notify is not None:
                     Lp().notify.inhibit()
                 self._load_track(track)
                 # We set this initial state
                 # because seek while failed otherwise
                 self.pause()
                 if playlist_ids:
                     pids = []
                     for playlist_id in playlist_ids:
                         pids.append(int(playlist_id))
                     track_ids = []
                     for playlist_id in playlist_ids:
                         if playlist_id == Type.POPULARS:
                             tracks = Lp().tracks.get_populars()
                         elif playlist_id == Type.RECENTS:
                             tracks = Lp().tracks.get_recently_listened_to()
                         elif playlist_id == Type.NEVER:
                             tracks = Lp().tracks.get_never_listened_to()
                         elif playlist_id == Type.RANDOMS:
                             tracks = Lp().tracks.get_randoms()
                         else:
                             tracks = Lp().playlists.get_track_ids(
                                 playlist_id)
                         for track_id in tracks:
                             if track_id not in track_ids:
                                 track_ids.append(track_id)
                         self.populate_user_playlist_by_tracks(
                             track_ids, pids)
                 else:
                     self._albums = load(
                         open(DataPath + "/albums.bin", "rb"))
                     self.shuffle_albums(True)
                     self._context.genre_ids = load(
                         open(DataPath + "/genre_ids.bin", "rb"))
                     self._context.artist_ids = load(
                         open(DataPath + "/artist_ids.bin", "rb"))
                 self.set_next()
                 self.set_prev()
             else:
                 print("Player::restore_state(): track missing")
     except Exception as e:
         print("Player::restore_state()", e)
示例#10
0
 def restore_state(self):
     """
         Restore player state
     """
     if Lp().settings.get_value('save-state'):
         track_id = Lp().settings.get_value('track-id').get_int32()
         playlist_ids = Lp().settings.get_value('playlist-ids')
         if playlist_ids and playlist_ids[0] == Type.RADIOS:
             radios = Radios()
             track = Track()
             name = radios.get_name(track_id)
             url = radios.get_url(name)
             track.set_radio(name, url)
             self.load(track)
         elif Lp().tracks.get_path(track_id) != "":
             track = Track(track_id)
             self._load_track(track)
             if playlist_ids:
                 try:
                     pids = []
                     for playlist_id in playlist_ids:
                         pids.append(int(playlist_id))
                     track_ids = []
                     for playlist_id in playlist_ids:
                         if playlist_id == Type.POPULARS:
                             tracks = Lp().tracks.get_populars()
                         elif playlist_id == Type.RECENTS:
                             tracks = Lp().tracks.get_recently_listened_to()
                         elif playlist_id == Type.NEVER:
                             tracks = Lp().tracks.get_never_listened_to()
                         elif playlist_id == Type.RANDOMS:
                             tracks = Lp().tracks.get_randoms()
                         else:
                             tracks = Lp().playlists.get_tracks_ids(
                                                                playlist_id)
                         for track_id in tracks:
                             if track_id not in track_ids:
                                 track_ids.append(track_id)
                         self.populate_user_playlist_by_tracks(track_ids,
                                                               pids)
                 except:
                     pass  # User set non int in gsettings
             else:
                 self._albums = Lp().artists.get_albums(
                                                     track.album_artist_ids)
                 for album_id in self._albums:
                     self.context.genre_ids[album_id] = []
                     self.context.artist_ids[album_id] = []
             self.set_next()
             self.set_prev()
             if Lp().settings.get_value('repeat'):
                 self.context.next = NextContext.NONE
             else:
                 self.context.next = NextContext.STOP_ALL
             self.emit('current-changed')
         else:
             print("Player::restore_state(): track missing")
示例#11
0
 def restore_state(self):
     """
         Restore player state
     """
     if Lp().settings.get_value('save-state'):
         track_id = Lp().settings.get_value('track-id').get_int32()
         playlist_ids = Lp().settings.get_value('playlist-ids')
         if playlist_ids and playlist_ids[0] == Type.RADIOS:
             radios = Radios()
             track = Track()
             name = radios.get_name(track_id)
             url = radios.get_url(name)
             track.set_radio(name, url)
             self.load(track)
         elif Lp().tracks.get_path(track_id) != "":
             track = Track(track_id)
             self._load_track(track)
             if playlist_ids:
                 try:
                     pids = []
                     for playlist_id in playlist_ids:
                         pids.append(int(playlist_id))
                     track_ids = []
                     for playlist_id in playlist_ids:
                         if playlist_id == Type.POPULARS:
                             tracks = Lp().tracks.get_populars()
                         elif playlist_id == Type.RECENTS:
                             tracks = Lp().tracks.get_recently_listened_to()
                         elif playlist_id == Type.NEVER:
                             tracks = Lp().tracks.get_never_listened_to()
                         elif playlist_id == Type.RANDOMS:
                             tracks = Lp().tracks.get_randoms()
                         else:
                             tracks = Lp().playlists.get_tracks_ids(
                                                                playlist_id)
                         for track_id in tracks:
                             if track_id not in track_ids:
                                 track_ids.append(track_id)
                         self.populate_user_playlist_by_tracks(track_ids,
                                                               pids)
                 except:
                     pass  # User set non int in gsettings
             else:
                 self._albums = Lp().artists.get_albums(
                                                     track.album_artist_ids)
                 for album_id in self._albums:
                     self.context.genre_ids[album_id] = []
                     self.context.artist_ids[album_id] = []
             self.set_next()
             self.set_prev()
             if Lp().settings.get_value('repeat'):
                 self.context.next = NextContext.NONE
             else:
                 self.context.next = NextContext.STOP_ALL
             self.emit('current-changed')
         else:
             print("Player::restore_state(): track missing")
示例#12
0
 def set_rate(self, rate):
     """
         Set rate
         @param rate as int between -1 and 5
     """
     if self.id == Type.RADIOS:
         radios = Radios()
         radios.set_rate(self._album_artists[0], rate)
     else:
         self.db.set_rate(self.id, rate)
示例#13
0
 def set_radio_id(self, radio_id):
     """
         Set radio id
         @param radio_id as int
     """
     from lollypop.radios import Radios
     radios = Radios()
     name = radios.get_name(radio_id)
     uri = radios.get_uri(radio_id)
     self.set_radio(name, uri)
示例#14
0
 def set_rate(self, rate):
     """
         Set rate
         @param rate as int between -1 and 5
     """
     if self.id == Type.RADIOS:
         radios = Radios()
         radios.set_rate(self._radio_id, rate)
     else:
         self.db.set_rate(self.id, rate)
         App().player.emit("rate-changed", (self.id, rate))
示例#15
0
 def set_radio_id(self, radio_id):
     """
         Set radio id
         @param radio_id as int
     """
     from lollypop.radios import Radios
     radios = Radios()
     self.id = Type.RADIOS
     self._radio_id = radio_id
     self._radio_name = radios.get_name(radio_id)
     self._uri = radios.get_uri(radio_id)
示例#16
0
 def prepare_to_exit(self, action=None, param=None, exit=True):
     """
         Save window position and view
     """
     if self.__is_fs:
         return
     if self.settings.get_value('save-state'):
         self.window.save_view_state()
         # Save current track
         if self.player.current_track.id is None:
             track_id = -1
         elif self.player.current_track.id == Type.RADIOS:
             from lollypop.radios import Radios
             radios = Radios()
             track_id = radios.get_id(
                                 self.player.current_track.album_artists[0])
         else:
             track_id = self.player.current_track.id
             # Save albums context
             try:
                 dump(self.player.context.genre_ids,
                      open(DataPath + "/genre_ids.bin", "wb"))
                 dump(self.player.context.artist_ids,
                      open(DataPath + "/artist_ids.bin", "wb"))
                 self.player.shuffle_albums(False)
                 dump(self.player.get_albums(),
                      open(DataPath + "/albums.bin", "wb"))
             except Exception as e:
                 print("Application::prepare_to_exit()", e)
         dump(track_id, open(DataPath + "/track_id.bin", "wb"))
         dump([self.player.is_playing, self.player.is_party],
              open(DataPath + "/player.bin", "wb"))
         # Save current playlist
         if self.player.current_track.id == Type.RADIOS:
             playlist_ids = [Type.RADIOS]
         elif not self.player.get_user_playlist_ids():
             playlist_ids = []
         else:
             playlist_ids = self.player.get_user_playlist_ids()
         dump(playlist_ids,
              open(DataPath + "/playlist_ids.bin", "wb"))
     if self.player.current_track.id is not None:
         position = self.player.position
     else:
         position = 0
     dump(position, open(DataPath + "/position.bin", "wb"))
     self.player.stop_all()
     self.window.stop_all()
     if self.charts is not None:
         self.charts.stop()
     if exit:
         self.quit()
示例#17
0
    def __init__(self, radios_manager=None):
        """
            Init Popover
            @param radios_manager as Radios
        """
        Gtk.Popover.__init__(self)
        self._tunein = TuneIn()
        if radios_manager is not None:
            self._radios_manager = radios_manager
        else:
            self._radios_manager = Radios()
        self._current_url = None
        self._previous_urls = []
        self._covers_to_download = []

        self._stack = Gtk.Stack()
        self._stack.set_property('expand', True)
        self._stack.show()

        builder = Gtk.Builder()
        builder.add_from_resource('/org/gnome/Lollypop/TuneinPopover.ui')
        builder.connect_signals(self)
        widget = builder.get_object('widget')
        widget.attach(self._stack, 0, 2, 4, 1)

        self._back_btn = builder.get_object('back_btn')
        self._home_btn = builder.get_object('home_btn')
        self._label = builder.get_object('label')

        self._view = Gtk.FlowBox()
        self._view.set_selection_mode(Gtk.SelectionMode.NONE)
        self._view.set_max_children_per_line(100)
        self._view.set_property('row-spacing', 10)
        self._view.set_property('expand', True)
        self._view.show()

        self._spinner = builder.get_object('spinner')

        builder.get_object('viewport').add(self._view)
        builder.get_object('viewport').set_property('margin', 10)

        self._scrolled = builder.get_object('scrolled')
        self._stack.add_named(self._spinner, 'spinner')
        self._stack.add_named(builder.get_object('notfound'), 'notfound')
        self._stack.add_named(self._scrolled, 'scrolled')
        self.add(widget)
        size_setting = Lp().settings.get_value('window-size')
        if isinstance(size_setting[1], int):
            self.set_size_request(700, size_setting[1] * 0.7)
        else:
            self.set_size_request(700, 400)
示例#18
0
    def __init__(self, radios_manager=None):
        """
            Init Popover
            @param radios_manager as Radios
        """
        Gtk.Popover.__init__(self)
        self.__tunein = TuneIn()
        if radios_manager is not None:
            self.__radios_manager = radios_manager
        else:
            self.__radios_manager = Radios()
        self.__current_url = None
        self.__timeout_id = None
        self.__previous_urls = []
        self.__covers_to_download = []

        self.__stack = Gtk.Stack()
        self.__stack.set_property("expand", True)
        self.__stack.show()

        builder = Gtk.Builder()
        builder.add_from_resource("/org/gnome/Lollypop/TuneinPopover.ui")
        builder.connect_signals(self)
        widget = builder.get_object("widget")
        widget.attach(self.__stack, 0, 2, 5, 1)

        self.__back_btn = builder.get_object("back_btn")
        self.__home_btn = builder.get_object("home_btn")
        self.__label = builder.get_object("label")

        self.__view = Gtk.FlowBox()
        self.__view.set_selection_mode(Gtk.SelectionMode.NONE)
        self.__view.set_max_children_per_line(100)
        self.__view.set_property("row-spacing", 10)
        self.__view.set_property("expand", True)
        self.__view.show()

        self.__spinner = builder.get_object("spinner")

        builder.get_object("viewport").add(self.__view)
        builder.get_object("viewport").set_property("margin", 10)

        self.__scrolled = builder.get_object("scrolled")
        self.__stack.add_named(self.__spinner, "spinner")
        self.__stack.add_named(builder.get_object("notfound"), "notfound")
        self.__stack.add_named(self.__scrolled, "scrolled")
        self.add(widget)
        self.connect("map", self.__on_map)
        self.connect("unmap", self.__on_unmap)
示例#19
0
 def __init__(self):
     """
         Init view
     """
     FlowBoxView.__init__(self)
     ViewController.__init__(self, ViewControllerType.RADIO)
     self._widget_class = RadioWidget
     self.__radios = Radios()
     builder = Gtk.Builder()
     builder.add_from_resource("/org/gnome/Lollypop/RadiosView.ui")
     builder.connect_signals(self)
     self.insert_row(0)
     self.attach(builder.get_object("widget"), 0, 0, 1, 1)
     self.__pop_tunein = TuneinPopover(self.__radios)
     self.__pop_tunein.set_relative_to(builder.get_object("search_btn"))
示例#20
0
    def get_rate(self):
        """
            Get rate
            @return int
        """
        if self.id is None or self.id == Type.EXTERNALS:
            return 0

        rate = 0
        if self.id >= 0:
            rate = self.db.get_rate(self.id)
        elif self.id == Type.RADIOS:
            radios = Radios()
            rate = radios.get_rate(self._album_artists[0])
        return rate
示例#21
0
    def get_rate(self):
        """
            Get rate
            @return int
        """
        if self.id is None:
            return 0

        rate = 0
        if self.id >= 0:
            rate = self.db.get_rate(self.id)
        elif self.id == Type.RADIOS:
            radios = Radios()
            rate = radios.get_rate(self._radio_id)
        return rate
示例#22
0
 def __start_playback(self, track):
     """
         Start playing track
         @param track as Track:
     """
     self._plugins.volume.props.volume = 1.0
     self._playbin.set_state(Gst.State.NULL)
     self._playbin.set_property('uri', track.uri)
     Radios().set_more_popular(track.album_artists[0])
     self._current_track = track
     self.__current = None
     self._playbin.set_state(Gst.State.PLAYING)
     if not self.__radios:
         self.__radios = Radios().get()
     self.emit('status-changed')
示例#23
0
 def __save_state(self):
     """
         Save window position and view
     """
     if self.is_fullscreen():
         return
     if self.settings.get_value("save-state"):
         self.window.save_view_state()
         # Save current track
         if self.player.current_track.id is None:
             track_id = -1
         elif self.player.current_track.id == Type.RADIOS:
             from lollypop.radios import Radios
             radios = Radios()
             track_id = radios.get_id(
                 self.player.current_track.album_artists[0])
         else:
             track_id = self.player.current_track.id
             # Save albums context
             try:
                 dump(self.player.context.genre_ids,
                      open(LOLLYPOP_DATA_PATH + "/genre_ids.bin", "wb"))
                 dump(self.player.context.artist_ids,
                      open(LOLLYPOP_DATA_PATH + "/artist_ids.bin", "wb"))
                 self.player.shuffle_albums(False)
                 dump(self.player.get_albums(),
                      open(LOLLYPOP_DATA_PATH + "/albums.bin", "wb"))
             except Exception as e:
                 print("Application::__save_state()", e)
         dump(track_id, open(LOLLYPOP_DATA_PATH + "/track_id.bin", "wb"))
         dump([self.player.is_playing, self.player.is_party],
              open(LOLLYPOP_DATA_PATH + "/player.bin", "wb"))
         # Save current playlist
         if self.player.current_track.id == Type.RADIOS:
             playlist_ids = [Type.RADIOS]
         elif not self.player.get_user_playlist_ids():
             playlist_ids = []
         else:
             playlist_ids = self.player.get_user_playlist_ids()
         dump(playlist_ids,
              open(LOLLYPOP_DATA_PATH + "/playlist_ids.bin", "wb"))
     if self.player.current_track.id is not None:
         position = self.player.position
     else:
         position = 0
     dump(position, open(LOLLYPOP_DATA_PATH + "/position.bin", "wb"))
     self.player.stop_all()
     self.window.stop_all()
示例#24
0
 def quit(self):
     """
         Quit lollypop
     """
     if self.scanner.is_locked():
         self.scanner.stop()
         GLib.idle_add(self.quit)
         return
     self.db.del_tracks(self.tracks.get_non_persistent())
     try:
         from lollypop.radios import Radios
         with SqlCursor(self.db) as sql:
             sql.isolation_level = None
             sql.execute('VACUUM')
             sql.isolation_level = ''
         with SqlCursor(self.playlists) as sql:
             sql.isolation_level = None
             sql.execute('VACUUM')
             sql.isolation_level = ''
         with SqlCursor(Radios()) as sql:
             sql.isolation_level = None
             sql.execute('VACUUM')
             sql.isolation_level = ''
     except Exception as e:
         print("Application::quit(): ", e)
     self.window.destroy()
示例#25
0
 def __upgrade_21(self, db):
     """
         Add rate to radios
     """
     with SqlCursor(Radios()) as sql:
         sql.execute("ALTER TABLE radios ADD rate\
                      INT NOT NULL DEFAULT -1")
示例#26
0
    def __vacuum(self):
        """
            VACUUM DB
        """
        try:
            if self.scanner.is_locked():
                self.scanner.stop()
                GLib.idle_add(self.__vacuum)
                return
            self.tracks.del_non_persistent()
            self.tracks.clean()
            self.albums.clean()
            self.artists.clean()
            self.genres.clean()

            from lollypop.radios import Radios
            with SqlCursor(self.db) as sql:
                sql.isolation_level = None
                sql.execute("VACUUM")
                sql.isolation_level = ""
            with SqlCursor(self.playlists) as sql:
                sql.isolation_level = None
                sql.execute("VACUUM")
                sql.isolation_level = ""
            with SqlCursor(Radios()) as sql:
                sql.isolation_level = None
                sql.execute("VACUUM")
                sql.isolation_level = ""
        except Exception as e:
            Logger.error("Application::__vacuum(): %s" % e)
示例#27
0
 def __vacuum(self):
     """
         VACUUM DB
     """
     if self.scanner.is_locked():
         self.scanner.stop()
         GLib.idle_add(self.__vacuum)
         return
     self.db.del_tracks(self.tracks.get_non_persistent())
     try:
         from lollypop.radios import Radios
         with SqlCursor(self.db) as sql:
             sql.isolation_level = None
             sql.execute("VACUUM")
             sql.isolation_level = ""
         with SqlCursor(self.playlists) as sql:
             sql.isolation_level = None
             sql.execute("VACUUM")
             sql.isolation_level = ""
         with SqlCursor(Radios()) as sql:
             sql.isolation_level = None
             sql.execute("VACUUM")
             sql.isolation_level = ""
     except Exception as e:
         print("Application::__vacuum(): ", e)
示例#28
0
 def set_radio(self, name, uri):
     """
         Set radio for non DB radios (Tunein)
         @param name as string
         @param uri as string
     """
     from lollypop.radios import Radios
     radios = Radios()
     self.id = Type.RADIOS
     self._radio_id = radios.get_id(name)
     self._radio_name = name
     self._uri = uri
     # Generate a tmp album id, needed by InfoController
     album_id = 0
     for i in list(map(ord, name)):
         album_id += i
     self.album.id = album_id
示例#29
0
    def __init__(self):
        """
            Init view
        """
        View.__init__(self)
        self._signal = Lp().art.connect('radio-artwork-changed',
                                        self._on_logo_changed)

        self._radios_manager = Radios()
        self._radios_manager.connect('radios-changed',
                                     self._on_radios_changed)
        builder = Gtk.Builder()
        builder.add_from_resource('/org/gnome/Lollypop/RadiosView.ui')
        builder.connect_signals(self)
        widget = builder.get_object('widget')
        self._empty = builder.get_object('empty')

        self._pop_tunein = TuneinPopover(self._radios_manager)
        self._pop_tunein.set_relative_to(builder.get_object('search_btn'))

        self._sizegroup = Gtk.SizeGroup(mode=Gtk.SizeGroupMode.BOTH)

        self._radiobox = Gtk.FlowBox()
        self._radiobox.set_selection_mode(Gtk.SelectionMode.NONE)
        self._radiobox.connect("child-activated", self._on_album_activated)
        self._radiobox.set_property('column-spacing', 5)
        self._radiobox.set_property('row-spacing', 5)
        self._radiobox.set_homogeneous(True)
        self._radiobox.set_max_children_per_line(1000)
        self._radiobox.show()

        self._stack = Gtk.Stack()
        self._stack.set_transition_duration(500)
        self._stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE)
        self._stack.add(self._scrolled)
        self._stack.add(self._empty)
        self._stack.show()

        self._viewport.set_property("valign", Gtk.Align.START)
        self._viewport.set_property('margin', 5)
        self._viewport.add(self._radiobox)
        self._scrolled.set_property('expand', True)

        self.add(widget)
        self.add(self._stack)
示例#30
0
 def __init__(self, view_type=ViewType.SCROLLED):
     """
         Init view
         @param view_type as ViewType
     """
     FlowBoxView.__init__(self, view_type)
     ViewController.__init__(self, ViewControllerType.RADIO)
     self._widget_class = RadioWidget
     self._empty_icon_name = get_icon_name(Type.RADIOS)
     self.__radios = Radios()
     builder = Gtk.Builder()
     builder.add_from_resource("/org/gnome/Lollypop/RadiosView.ui")
     builder.connect_signals(self)
     self.insert_row(0)
     self.attach(builder.get_object("widget"), 0, 0, 1, 1)
     self.__pop_tunein = None
     if not get_network_available("TUNEIN"):
         builder.get_object("search_btn").hide()
示例#31
0
 def set_popularity(self, popularity):
     """
         Set popularity
         @param popularity as int between 0 and 5
     """
     if self.id is None or self.id == Type.EXTERNALS:
         return
     try:
         if self.id >= 0:
             avg_popularity = self.db.get_avg_popularity()
             popularity = int((popularity * avg_popularity / 5) + 0.5)
             self.db.set_popularity(self.id, popularity, True)
         elif self.id == Type.RADIOS:
             radios = Radios()
             avg_popularity = radios.get_avg_popularity()
             popularity = int((popularity * avg_popularity / 5) + 0.5)
             radios.set_popularity(self._album_artists[0], popularity)
     except Exception as e:
         print("Base::set_popularity(): %s" % e)
示例#32
0
    def get_popularity(self):
        """
            Get popularity
            @return int between 0 and 5
        """
        if self.id is None or self.id == Type.EXTERNALS:
            return 0

        popularity = 0
        if self.id >= 0:
            avg_popularity = self.db.get_avg_popularity()
            if avg_popularity > 0:
                popularity = self.db.get_popularity(self.id)
        elif self.id == Type.RADIOS:
            radios = Radios()
            avg_popularity = radios.get_avg_popularity()
            if avg_popularity > 0:
                popularity = radios.get_popularity(self._album_artists[0])
        return popularity * 5 / avg_popularity + 0.5
示例#33
0
 def set_popularity(self, popularity):
     """
         Set popularity
         @param popularity as int between 0 and 5
     """
     if self.id is None or self.id == Type.EXTERNALS:
         return
     try:
         if self.id >= 0:
             avg_popularity = self.db.get_avg_popularity()
             popularity = int((popularity * avg_popularity / 5) + 0.5)
             self.db.set_popularity(self.id, popularity, True)
         elif self.id == Type.RADIOS:
             radios = Radios()
             avg_popularity = radios.get_avg_popularity()
             popularity = int((popularity * avg_popularity / 5) + 0.5)
             radios.set_popularity(self._album_artists[0], popularity)
     except Exception as e:
         print("Base::set_popularity(): %s" % e)
示例#34
0
    def get_popularity(self):
        """
            Get popularity
            @return int between 0 and 5
        """
        if self.id is None:
            return 0

        popularity = 0
        if self.id >= 0:
            avg_popularity = self.db.get_avg_popularity()
            if avg_popularity > 0:
                popularity = self.db.get_popularity(self.id)
        elif self.id == Type.RADIOS:
            radios = Radios()
            avg_popularity = radios.get_avg_popularity()
            if avg_popularity > 0:
                popularity = radios.get_popularity(self._radio_id)
        return popularity * 5 / avg_popularity + 0.5
示例#35
0
    def get_popularity(self):
        """
            Get popularity
            @return int between 0 and 5
        """
        if self.id is None or self.id == Type.EXTERNALS:
            return 0

        popularity = 0
        if self.id >= 0:
            avg_popularity = self.db.get_avg_popularity()
            if avg_popularity > 0:
                popularity = self.db.get_popularity(self.id)
        elif self.id == Type.RADIOS:
            radios = Radios()
            avg_popularity = radios.get_avg_popularity()
            if avg_popularity > 0:
                popularity = radios.get_popularity(self._album_artists[0])
        return popularity * 5 / avg_popularity + 0.5
示例#36
0
    def __save_state(self):
        """
            Save window position and view
        """
        if not self.settings.get_value("save-state"):
            return

        if self.player.current_track.id is None or\
                self.player.current_track.mtime == 0:
            track_id = None
        elif self.player.current_track.id == Type.RADIOS:
            from lollypop.radios import Radios
            radios = Radios()
            track_id = radios.get_id(self.player.current_track.radio_name)
        else:
            track_id = self.player.current_track.id
            # Save albums context
            try:
                with open(LOLLYPOP_DATA_PATH + "/Albums.bin", "wb") as f:
                    dump(list(self.player.albums), f)
            except Exception as e:
                Logger.error("Application::__save_state(): %s" % e)
        dump(track_id, open(LOLLYPOP_DATA_PATH + "/track_id.bin", "wb"))
        dump([self.player.is_playing, self.player.is_party],
             open(LOLLYPOP_DATA_PATH + "/player.bin", "wb"))
        dump(self.player.queue, open(LOLLYPOP_DATA_PATH + "/queue.bin", "wb"))
        # Save current playlist
        if self.player.current_track.id == Type.RADIOS:
            playlist_ids = [Type.RADIOS]
        elif not self.player.playlist_ids:
            playlist_ids = []
        else:
            playlist_ids = self.player.playlist_ids
        dump(playlist_ids, open(LOLLYPOP_DATA_PATH + "/playlist_ids.bin",
                                "wb"))
        if self.player.current_track.id is not None:
            position = self.player.position
        else:
            position = 0
        dump(position, open(LOLLYPOP_DATA_PATH + "/position.bin", "wb"))
        self.player.stop_all()
        self.__window.container.stop_all()
示例#37
0
    def __init__(self, radios_manager=None):
        """
            Init Popover
            @param radios_manager as Radios
        """
        Gtk.Popover.__init__(self)
        self._tunein = TuneIn()
        if radios_manager is not None:
            self._radios_manager = radios_manager
        else:
            self._radios_manager = Radios()
        self._current_url = None
        self._timeout_id = None
        self._previous_urls = []
        self._covers_to_download = []

        self._stack = Gtk.Stack()
        self._stack.set_property('expand', True)
        self._stack.show()

        builder = Gtk.Builder()
        builder.add_from_resource('/org/gnome/Lollypop/TuneinPopover.ui')
        builder.connect_signals(self)
        widget = builder.get_object('widget')
        widget.attach(self._stack, 0, 2, 5, 1)

        self._back_btn = builder.get_object('back_btn')
        self._home_btn = builder.get_object('home_btn')
        self._label = builder.get_object('label')

        self._view = Gtk.FlowBox()
        self._view.set_selection_mode(Gtk.SelectionMode.NONE)
        self._view.set_max_children_per_line(100)
        self._view.set_property('row-spacing', 10)
        self._view.set_property('expand', True)
        self._view.show()

        self._spinner = builder.get_object('spinner')

        builder.get_object('viewport').add(self._view)
        builder.get_object('viewport').set_property('margin', 10)

        self._scrolled = builder.get_object('scrolled')
        self._stack.add_named(self._spinner, 'spinner')
        self._stack.add_named(builder.get_object('notfound'), 'notfound')
        self._stack.add_named(self._scrolled, 'scrolled')
        self.add(widget)
        size_setting = Lp().settings.get_value('window-size')
        if isinstance(size_setting[1], int):
            self.set_size_request(700, size_setting[1]*0.7)
        else:
            self.set_size_request(700, 400)
示例#38
0
 def quit(self):
     """
         Quit lollypop
     """
     if Lp.scanner.is_locked():
         Lp.scanner.stop()
         GLib.idle_add(self.quit)
         return
     try:
         Lp.sql.execute('VACUUM')
         sql_p = Lp.playlists.get_cursor()
         sql_p.execute('VACUUM')
         sql_p.close()
         radios = Radios()
         sql_r = radios.get_cursor()
         sql_r.execute('VACUUM')
         sql_r.close()
     except Exception as e:
         print("Application::quit(): ", e)
     Lp.window.destroy()
     Lp.sql.close()
     Gst.deinit()
示例#39
0
    def __init__(self, radios_manager=None):
        """
            Init Popover
            @param radios_manager as Radios
        """
        Gtk.Popover.__init__(self)
        self._tunein = TuneIn()
        if radios_manager is not None:
            self._radios_manager = radios_manager
        else:
            self._radios_manager = Radios()
        self._current_url = None
        self._previous_urls = []

        self._stack = Gtk.Stack()
        self._stack.set_property("expand", True)
        self._stack.show()

        builder = Gtk.Builder()
        builder.add_from_resource("/org/gnome/Lollypop/TuneinPopover.ui")
        builder.connect_signals(self)
        widget = builder.get_object("widget")
        widget.attach(self._stack, 0, 2, 4, 1)

        self._back_btn = builder.get_object("back_btn")
        self._home_btn = builder.get_object("home_btn")
        self._label = builder.get_object("label")

        self._view = Gtk.FlowBox()
        self._view.set_selection_mode(Gtk.SelectionMode.NONE)
        self._view.set_max_children_per_line(100)
        self._view.set_property("row-spacing", 10)
        self._view.set_property("expand", True)
        self._view.show()

        builder.get_object("viewport").add(self._view)
        builder.get_object("viewport").set_property("margin", 10)

        self._scrolled = builder.get_object("scrolled")
        self._stack.add_named(builder.get_object("spinner"), "spinner")
        self._stack.add_named(builder.get_object("notfound"), "notfound")
        self._stack.add_named(self._scrolled, "scrolled")
        self._stack.set_visible_child_name("spinner")
        self.add(widget)
        size_setting = Lp().settings.get_value("window-size")
        if isinstance(size_setting[1], int):
            self.set_size_request(700, size_setting[1] * 0.7)
        else:
            self.set_size_request(700, 400)
示例#40
0
    def __init__(self):
        """
            Init view
        """
        View.__init__(self)
        self._signal = Lp().art.connect('radio-artwork-changed',
                                        self._on_logo_changed)

        self._radios_manager = Radios()
        self._radios_manager.connect('radios-changed',
                                     self._on_radios_changed)
        builder = Gtk.Builder()
        builder.add_from_resource('/org/gnome/Lollypop/RadiosView.ui')
        builder.connect_signals(self)
        widget = builder.get_object('widget')
        self._empty = builder.get_object('empty')

        self._pop_tunein = TuneinPopover(self._radios_manager)
        self._pop_tunein.set_relative_to(builder.get_object('search_btn'))

        self._sizegroup = Gtk.SizeGroup(mode=Gtk.SizeGroupMode.BOTH)

        self._radiobox = Gtk.FlowBox()
        self._radiobox.set_selection_mode(Gtk.SelectionMode.NONE)
        self._radiobox.connect("child-activated", self._on_album_activated)
        self._radiobox.set_property('column-spacing', 5)
        self._radiobox.set_property('row-spacing', 5)
        self._radiobox.set_homogeneous(True)
        self._radiobox.set_max_children_per_line(1000)
        self._radiobox.show()

        self._stack = Gtk.Stack()
        self._stack.set_transition_duration(500)
        self._stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE)
        self._stack.add(self._scrolled)
        self._stack.add(self._empty)
        self._stack.show()

        self._viewport.set_property("valign", Gtk.Align.START)
        self._viewport.set_property('margin', 5)
        self._viewport.add(self._radiobox)
        self._scrolled.set_property('expand', True)

        self.add(widget)
        self.add(self._stack)
示例#41
0
    def __init__(self):
        """
            Init view
        """
        LazyLoadingView.__init__(self, True)
        self.__signal = Lp().art.connect('radio-artwork-changed',
                                         self.__on_logo_changed)

        self.__radios_manager = Radios()
        self.__radios_manager.connect('radios-changed',
                                      self.__on_radios_changed)
        builder = Gtk.Builder()
        builder.add_from_resource('/org/gnome/Lollypop/RadiosView.ui')
        builder.connect_signals(self)
        widget = builder.get_object('widget')
        self.__empty = builder.get_object('empty')

        self.__pop_tunein = TuneinPopover(self.__radios_manager)
        self.__pop_tunein.set_relative_to(builder.get_object('search_btn'))

        self._box = Gtk.FlowBox()
        self._box.set_selection_mode(Gtk.SelectionMode.NONE)
        # Allow lazy loading to not jump up and down
        self._box.set_homogeneous(True)
        self._box.set_max_children_per_line(1000)
        self._box.set_filter_func(self._filter_func)
        self._box.show()

        self.__stack = Gtk.Stack()
        self.__stack.set_transition_duration(500)
        self.__stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE)
        self.__stack.add(self._scrolled)
        self.__stack.add(self.__empty)
        self.__stack.show()

        self._viewport.set_property("valign", Gtk.Align.START)
        self._viewport.set_property('margin', 5)
        self._scrolled.set_property('expand', True)

        self.add(widget)
        self.add(self.__stack)
示例#42
0
 def restore_state(self):
     """
         Restore player state
     """
     try:
         if Lp().settings.get_value('save-state'):
             track_id = load(open(DataPath + "/track_id.bin", "rb"))
             playlist_ids = load(open(DataPath + "/playlist_ids.bin",
                                 "rb"))
             if playlist_ids and playlist_ids[0] == Type.RADIOS:
                 radios = Radios()
                 track = Track()
                 name = radios.get_name(track_id)
                 url = radios.get_url(name)
                 track.set_radio(name, url)
                 self.load(track)
             elif Lp().tracks.get_path(track_id) != "":
                 track = Track(track_id)
                 if Lp().notify is not None:
                     Lp().notify.inhibit()
                 self._load_track(track)
                 # We set this initial state
                 # because seek while failed otherwise
                 self.pause()
                 if playlist_ids:
                     pids = []
                     for playlist_id in playlist_ids:
                         pids.append(int(playlist_id))
                     track_ids = []
                     for playlist_id in playlist_ids:
                         if playlist_id == Type.POPULARS:
                             tracks = Lp().tracks.get_populars()
                         elif playlist_id == Type.RECENTS:
                             tracks = Lp().tracks.get_recently_listened_to()
                         elif playlist_id == Type.NEVER:
                             tracks = Lp().tracks.get_never_listened_to()
                         elif playlist_id == Type.RANDOMS:
                             tracks = Lp().tracks.get_randoms()
                         else:
                             tracks = Lp().playlists.get_track_ids(
                                                                playlist_id)
                         for track_id in tracks:
                             if track_id not in track_ids:
                                 track_ids.append(track_id)
                         self.populate_user_playlist_by_tracks(track_ids,
                                                               pids)
                 else:
                     self._albums = load(open(
                                         DataPath + "/albums.bin",
                                         "rb"))
                     self.shuffle_albums(True)
                     self._context.genre_ids = load(open(
                                         DataPath + "/genre_ids.bin",
                                         "rb"))
                     self._context.artist_ids = load(open(
                                         DataPath + "/artist_ids.bin",
                                         "rb"))
                 self.set_next()
                 self.set_prev()
                 if Lp().settings.get_value('repeat'):
                     self._context.next = NextContext.NONE
                 else:
                     self._context.next = NextContext.STOP_ALL
             else:
                 print("Player::restore_state(): track missing")
     except Exception as e:
         print("Player::restore_state()", e)
示例#43
0
class TuneinPopover(Gtk.Popover):
    """
        Popover showing tunin radios
    """

    def __init__(self, radios_manager=None):
        """
            Init Popover
            @param radios_manager as Radios
        """
        Gtk.Popover.__init__(self)
        self._tunein = TuneIn()
        if radios_manager is not None:
            self._radios_manager = radios_manager
        else:
            self._radios_manager = Radios()
        self._current_url = None
        self._previous_urls = []

        self._stack = Gtk.Stack()
        self._stack.set_property('expand', True)
        self._stack.show()

        builder = Gtk.Builder()
        builder.add_from_resource('/org/gnome/Lollypop/TuneinPopover.ui')
        builder.connect_signals(self)
        widget = builder.get_object('widget')
        widget.attach(self._stack, 0, 2, 4, 1)

        self._back_btn = builder.get_object('back_btn')
        self._home_btn = builder.get_object('home_btn')
        self._label = builder.get_object('label')

        self._view = Gtk.FlowBox()
        self._view.set_selection_mode(Gtk.SelectionMode.NONE)
        self._view.set_max_children_per_line(100)
        self._view.set_property('row-spacing', 10)
        self._view.set_property('expand', True)
        self._view.show()

        builder.get_object('viewport').add(self._view)
        builder.get_object('viewport').set_property('margin', 10)

        self._scrolled = builder.get_object('scrolled')
        self._stack.add_named(builder.get_object('spinner'), 'spinner')
        self._stack.add_named(builder.get_object('notfound'), 'notfound')
        self._stack.add_named(self._scrolled, 'scrolled')
        self._stack.set_visible_child_name('spinner')
        self.add(widget)
        size_setting = Lp().settings.get_value('window-size')
        if isinstance(size_setting[1], int):
            self.set_size_request(700, size_setting[1]*0.7)
        else:
            self.set_size_request(700, 400)

    def populate(self, url=None):
        """
            Populate views
            @param url as string
        """
        if not self._view.get_children():
            self._current_url = url
            self._clear()
            self._back_btn.set_sensitive(False)
            self._home_btn.set_sensitive(False)
            self._label.set_text(_("Please wait..."))
            t = Thread(target=self._populate, args=(url,))
            t.daemon = True
            t.start()

#######################
# PRIVATE             #
#######################
    def _show_not_found(self):
        """
            Show not found message
        """
        self._label.set_text(_("Can't connect to TuneIn..."))
        self._stack.set_visible_child_name('notfound')
        self._home_btn.set_sensitive(True)

    def _populate(self, url):
        """
            Same as populate()
            @param url as string
            @thread safe
        """
        if url is None:
            items = self._tunein.get_items()
        else:
            items = self._tunein.get_items(url)

        if items:
            self._add_items(items)
        else:
            GLib.idle_add(self._show_not_found)

    def _add_items(self, items):
        """
            Add current items
            @param items as [TuneItem]
            @thread safe
        """
        for item in items:
            GLib.idle_add(self._add_item, item)

    def _add_item(self, item):
        """
            Add item
            @param item as TuneItem
        """
        child = Gtk.Grid()
        child.set_property('halign', Gtk.Align.START)
        child.show()
        link = Gtk.LinkButton.new_with_label(item.URL, item.TEXT)
        link.connect('activate-link', self._on_activate_link, item)
        link.show()
        if item.TYPE == "audio":
            link.set_tooltip_text(_("Play"))
            button = Gtk.Button.new_from_icon_name('list-add-symbolic',
                                                   Gtk.IconSize.MENU)
            button.connect('clicked', self._on_button_clicked, item)
            button.set_relief(Gtk.ReliefStyle.NONE)
            button.set_tooltip_text(_("Add"))
            button.show()
            child.add(button)
        else:
            link.set_tooltip_text('')
        child.add(link)

        self._view.add(child)

        # Remove spinner if exist
        if self._stack.get_visible_child_name() == 'spinner':
            self._stack.set_visible_child_name('scrolled')
            self._label.set_text(_("Browse themes and add a new radio"))
            if self._current_url is not None:
                self._back_btn.set_sensitive(True)
            self._home_btn.set_sensitive(True)

    def _clear(self):
        """
            Clear view
        """
        for child in self._view.get_children():
            self._view.remove(child)
            child.destroy()

    def _add_radio(self, item):
        """
            Add selected radio
            @param item as TuneIn Item
        """
        # Get cover art
        try:
            cache = Art._RADIOS_PATH
            s = Gio.File.new_for_uri(item.LOGO)
            d = Gio.File.new_for_path(cache+"/%s.png" %
                                      item.TEXT.replace('/', '-'))
            s.copy(d, Gio.FileCopyFlags.OVERWRITE, None, None)
        except Exception as e:
            print("TuneinPopover::_add_radio: %s" % e)
        url = item.URL
        # Tune in embbed uri in ashx files, so get content if possible
        try:
            f = Gio.File.new_for_uri(url)
            (status, data, tag) = f.load_contents()
            if status:
                url = data.decode('utf-8').split('\n')[0]
        except Exception as e:
            print("TuneinPopover::_add_radio: %s" % e)
        self._radios_manager.add(item.TEXT.replace('/', '-'), url)

    def _on_back_btn_clicked(self, btn):
        """
            Go to previous URL
            @param btn as Gtk.Button
        """
        url = None
        self._current_url = None
        if self._previous_urls:
            url = self._previous_urls.pop()
        self._stack.set_visible_child_name('spinner')
        self._clear()
        self.populate(url)

    def _on_home_btn_clicked(self, btn):
        """
            Go to root URL
            @param btn as Gtk.Button
        """
        self._current_url = None
        self._previous_urls = []
        self._stack.set_visible_child_name('spinner')
        self._clear()
        self.populate()

    def _on_activate_link(self, link, item):
        """
            Update header with new link
            @param link as Gtk.LinkButton
            @param item as TuneIn Item
        """
        if item.TYPE == "link":
            self._stack.set_visible_child_name('spinner')
            self._clear()
            self._scrolled.get_vadjustment().set_value(0.0)
            if self._current_url is not None:
                self._previous_urls.append(self._current_url)
            self.populate(item.URL)
        elif item.TYPE == "audio":
            # Only toolbar will get this one, so only create small in cache
            if Gio.NetworkMonitor.get_default().get_network_available():
                t = Thread(target=Lp().art.copy_uri_to_cache,
                           args=(item.LOGO, item.TEXT, ArtSize.SMALL))
                t.daemon = True
                t.start()
            Lp().player.load_external(item.URL, item.TEXT)
            Lp().player.play_this_external(item.URL)
        return True

    def _on_button_clicked(self, button, item):
        """
            Play the radio
            @param link as Gtk.Button
            @param item as TuneIn Item
        """
        t = Thread(target=self._add_radio, args=(item,))
        t.daemon = True
        t.start()
        self.hide()
示例#44
0
class TuneinPopover(Gtk.Popover):
    """
        Popover showing tunin radios
    """

    def __init__(self, radios_manager=None):
        """
            Init Popover
            @param radios_manager as Radios
        """
        Gtk.Popover.__init__(self)
        self._tunein = TuneIn()
        if radios_manager is not None:
            self._radios_manager = radios_manager
        else:
            self._radios_manager = Radios()
        self._current_url = None
        self._timeout_id = None
        self._previous_urls = []
        self._covers_to_download = []

        self._stack = Gtk.Stack()
        self._stack.set_property('expand', True)
        self._stack.show()

        builder = Gtk.Builder()
        builder.add_from_resource('/org/gnome/Lollypop/TuneinPopover.ui')
        builder.connect_signals(self)
        widget = builder.get_object('widget')
        widget.attach(self._stack, 0, 2, 5, 1)

        self._back_btn = builder.get_object('back_btn')
        self._home_btn = builder.get_object('home_btn')
        self._label = builder.get_object('label')

        self._view = Gtk.FlowBox()
        self._view.set_selection_mode(Gtk.SelectionMode.NONE)
        self._view.set_max_children_per_line(100)
        self._view.set_property('row-spacing', 10)
        self._view.set_property('expand', True)
        self._view.show()

        self._spinner = builder.get_object('spinner')

        builder.get_object('viewport').add(self._view)
        builder.get_object('viewport').set_property('margin', 10)

        self._scrolled = builder.get_object('scrolled')
        self._stack.add_named(self._spinner, 'spinner')
        self._stack.add_named(builder.get_object('notfound'), 'notfound')
        self._stack.add_named(self._scrolled, 'scrolled')
        self.add(widget)
        self.connect('map', self._on_map)
        self.connect('unmap', self._on_unmap)

    def populate(self, url=None):
        """
            Populate views
            @param url as string
        """
        if url is None and self._current_url is not None:
            return
        self._spinner.start()
        self._clear()
        self._stack.set_visible_child_name('spinner')
        self._current_url = url
        self._back_btn.set_sensitive(False)
        self._home_btn.set_sensitive(False)
        self._label.set_text(_("Please wait..."))
        t = Thread(target=self._populate, args=(url,))
        t.daemon = True
        t.start()

#######################
# PRIVATE             #
#######################
    def _show_not_found(self, message=""):
        """
            Show not found message
            @param message as str
        """
        # TODO Add a string
        self._label.set_text(message)
        self._stack.set_visible_child_name('notfound')
        self._home_btn.set_sensitive(True)

    def _populate(self, url):
        """
            Same as populate()
            @param url as string
            @thread safe
        """
        try:
            if url is None:
                items = self._tunein.get_items(
                                    "http://opml.radiotime.com/Browse.ashx?c=")
            else:
                items = self._tunein.get_items(url)

            if self._current_url == url:
                if items:
                    self._add_items(items, url)
                else:
                    GLib.idle_add(self._show_not_found)
        except:
            GLib.idle_add(self._show_not_found,
                          _("Can't connect to TuneIn..."))

    def _add_items(self, items, url):
        """
            Add current items
            @param items as [TuneItem]
            @parma url as str
            @thread safe
        """
        GLib.idle_add(self._add_item, items, url)

    def _add_item(self, items, url):
        """
            Add item
            @param items as [TuneItem]
            @param url as str
        """
        if url != self._current_url:
            return
        if not items:
            self._home_btn.set_sensitive(self._current_url is not None)
            t = Thread(target=self._download_images, args=(url,))
            t.daemon = True
            t.start()
            return
        item = items.pop(0)
        child = Gtk.Grid()
        child.set_column_spacing(5)
        child.set_property('halign', Gtk.Align.START)
        child.show()
        link = Gtk.LinkButton.new_with_label(item.URL, item.TEXT)
        # Hack
        link.get_children()[0].set_ellipsize(Pango.EllipsizeMode.END)
        link.connect('activate-link', self._on_activate_link, item)
        link.show()
        if item.TYPE == "audio":
            link.set_tooltip_text(_("Play"))
            button = Gtk.Button.new_from_icon_name('list-add-symbolic',
                                                   Gtk.IconSize.MENU)
            button.connect('clicked', self._on_button_clicked, item)
            button.set_relief(Gtk.ReliefStyle.NONE)
            button.set_property('valign', Gtk.Align.CENTER)
            button.set_tooltip_text(_("Add"))
            button.show()
            child.add(button)
            image = Gtk.Image.new()
            image.set_property('width-request', ArtSize.MEDIUM)
            image.set_property('height-request', ArtSize.MEDIUM)
            image.show()
            child.add(image)
            self._covers_to_download.append((item, image))
        else:
            link.set_tooltip_text('')
        child.add(link)

        self._view.add(child)

        # Remove spinner if exist
        if self._stack.get_visible_child_name() == 'spinner':
            self._stack.set_visible_child_name('scrolled')
            self._spinner.stop()
            self._label.set_text("")
            if self._current_url is not None:
                self._back_btn.set_sensitive(True)
        GLib.idle_add(self._add_items, items, url)

    def _download_images(self, url):
        """
            Download and set image for TuneItem
            @param url as str
            @thread safe
        """
        while self._covers_to_download and url == self._current_url:
            (item, image) = self._covers_to_download.pop(0)
            try:
                f = Gio.File.new_for_uri(item.LOGO)
                (status, data, tag) = f.load_contents()
                if status:
                    stream = Gio.MemoryInputStream.new_from_data(data, None)
                    if stream is not None:
                        GLib.idle_add(self._set_image, image, stream)
            except Exception as e:
                GLib.idle_add(image.set_from_icon_name,
                              "image-missing",
                              Gtk.IconSize.LARGE_TOOLBAR)
                print("TuneinPopover::_download_images: %s" % e)

    def _set_image(self, image, stream):
        """
            Set image with stream
            @param image as Gtk.Image
            @param stream as Gio.MemoryInputStream
        """
        pixbuf = GdkPixbuf.Pixbuf.new_from_stream_at_scale(stream,
                                                           ArtSize.MEDIUM,
                                                           ArtSize.MEDIUM,
                                                           True,
                                                           None)
        surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf,
                                                       0,
                                                       None)
        del pixbuf
        image.set_from_surface(surface)
        del surface

    def _clear(self):
        """
            Clear view
        """
        for child in self._view.get_children():
            self._view.remove(child)
            child.destroy()

    def _add_radio(self, item):
        """
            Add selected radio
            @param item as TuneIn Item
        """
        # Get cover art
        try:
            cache = Art._RADIOS_PATH
            s = Gio.File.new_for_uri(item.LOGO)
            d = Gio.File.new_for_path(cache+"/%s.png" %
                                      item.TEXT.replace('/', '-'))
            s.copy(d, Gio.FileCopyFlags.OVERWRITE, None, None)
        except Exception as e:
            print("TuneinPopover::_add_radio: %s" % e)
        url = item.URL
        # Tune in embbed uri in ashx files, so get content if possible
        try:
            f = Gio.File.new_for_uri(url)
            (status, data, tag) = f.load_contents()
            if status:
                url = data.decode('utf-8').split('\n')[0]
        except Exception as e:
            print("TuneinPopover::_add_radio: %s" % e)
        self._radios_manager.add(item.TEXT.replace('/', '-'), url)

    def _on_map(self, widget):
        """
            Resize and disable global shortcuts
            @param widget as Gtk.Widget
        """
        # FIXME Not needed with GTK >= 3.18
        Lp().window.enable_global_shorcuts(False)
        size = Lp().window.get_size()
        self.set_size_request(size[0]*0.5, size[1]*0.7)

    def _on_unmap(self, widget):
        """
            Enable global shorcuts
            @param widget as Gtk.Widget
        """
        # FIXME Not needed with GTK >= 3.18
        Lp().window.enable_global_shorcuts(True)

    def _on_back_btn_clicked(self, btn):
        """
            Go to previous URL
            @param btn as Gtk.Button
        """
        url = None
        self._current_url = None
        if self._previous_urls:
            url = self._previous_urls.pop()
        self._stack.set_visible_child_name('spinner')
        self._spinner.start()
        self._clear()
        self.populate(url)

    def _on_home_btn_clicked(self, btn):
        """
            Go to root URL
            @param btn as Gtk.Button
        """
        self._current_url = None
        self._previous_urls = []
        self.populate()

    def _on_activate_link(self, link, item):
        """
            Update header with new link
            @param link as Gtk.LinkButton
            @param item as TuneIn Item
        """
        if item.TYPE == "link":
            self._scrolled.get_vadjustment().set_value(0.0)
            if self._current_url is not None:
                self._previous_urls.append(self._current_url)
            self.populate(item.URL)
        elif item.TYPE == "audio":
            # Only toolbar will get this one, so only create small in cache
            if Gio.NetworkMonitor.get_default().get_network_available():
                t = Thread(target=Lp().art.copy_uri_to_cache,
                           args=(item.LOGO, item.TEXT,
                                 Lp().window.toolbar.artsize))
                t.daemon = True
                t.start()
                t = Thread(target=Lp().art.copy_uri_to_cache,
                           args=(item.LOGO, item.TEXT,
                                 ArtSize.BIG))
                t.daemon = True
                t.start()
            Lp().player.load_external(item.URL, item.TEXT)
            Lp().player.play_this_external(item.URL)
        return True

    def _on_button_clicked(self, button, item):
        """
            Play the radio
            @param link as Gtk.Button
            @param item as TuneIn Item
        """
        self._timeout_id = None
        t = Thread(target=self._add_radio, args=(item,))
        t.daemon = True
        t.start()
        self.hide()

    def _on_search_changed(self, widget):
        """
            Timeout filtering, call _really_do_filterting()
            after timeout
            @param widget as Gtk.TextEntry
        """
        self._current_url = None
        if self._timeout_id is not None:
            GLib.source_remove(self._timeout_id)
            self._timeout_id = None

        text = widget.get_text()
        if text != "":
            self._home_btn.set_sensitive(True)
            self._timeout_id = GLib.timeout_add(1000,
                                                self._on_search_timeout,
                                                text)
        else:
            self._home_btn.set_sensitive(False)
            self._timeout_id = GLib.timeout_add(1000,
                                                self._on_home_btn_clicked,
                                                None)

    def _on_search_timeout(self, string):
        """
            Populate widget
            @param string as str
        """
        self._timeout_id = None
        url = "http://opml.radiotime.com/Search.ashx?query=%s" % escape(string)
        self.populate(url)
示例#45
0
class RadiosView(View):
    """
        Show radios in a grid
    """

    def __init__(self):
        """
            Init view
        """
        View.__init__(self)
        self._signal = Lp().art.connect('radio-artwork-changed',
                                        self._on_logo_changed)

        self._radios_manager = Radios()
        self._radios_manager.connect('radios-changed',
                                     self._on_radios_changed)
        builder = Gtk.Builder()
        builder.add_from_resource('/org/gnome/Lollypop/RadiosView.ui')
        builder.connect_signals(self)
        widget = builder.get_object('widget')
        self._empty = builder.get_object('empty')

        self._pop_tunein = TuneinPopover(self._radios_manager)
        self._pop_tunein.set_relative_to(builder.get_object('search_btn'))

        self._sizegroup = Gtk.SizeGroup(mode=Gtk.SizeGroupMode.BOTH)

        self._radiobox = Gtk.FlowBox()
        self._radiobox.set_selection_mode(Gtk.SelectionMode.NONE)
        self._radiobox.connect("child-activated", self._on_album_activated)
        self._radiobox.set_property('column-spacing', 5)
        self._radiobox.set_property('row-spacing', 5)
        self._radiobox.set_homogeneous(True)
        self._radiobox.set_max_children_per_line(1000)
        self._radiobox.show()

        self._stack = Gtk.Stack()
        self._stack.set_transition_duration(500)
        self._stack.set_transition_type(Gtk.StackTransitionType.CROSSFADE)
        self._stack.add(self._scrolled)
        self._stack.add(self._empty)
        self._stack.show()

        self._viewport.set_property("valign", Gtk.Align.START)
        self._viewport.set_property('margin', 5)
        self._viewport.add(self._radiobox)
        self._scrolled.set_property('expand', True)

        self.add(widget)
        self.add(self._stack)

    def populate(self):
        """
            Populate view with tracks from playlist
            Thread safe
        """
        Lp().player.set_radios(self._radios_manager.get())
        if Lp().player.current_track.id == Type.RADIOS:
            Lp().player.set_next()  # We force next update
            Lp().player.set_prev()  # We force prev update
        t = Thread(target=self._populate)
        t.daemon = True
        t.start()

#######################
# PRIVATE             #
#######################
    def _populate(self):
        """
            Populate view with tracks from playlist
            Thread safe
        """
        radios = []
        # Get radios name
        for (name, url) in self._radios_manager.get():
            radios.append(name)
        GLib.idle_add(self._show_stack, radios)

    def _get_children(self):
        """
            Return view children
            @return [RadioWidget]
        """
        children = []
        for child in self._radiobox.get_children():
            widget = child.get_child()
            children.append(widget)
        return children

    def _on_destroy(self, widget):
        """
            Disconnect signals
            @param widget as Gtk.Widget
        """
        if self._signal is not None:
            Lp().art.disconnect(self._signal)

    def _on_new_clicked(self, widget):
        """
            Show popover for adding a new radio
            @param widget as Gtk.Widget
        """
        popover = RadioPopover('', self._radios_manager)
        popover.set_relative_to(widget)
        popover.show()

    def _on_search_clicked(self, widget):
        """
            Show popover for searching radios
            @param widget as Gtk.Widget
        """
        self._pop_tunein.populate()
        self._pop_tunein.show()

    def _on_radios_changed(self, manager):
        """
            Update radios
            @param manager as PlaylistManager
        """
        radios_name = []
        currents = []
        new_name = None
        old_widget = None
        old_child = None

        # Get radios name
        for (name, url) in manager.get():
            radios_name.append(name)

        # Get currents widget less removed
        for child in self._radiobox.get_children():
            widget = child.get_child()
            if widget.get_name() not in radios_name:
                old_widget = widget
                old_child = child
            else:
                currents.append(widget.get_name())

        # Add the new radio
        for name in radios_name:
            if name not in currents:
                new_name = name
                break

        # Rename widget
        if new_name is not None:
            if old_widget is not None:
                old_widget.set_name(new_name)
            else:
                radios = [new_name]
                self._show_stack(radios)
        # Delete widget
        elif old_widget is not None:
            self._radiobox.remove(old_child)
            old_widget.destroy()
            if not self._radiobox.get_children():
                self._show_stack([])

        # Update player state based on current view
        radios = []
        for child in self._radiobox.get_children():
            widget = child.get_child()
            name = widget.get_name()
            url = manager.get_url(name)
            radios.append((name, url))
        Lp().player.set_radios(radios)
        if Lp().player.current_track.id == Type.RADIOS:
            Lp().player.set_next()  # We force next update
            Lp().player.set_prev()  # We force prev update

    def _on_logo_changed(self, player, name):
        """
            Update radio logo
            @param player as Plyaer
            @param name as string
        """
        for child in self._radiobox.get_children():
            widget = child.get_child()
            if widget.get_name() == name:
                widget.update_cover()

    def _show_stack(self, radios):
        """
            Switch empty/radios view based on radios
            @param [radio names as string]
        """
        if radios:
            self._stack.set_visible_child(self._scrolled)
            self._add_radios(radios, True)
        else:
            self._stack.set_visible_child(self._empty)

    def _add_radios(self, radios, first=False):
        """
            Pop a radio and add it to the view,
            repeat operation until radio list is empty
            @param [radio names as string]
            @param first as bool
        """
        if radios and not self._stop:
            radio = radios.pop(0)
            widget = RadioWidget(radio,
                                 self._radios_manager)
            widget.show()
            self._sizegroup.add_widget(widget)
            if first:
                self._radiobox.insert(widget, 0)
            else:
                self._radiobox.insert(widget, -1)
            GLib.idle_add(self._add_radios, radios)
        else:
            self._stop = False
        return None

    def _on_album_activated(self, flowbox, child):
        """
            Play album
            @param flowbox as Gtk.Flowbox
            @child as Gtk.FlowboxChild
        """
        name = child.get_child().get_name()
        url = self._radios_manager.get_url(name)
        if url:
            track = Track()
            track.set_radio(name, url)
            Lp().player.load(track)