Example #1
0
    def __init__(self, exaile, username, password):

        self.doubanfm = DoubanRadio(username, password)
        self.exaile = exaile
        self.__create_menu_item__()

        self.__register_events()
        self.doubanfm_mode = DoubanfmMode(self.exaile, self)
Example #2
0
    def __init__(self, exaile, username ,password):
        
        self.doubanfm = DoubanRadio(username, password)
        self.exaile = exaile
        self.__create_menu_item__()

        self.__register_events()
        self.doubanfm_mode = DoubanfmMode(self.exaile, self)
Example #3
0
class DoubanRadioPlugin(object):
    channels = {
        _('Personalized'): 0,
        _('Mandarin'): 1,
        _('Western'): 2,
        _('Cantonese'): 6,
        _('70s'): 3,
        _('80s'): 4,
        _('90s'): 5
    }

    @common.threaded
    def __init__(self, exaile, username, password):

        self.doubanfm = DoubanRadio(username, password)
        self.exaile = exaile
        self.__create_menu_item__()

        self.__register_events()
        self.doubanfm_mode = DoubanfmMode(self.exaile, self)

    def __register_events(self):
        event.add_callback(self.check_to_load_more, 'playback_player_start')
        event.add_callback(self.close_playlist, 'quit_application')
        event.add_callback(self.play_feedback, 'playlist_current_changed')
        event.add_callback(self.user_feedback, 'doubanfm_track_rating_change')

    def __unregister_events(self):
        event.remove_callback(self.check_to_load_more, 'playback_player_start')
        event.remove_callback(self.close_playlist, 'quit_application')
        event.remove_callback(self.play_feedback, 'playlist_current_changed')
        event.remove_callback(self.user_feedback,
                              'doubanfm_track_rating_change')

    def user_feedback(self, type, track, rating_pair):
        prev_rating, rating = rating_pair
        if rating == 1:
            ## mark to recycle
            self.mark_as_recycle(track)
        if rating == 2 and prev_rating != 2:
            self.mark_as_skip(track)
        if prev_rating == 5 and rating < 5:
            ## mark to dislike
            self.mark_as_dislike(track)
        if rating == 5 and prev_rating < 5:
            ## mark to like
            self.mark_as_like(track)

    def is_douban_track(self, track):
        return isinstance(track, DoubanFMTrack)

    @common.threaded
    def mark_as_skip(self, track):
        playlist = self.get_current_playlist()

        rest_sids = self.get_rest_sids(playlist)

        ## play next song
        self.exaile.gui.main.queue.next()

        sid = track.sid
        aid = track.aid
        songs = self.doubanfm.skip_song(
            sid, aid, history=self.get_history_sids(playlist))
        if self.get_tracks_remain() < 15:
            tracks = map(self.create_track_from_douban_song, songs)

            playlist.add_tracks(tracks)
        track.set_rating2(2)

    @common.threaded
    def mark_as_like(self, track):
        sid = track.sid
        aid = track.aid
        self.doubanfm.fav_song(sid, aid)
        track.set_rating2(5)

    @common.threaded
    def mark_as_dislike(self, track):
        sid = track.sid
        aid = track.aid

        self.doubanfm.unfav_song(sid, aid)
        track.set_rating2(3)

    @common.threaded
    def mark_as_recycle(self, track):
        playlist = self.get_current_playlist()

        rest_sids = self.get_rest_sids(playlist)

        ## play next song
        self.exaile.gui.main.queue.next()

        ## remove the track
        self.remove_current_track()

        sid = track.sid
        aid = track.aid
        songs = self.doubanfm.del_song(sid, aid, rest=rest_sids)
        if self.get_tracks_remain() < 15:
            tracks = map(self.create_track_from_douban_song, songs)

            playlist.add_tracks(tracks)
        track.set_rating2(1)

    def get_rest_sids(self, playlist):
        playlist = self.get_current_playlist()

        current_tracks = playlist.get_tracks()
        rest_tracks = current_tracks[playlist.get_current_pos() + 1:]
        rest_sids = self.tracks_to_sids(rest_tracks)
        return rest_sids

    def get_tracks_remain(self):
        pl = self.exaile.gui.main.get_current_playlist().playlist
        total = len(pl.get_tracks())
        cursor = pl.get_current_pos()
        return total - cursor

    def get_selected_track(self):
        self.exaile.gui.main.get_current_playlist().get_selected_track()

    def get_current_track(self):
        pl = self.exaile.gui.main.get_current_playlist().playlist
        return pl.get_tracks()[pl.get_current_pos()]

    def remove_current_track(self):
        self.exaile.gui.main.get_current_playlist().remove_selected_tracks()

    def tracks_to_sids(self, tracks):
        return map(lambda t: t.sid, tracks)

    @common.threaded
    def play_feedback(self, type, playlist, current_track):
        if isinstance(playlist, DoubanFMPlaylist) and isinstance(
                self.last_track, DoubanFMTrack):
            track = self.last_track
            sid = track.sid
            aid = track.aid
            if sid is not None and aid is not None:
                self.doubanfm.played_song(sid, aid)
            self.last_track = current_track

    def get_current_playlist(self):
        return self.exaile.gui.main.get_selected_playlist().playlist

    def close_playlist(self, type, exaile, data=None):
        removed = 0
        for i, page in enumerate(exaile.gui.main.playlist_notebook):
            if isinstance(page.playlist, DoubanFMPlaylist):
                exaile.gui.main.close_playlist_tab(i - removed)
                removed += 1

    def check_to_load_more(self, type, player, track):
        playlist = self.get_current_playlist()
        if isinstance(playlist, DoubanFMPlaylist):
            ## check if last one
            if playlist.index(track) == len(playlist.get_tracks()) - 1:
                self.load_more(playlist)

    def get_history_sids(self, playlist):
        current_tracks = playlist.get_ordered_tracks()
        sids = self.tracks_to_sids(current_tracks)
        return sids

    def load_more(self, playlist):
        sids = self.get_history_sids(playlist)
        retry = 0
        while retry < 3:
            try:
                songs = self.doubanfm.played_list(sids)
            except:
                retry += 1
                continue

            if len(songs) > 0:
                tracks = map(self.create_track_from_douban_song, songs)
                playlist.add_tracks(tracks)
                break
            else:
                retry += 1

    def __create_menu_item__(self):
        exaile = self.exaile

        self.menuItem = gtk.MenuItem(_('Open Douban.fm'))
        menu = gtk.Menu()
        self.menuItem.set_submenu(menu)

        for channel_name in self.channels.keys():
            menuItem = gtk.MenuItem(_(channel_name))

            menuItem.connect('activate', self.active_douban_radio,
                             channel_name)

            menu.prepend(menuItem)
            menuItem.show()

#       self.menu.connect('activate', self.active_douban_radio, self.exaile)

        exaile.gui.builder.get_object('file_menu').insert(self.menuItem, 5)

        self.menuItem.show()

        self.modeMenuItem = gtk.MenuItem(_('DoubanFM mode'))
        key, modifier = gtk.accelerator_parse('<Control><Alt>D')
        self.accels = gtk.AccelGroup()
        self.modeMenuItem.add_accelerator('activate', self.accels, key,
                                          modifier, gtk.ACCEL_VISIBLE)
        self.exaile.gui.main.window.add_accel_group(self.accels)
        self.modeMenuItem.connect('activate', self.show_mode)
        exaile.gui.builder.get_object('view_menu').append(self.modeMenuItem)
        self.modeMenuItem.show()

    def create_track_from_douban_song(self, song):
        uri = song['url']

        track = DoubanFMTrack(uri, song['sid'], song['aid'], song['like'])
        track.set_tag_raw('title', song['title'])
        track.set_tag_raw('artist', song['artist'])
        track.set_tag_raw('album', song['albumtitle'])
        track.set_tag_raw('cover_url', song['picture'])

        return track

    def show_mode(self, *e):
        self.doubanfm_mode.show()

    def create_playlist(self, name, initial_tracks=[]):
        ## to update in 0.3.2
        ## plist = DoubanFMPlaylist(name, initial_tracks)
        plist = DoubanFMPlaylist(name)
        plist.set_ordered_tracks(initial_tracks)

        ## set_shuffle_mode('disabled')
        plist.set_random(False)
        ## set_repeat_mode('disabled')
        plist.set_repeat(False)
        ## set_dynamic_mode('disabled')
        plist.set_dynamic(False)

        return plist

    def active_douban_radio(self, type, channel_name):
        channel_id = self.channels[channel_name]

        self.doubanfm.set_channel(channel_id)
        try:
            songs = self.doubanfm.new_playlist()
        except:
            dialog = gtk.MessageDialog(
                self.exaile.gui.main.window, 0, gtk.MESSAGE_ERROR,
                gtk.BUTTONS_OK, _('Failed to retrieve playlist, try again.'))
            dialog.run()
            dialog.destroy()
            return

        tracks = map(self.create_track_from_douban_song, songs)
        plist = self.create_playlist(
            _('DoubanFM') + " " + channel_name, tracks)

        self.exaile.gui.main.add_playlist(plist)
        #       self.play(plist)

        self.last_track = plist.get_ordered_tracks()[0]


#       self.doubanfm_mode.show()

    def destroy(self, exaile):
        if self.menuItem:
            exaile.gui.builder.get_object('file_menu').remove(self.menuItem)
        if self.modeMenuItem:
            exaile.gui.builder.get_object('view_menu').remove(
                self.modeMenuItem)
            exaile.gui.main.remove_accel_group(self.accels)
        self.__unregister_events()

        self.doubanfm_mode.destroy()
        pass
Example #4
0
class DoubanRadioPlugin(object):
    channels = {_('Personalized'):0, _('Mandarin'):1, _('Western'):2, 
            _('Cantonese'): 6, _('70s'): 3, _('80s'): 4, _('90s'): 5}

    @common.threaded
    def __init__(self, exaile, username ,password):
        
        self.doubanfm = DoubanRadio(username, password)
        self.exaile = exaile
        self.__create_menu_item__()

        self.__register_events()
        self.doubanfm_mode = DoubanfmMode(self.exaile, self)


    def __register_events(self):
        event.add_callback(self.check_to_load_more, 'playback_player_start')
        event.add_callback(self.close_playlist, 'quit_application')
        event.add_callback(self.play_feedback, 'playlist_current_changed')
        event.add_callback(self.user_feedback, 'doubanfm_track_rating_change')

    def __unregister_events(self):
        event.remove_callback(self.check_to_load_more, 'playback_player_start')
        event.remove_callback(self.close_playlist, 'quit_application')
        event.remove_callback(self.play_feedback, 'playlist_current_changed')
        event.remove_callback(self.user_feedback, 'doubanfm_track_rating_change')

    def user_feedback(self, type, track, rating_pair) :
        prev_rating, rating = rating_pair
        if rating == 1:
            ## mark to recycle
            self.mark_as_recycle(track)
        if rating == 2 and prev_rating != 2:
            self.mark_as_skip(track)
        if prev_rating == 5 and rating < 5:
            ## mark to dislike
            self.mark_as_dislike(track)
        if rating == 5 and prev_rating < 5:
            ## mark to like
            self.mark_as_like(track)

    def is_douban_track(self, track):
        return isinstance(track, DoubanFMTrack)

    @common.threaded
    def mark_as_skip(self, track):
        playlist = self.get_current_playlist()

        rest_sids = self.get_rest_sids(playlist)

        ## play next song
        self.exaile.gui.main.queue.next()

        sid = track.sid
        aid = track.aid
        songs = self.doubanfm.skip_song(sid, aid, history=self.get_history_sids(playlist))
        if self.get_tracks_remain() < 15:
            tracks = map(self.create_track_from_douban_song, songs)

            playlist.add_tracks(tracks)
        track.set_rating2(2)

    @common.threaded
    def mark_as_like(self, track):
        sid = track.sid
        aid = track.aid
        self.doubanfm.fav_song(sid, aid)
        track.set_rating2(5)

    @common.threaded
    def mark_as_dislike(self, track):
        sid = track.sid
        aid = track.aid

        self.doubanfm.unfav_song(sid, aid)
        track.set_rating2(3)

    @common.threaded
    def mark_as_recycle(self, track):
        playlist = self.get_current_playlist()

        rest_sids = self.get_rest_sids(playlist)

        ## play next song
        self.exaile.gui.main.queue.next()

        ## remove the track
        self.remove_current_track()

        sid = track.sid
        aid = track.aid
        songs = self.doubanfm.del_song(sid, aid, rest=rest_sids)
        if self.get_tracks_remain() < 15:
            tracks = map(self.create_track_from_douban_song, songs)

            playlist.add_tracks(tracks)
        track.set_rating2(1)

    def get_rest_sids(self, playlist):
        playlist = self.get_current_playlist()

        current_tracks = playlist.get_tracks()
        rest_tracks = current_tracks[playlist.get_current_pos()+1:]
        rest_sids = self.tracks_to_sids(rest_tracks)
        return rest_sids

    def get_tracks_remain(self):
        pl = self.exaile.gui.main.get_current_playlist().playlist
        total = len(pl.get_tracks())
        cursor = pl.get_current_pos()
        return total-cursor

    def get_selected_track(self):
        self.exaile.gui.main.get_current_playlist().get_selected_track()

    def get_current_track(self):
        pl = self.exaile.gui.main.get_current_playlist().playlist
        return pl.get_tracks()[pl.get_current_pos()]

    def remove_current_track(self):
        self.exaile.gui.main.get_current_playlist().remove_selected_tracks()

    def tracks_to_sids(self, tracks):
        return map(lambda t: t.sid, tracks)

    @common.threaded
    def play_feedback(self, type, playlist, current_track):
        if isinstance(playlist, DoubanFMPlaylist) and isinstance(self.last_track, DoubanFMTrack):
            track = self.last_track
            sid = track.sid
            aid = track.aid
            if sid is not None and aid is not None:
                self.doubanfm.played_song(sid, aid)
            self.last_track = current_track

    def get_current_playlist(self):
        return self.exaile.gui.main.get_selected_playlist().playlist

    def close_playlist(self, type, exaile, data=None):
        removed = 0
        for i,page in enumerate(exaile.gui.main.playlist_notebook):
            if isinstance(page.playlist, DoubanFMPlaylist):
                exaile.gui.main.close_playlist_tab(i-removed)
                removed += 1

    def check_to_load_more(self, type, player, track):
        playlist = self.get_current_playlist()
        if isinstance(playlist, DoubanFMPlaylist):
            ## check if last one
            if playlist.index(track) == len(playlist.get_tracks())-1:
                self.load_more(playlist)

    def get_history_sids(self, playlist):
        current_tracks = playlist.get_ordered_tracks()
        sids = self.tracks_to_sids(current_tracks)
        return sids

    def load_more(self, playlist):
        sids = self.get_history_sids(playlist)
        retry = 0
        while retry < 3:
            try:
                songs = self.doubanfm.played_list(sids)
            except:
                retry += 1
                continue
            
            if len(songs) > 0:
                tracks = map(self.create_track_from_douban_song, songs)
                playlist.add_tracks(tracks)
                break
            else:
                retry += 1

    def __create_menu_item__(self):
        exaile = self.exaile
        
        self.menuItem = gtk.MenuItem(_('Open Douban.fm'))
        menu = gtk.Menu()
        self.menuItem.set_submenu(menu)

        for channel_name  in self.channels.keys():
            menuItem = gtk.MenuItem(_(channel_name))

            menuItem.connect('activate', self.active_douban_radio, channel_name)
            
            menu.prepend(menuItem)
            menuItem.show()

#       self.menu.connect('activate', self.active_douban_radio, self.exaile)

        exaile.gui.builder.get_object('file_menu').insert(self.menuItem, 5)

        self.menuItem.show()

        self.modeMenuItem = gtk.MenuItem(_('DoubanFM mode'))
        key, modifier = gtk.accelerator_parse('<Control><Alt>D')
        self.accels = gtk.AccelGroup()
        self.modeMenuItem.add_accelerator('activate', self.accels, key, modifier, gtk.ACCEL_VISIBLE)
        self.exaile.gui.main.window.add_accel_group(self.accels)
        self.modeMenuItem.connect('activate', self.show_mode)
        exaile.gui.builder.get_object('view_menu').append(self.modeMenuItem)
        self.modeMenuItem.show()
    
    def create_track_from_douban_song(self, song):
        uri = song['url']

        track = DoubanFMTrack(uri, song['sid'], song['aid'], song['like'])
        track.set_tag_raw('title', song['title'])
        track.set_tag_raw('artist', song['artist'])
        track.set_tag_raw('album', song['albumtitle'])
        track.set_tag_raw('cover_url', song['picture'])

        return track

    def show_mode(self, *e):
        self.doubanfm_mode.show()

    def create_playlist(self, name, initial_tracks=[]):
        ## to update in 0.3.2 
        ## plist = DoubanFMPlaylist(name, initial_tracks)
        plist = DoubanFMPlaylist(name)
        plist.set_ordered_tracks(initial_tracks)

        ## set_shuffle_mode('disabled')
        plist.set_random(False)
        ## set_repeat_mode('disabled')
        plist.set_repeat(False)
        ## set_dynamic_mode('disabled')
        plist.set_dynamic(False)

        return plist

    def active_douban_radio(self, type, channel_name):
        channel_id = self.channels[channel_name]    

        self.doubanfm.set_channel(channel_id)
        try:
            songs = self.doubanfm.new_playlist()
        except:
            dialog = gtk.MessageDialog(self.exaile.gui.main.window, 0,
                    gtk.MESSAGE_ERROR, gtk.BUTTONS_OK,
                    _('Failed to retrieve playlist, try again.'))
            dialog.run()
            dialog.destroy()
            return

        tracks = map(self.create_track_from_douban_song, songs)
        plist = self.create_playlist(
                _('DoubanFM')+" "+channel_name, tracks)
        
        self.exaile.gui.main.add_playlist(plist)
#       self.play(plist)

        self.last_track = plist.get_ordered_tracks()[0]

#       self.doubanfm_mode.show()

    def destroy(self, exaile):
        if self.menuItem :
            exaile.gui.builder.get_object('file_menu').remove(self.menuItem)
        if self.modeMenuItem:
            exaile.gui.builder.get_object('view_menu').remove(self.modeMenuItem)
            exaile.gui.main.remove_accel_group(self.accels)
        self.__unregister_events()

        self.doubanfm_mode.destroy()
        pass