def _setup_api_tools(self): # Init API tools self.player = Player() self.douban = Douban(self.email, self.password, self.user_id, self.expire, self.token, self.user_name, self.cookies) # Try to login if self.last_fm_username is None or self.last_fm_username == "": self.scrobbling = False if (self.email is None or self.email == "") and self.cookies == None: self.douban_account = False if self.scrobbling: self.scrobbler = Scrobbler(self.last_fm_username, self.last_fm_password) r, err = self.scrobbler.handshake() if r: logger.debug("Last.fm logged in.") else: print("Last.FM 登录失败: " + err) if self.douban_account: r, err = self.douban.do_login() if r: logger.debug("Douban logged in") else: print("Douban 登录失败: " + err) # Refresh account cache self.config.save_account_cache(self.douban.user_name, self.douban.user_id, self.douban.expire, self.douban.token, self.douban.cookies, self.last_fm_username, self.last_fm_password)
def _setup_api_tools(self): # Init API tools self.player = Player() self.douban = Douban( self.email, self.password, self.user_id, self.expire, self.token, self.user_name, self.cookies) # Try to login if self.last_fm_username is None or self.last_fm_username == "": self.scrobbling = False if (self.email is None or self.email == "") and self.cookies == None: self.douban_account = False if self.scrobbling: self.scrobbler = Scrobbler( self.last_fm_username, self.last_fm_password) r, err = self.scrobbler.handshake() if r: logger.debug("Last.fm logged in.") else: print("Last.FM 登录失败: " + err) self.scrobbling = False if self.douban_account: r, err = self.douban.do_login() if r: logger.debug("Douban logged in") else: print("Douban 登录失败: " + err) self.douban_account = False # Refresh account cache self.config.save_account_cache(self.douban.user_name, self.douban.user_id, self.douban.expire, self.douban.token, self.douban.cookies, self.last_fm_username, self.last_fm_password)
class Doubanfm(object): def __init__(self): self.douban = None self.player = None self.config = None self.scrobbler = None self.channels = None self.current_channel = 0 self.current_song = None self.current_play_list = None self._setup_config() self._setup_api_tools() self._setup_ui() self._setup_signals() def _setup_config(self): self.config = Config() # Set up config try: arg = sys.argv[1] self.config.do_config() except IndexError: self.config.load_config() def _setup_api_tools(self): # Init API tools self.player = Player() self.douban = Douban( self.email, self.password, self.user_id, self.expire, self.token, self.user_name, self.cookies) # Try to login if self.last_fm_username is None or self.last_fm_username == "": self.scrobbling = False if (self.email is None or self.email == "") and self.cookies == None: self.douban_account = False if self.scrobbling: self.scrobbler = Scrobbler( self.last_fm_username, self.last_fm_password) r, err = self.scrobbler.handshake() if r: logger.debug("Last.fm logged in.") else: print("Last.FM 登录失败: " + err) self.scrobbling = False if self.douban_account: r, err = self.douban.do_login() if r: logger.debug("Douban logged in") else: print("Douban 登录失败: " + err) self.douban_account = False # Refresh account cache self.config.save_account_cache(self.douban.user_name, self.douban.user_id, self.douban.expire, self.douban.token, self.douban.cookies, self.last_fm_username, self.last_fm_password) def _setup_ui(self): # Init terminal ui self.palette = [('selected', 'bold', 'default'), ('title', 'yellow', 'default')] self.selected_button = None self.main_loop = None self.song_change_alarm = None self.get_channels() title = '豆瓣FM' + ' '*32 if self.douban_account: title += '豆瓣已登录' else: title += '豆瓣未登陆' title += ' '*3 if self.scrobbling: title += 'Last.fm 已登录' else: title += 'Last.fm 未登录' self.title = urwid.AttrMap(urwid.Text(title), 'title') self.divider = urwid.Divider() self.pile = urwid.Padding( urwid.Pile([self.divider, self.title, self.divider]), left=4, right=4) self.channel_list_box = self.getChannelListBox() self.box = urwid.Padding(self.channel_list_box, left=2, right=4) self.frame = urwid.Frame( self.box, header=self.pile, footer=self.divider) self.main_loop = urwid.MainLoop( self.frame, self.palette, handle_mouse=False) # Cache the channel list self.config.save_channel_cache(self.channels) def _setup_signals(self): urwid.register_signal( ChannelListBox, ['exit', 'skip', 'rate', 'trash']) urwid.connect_signal(self.channel_list_box, 'exit', self.on_exit) urwid.connect_signal(self.channel_list_box, 'skip', self.on_skip) urwid.connect_signal( self.channel_list_box, 'rate', self.on_rate_and_unrate) urwid.connect_signal(self.channel_list_box, 'trash', self.on_trash) def __getattr__(self, name): try: return self.__dict__[name] except KeyError: return self.config.__dict__[name] def get_channels(self): if self.channels is None: try: self.channels = self.cached_channels except KeyError: self.channels = deque(self.douban.get_channels()) def _choose_channel(self, channel): self.current_channel = channel self.current_play_list = deque( self.douban.get_new_play_list(self.current_channel)) def _play_track(self): _song = self.current_play_list.popleft() self.current_song = Song(_song) # Post notification Notifier.notify("", self.current_song.song_title, self.current_song.artist + ' — ' + self.current_song.album_title, appIcon=self.current_song.picture, open_URL=self.current_song.album) logger.debug( '{0} tracks remaining in the playlist'.format(len(self.current_play_list))) self.song_change_alarm = self.main_loop.set_alarm_in(self.current_song.length_in_sec, self.next_song, None) self.selected_button.set_text(self.selected_button.text[0:11].strip()) heart = WHITE_HEART if self.current_song.like: heart = BLACK_HEART if not self.douban_account: heart = ' ' self.selected_button.set_text(self.selected_button.text + ' ' + heart + ' ' + self.current_song.artist + ' - ' + self.current_song.song_title) if self.scrobbling: self.scrobbler.now_playing(self.current_song.artist, self.current_song.song_title, self.current_song.album_title, self.current_song.length_in_sec) self.player.stop() self.player.play(self.current_song) # Currently playing the second last song in queue if len(self.current_play_list) == 1: # Extend the playing list playing_list = self.douban.get_playing_list( self.current_song.sid, self.current_channel) logger.debug('Got {0} more tracks'.format(len(playing_list))) self.current_play_list.extend(deque(playing_list)) def next_song(self, loop, user_data): # Scrobble the track if scrobbling is enabled # and total playback time of the track > 30s if self.scrobbling and self.current_song.length_in_sec > 30: self.scrobbler.submit(self.current_song.artist, self.current_song.song_title, self.current_song.album_title, self.current_song.length_in_sec) if self.douban_account: r, err = self.douban.end_song( self.current_song.sid, self.current_channel) if r: logger.debug('End song OK') else: logger.error(err) if self.song_change_alarm: self.main_loop.remove_alarm(self.song_change_alarm) self._play_track() def skip_current_song(self): if self.douban_account: r, err = self.douban.skip_song( self.current_song.sid, self.current_channel) if r: logger.debug('Skip song OK') else: logger.error(err) if self.song_change_alarm: self.main_loop.remove_alarm(self.song_change_alarm) self._play_track() def rate_current_song(self): if not self.douban_account: return r, err = self.douban.rate_song( self.current_song.sid, self.current_channel) if r: self.current_song.like = True self.selected_button.set_text(self.selected_button.text.replace( WHITE_HEART, BLACK_HEART)) logger.debug('Rate song OK') else: logger.error(err) def unrate_current_song(self): if not self.douban_account: return r, err = self.douban.unrate_song( self.current_song.sid, self.current_channel) if r: self.current_song.like = False self.selected_button.set_text(self.selected_button.text.replace( BLACK_HEART, WHITE_HEART)) logger.debug('Unrate song OK') else: logger.error(err) def trash_current_song(self): if not self.douban_account: return r, err = self.douban.bye_song( self.current_song.sid, self.current_channel) if r: # play next song if self.song_change_alarm: self.main_loop.remove_alarm(self.song_change_alarm) self._play_track() logger.debug('Trash song OK') else: logger.error(err) def getChannelListBox(self): body = [] for c in self.channels: _channel = ChannelButton(c['name']) urwid.connect_signal( _channel, 'click', self.on_channel_chosen, c['channel_id']) body.append(urwid.AttrMap(_channel, None, focus_map="channel")) return ChannelListBox(urwid.SimpleFocusListWalker(body)) def on_channel_chosen(self, button, choice): # Choose the channel which is playing right now # ignore this if self.selected_button == button: return # Choose a different channel if self.player.is_playing: self.player.stop() self._choose_channel(choice) if self.selected_button != None and button != self.selected_button: self.selected_button.set_text( self.selected_button.text[0:11].strip()) self.selected_button = button if self.song_change_alarm: self.main_loop.remove_alarm(self.song_change_alarm) self._play_track() def on_skip(self): self.skip_current_song() def on_rate_and_unrate(self): if self.current_song.like: self.unrate_current_song() else: self.rate_current_song() def on_trash(self): self.trash_current_song() def on_exit(self): self.exit() def exit(self): logger.debug('Exit') self.player.stop() raise urwid.ExitMainLoop() def start(self): self.main_loop.run()
class Doubanfm(object): def __init__(self): self.douban = None self.player = None self.config = None self.scrobbler = None self.channels = None self.current_channel = 0 self.current_song = None self.current_play_list = None self._setup_config() self._setup_api_tools() self._setup_ui() self._setup_signals() def _setup_config(self): self.config = Config() # Set up config try: arg = sys.argv[1] self.config.do_config() except IndexError: self.config.load_config() def _setup_api_tools(self): # Init API tools self.player = Player() self.douban = Douban(self.email, self.password, self.user_id, self.expire, self.token, self.user_name, self.cookies) # Try to login if self.last_fm_username is None or self.last_fm_username == "": self.scrobbling = False if (self.email is None or self.email == "") and self.cookies == None: self.douban_account = False if self.scrobbling: self.scrobbler = Scrobbler(self.last_fm_username, self.last_fm_password) r, err = self.scrobbler.handshake() if r: logger.debug("Last.fm logged in.") else: print("Last.FM 登录失败: " + err) self.scrobbling = False if self.douban_account: r, err = self.douban.do_login() if r: logger.debug("Douban logged in") else: print("Douban 登录失败: " + err) self.douban_account = False # Refresh account cache self.config.save_account_cache(self.douban.user_name, self.douban.user_id, self.douban.expire, self.douban.token, self.douban.cookies, self.last_fm_username, self.last_fm_password) def _setup_ui(self): # Init terminal ui self.palette = [('selected', 'bold', 'default'), ('title', 'yellow', 'default')] self.selected_button = None self.main_loop = None self.song_change_alarm = None self.get_channels() title = '豆瓣FM' + ' ' * 32 if self.douban_account: title += '豆瓣已登录' else: title += '豆瓣未登陆' title += ' ' * 3 if self.scrobbling: title += 'Last.fm 已登录' else: title += 'Last.fm 未登录' self.title = urwid.AttrMap(urwid.Text(title), 'title') self.divider = urwid.Divider() self.pile = urwid.Padding(urwid.Pile( [self.divider, self.title, self.divider]), left=4, right=4) self.channel_list_box = self.getChannelListBox() self.box = urwid.Padding(self.channel_list_box, left=2, right=4) self.frame = urwid.Frame(self.box, header=self.pile, footer=self.divider) self.main_loop = urwid.MainLoop(self.frame, self.palette, handle_mouse=False) # Cache the channel list self.config.save_channel_cache(self.channels) def _setup_signals(self): urwid.register_signal(ChannelListBox, ['exit', 'skip', 'rate', 'trash']) urwid.connect_signal(self.channel_list_box, 'exit', self.on_exit) urwid.connect_signal(self.channel_list_box, 'skip', self.on_skip) urwid.connect_signal(self.channel_list_box, 'rate', self.on_rate_and_unrate) urwid.connect_signal(self.channel_list_box, 'trash', self.on_trash) def __getattr__(self, name): try: return self.__dict__[name] except KeyError: return self.config.__dict__[name] def get_channels(self): if self.channels is None: try: self.channels = self.cached_channels except KeyError: self.channels = deque(self.douban.get_channels()) def _choose_channel(self, channel): self.current_channel = channel self.current_play_list = deque( self.douban.get_new_play_list(self.current_channel)) def _play_track(self): _song = self.current_play_list.popleft() self.current_song = Song(_song) # Post notification Notifier.notify("", self.current_song.song_title, self.current_song.artist + ' — ' + self.current_song.album_title, appIcon=self.current_song.picture, open_URL=self.current_song.album) logger.debug('{0} tracks remaining in the playlist'.format( len(self.current_play_list))) self.song_change_alarm = self.main_loop.set_alarm_in( self.current_song.length_in_sec, self.next_song, None) self.selected_button.set_text(self.selected_button.text[0:11].strip()) heart = WHITE_HEART if self.current_song.like: heart = BLACK_HEART if not self.douban_account: heart = ' ' self.selected_button.set_text(self.selected_button.text + ' ' + heart + ' ' + self.current_song.artist + ' - ' + self.current_song.song_title) if self.scrobbling: self.scrobbler.now_playing(self.current_song.artist, self.current_song.song_title, self.current_song.album_title, self.current_song.length_in_sec) self.player.stop() self.player.play(self.current_song) # Currently playing the second last song in queue if len(self.current_play_list) == 1: # Extend the playing list playing_list = self.douban.get_playing_list( self.current_song.sid, self.current_channel) logger.debug('Got {0} more tracks'.format(len(playing_list))) self.current_play_list.extend(deque(playing_list)) def next_song(self, loop, user_data): # Scrobble the track if scrobbling is enabled # and total playback time of the track > 30s if self.scrobbling and self.current_song.length_in_sec > 30: self.scrobbler.submit(self.current_song.artist, self.current_song.song_title, self.current_song.album_title, self.current_song.length_in_sec) if self.douban_account: r, err = self.douban.end_song(self.current_song.sid, self.current_channel) if r: logger.debug('End song OK') else: logger.error(err) if self.song_change_alarm: self.main_loop.remove_alarm(self.song_change_alarm) self._play_track() def skip_current_song(self): if self.douban_account: r, err = self.douban.skip_song(self.current_song.sid, self.current_channel) if r: logger.debug('Skip song OK') else: logger.error(err) if self.song_change_alarm: self.main_loop.remove_alarm(self.song_change_alarm) self._play_track() def rate_current_song(self): if not self.douban_account: return r, err = self.douban.rate_song(self.current_song.sid, self.current_channel) if r: self.current_song.like = True self.selected_button.set_text( self.selected_button.text.replace(WHITE_HEART, BLACK_HEART)) logger.debug('Rate song OK') else: logger.error(err) def unrate_current_song(self): if not self.douban_account: return r, err = self.douban.unrate_song(self.current_song.sid, self.current_channel) if r: self.current_song.like = False self.selected_button.set_text( self.selected_button.text.replace(BLACK_HEART, WHITE_HEART)) logger.debug('Unrate song OK') else: logger.error(err) def trash_current_song(self): if not self.douban_account: return r, err = self.douban.bye_song(self.current_song.sid, self.current_channel) if r: # play next song if self.song_change_alarm: self.main_loop.remove_alarm(self.song_change_alarm) self._play_track() logger.debug('Trash song OK') else: logger.error(err) def getChannelListBox(self): body = [] for c in self.channels: _channel = ChannelButton(c['name']) urwid.connect_signal(_channel, 'click', self.on_channel_chosen, c['channel_id']) body.append(urwid.AttrMap(_channel, None, focus_map="channel")) return ChannelListBox(urwid.SimpleFocusListWalker(body)) def on_channel_chosen(self, button, choice): # Choose the channel which is playing right now # ignore this if self.selected_button == button: return # Choose a different channel if self.player.is_playing: self.player.stop() self._choose_channel(choice) if self.selected_button != None and button != self.selected_button: self.selected_button.set_text( self.selected_button.text[0:11].strip()) self.selected_button = button if self.song_change_alarm: self.main_loop.remove_alarm(self.song_change_alarm) self._play_track() def on_skip(self): self.skip_current_song() def on_rate_and_unrate(self): if self.current_song.like: self.unrate_current_song() else: self.rate_current_song() def on_trash(self): self.trash_current_song() def on_exit(self): self.exit() def exit(self): logger.debug('Exit') self.player.stop() raise urwid.ExitMainLoop() def start(self): self.main_loop.run()