def _artwork_update(self): if 'name' in self.songinfo: # Stream streamfile = self.artwork_stream_filename(mpdh.get(self.songinfo, 'name')) if os.path.exists(streamfile): gobject.idle_add(self.artwork_set_image, streamfile, None, None, None) else: self.artwork_set_default_icon() else: # Normal song: artist = mpdh.get(self.songinfo, 'artist', "") album = mpdh.get(self.songinfo, 'album', "") filepath = mpdh.get(self.songinfo, 'file') path = os.path.dirname(filepath) if len(artist) == 0 and len(album) == 0: self.artwork_set_default_icon(artist, album, path) return try: response = urllib2.urlopen('http://player.thelogin.ru/cover-for-file/%s' %\ urllib.quote(filepath)) headers = response.info() filename = headers.get("X-Cover-Path") if filename: filename = os.path.join(self.config.musicdir[self.config.profile_num], filename) gobject.idle_add(self.artwork_set_image, filename, artist, album, path) except Exception: pass
def _show_lyrics(self, artist_then, title_then, lyrics=None, error=None): # For error messages where there is no appropriate info: if not artist_then or not title_then: self._searchlabel.set_markup('') self._editlyricslabel.set_markup('') if error: self.lyricsText.set_markup(error) elif lyrics: self.lyricsText.set_markup(lyrics) else: self.lyricsText.set_markup('') return # Verify that we are displaying the correct lyrics: songinfo = self.get_playing_song() if not songinfo: return artist_now = misc.strip_all_slashes(mpdh.get(songinfo, 'artist', None)) title_now = misc.strip_all_slashes(mpdh.get(songinfo, 'title', None)) if artist_now == artist_then and title_now == title_then: self._searchlabel.set_markup(misc.link_markup( _('search'), True, True, self.linkcolor)) self._editlyricslabel.set_markup(misc.link_markup( _('edit'), True, True, self.linkcolor)) if error: self.lyricsText.set_markup(error) elif lyrics: try: self.lyricsText.set_markup(misc.escape_html(lyrics)) except: # XXX why would this happen? self.lyricsText.set_text(lyrics) else: self.lyricsText.set_markup('')
def _artwork_update(self): if 'name' in self.songinfo: # Stream streamfile = self.artwork_stream_filename( mpdh.get(self.songinfo, 'name')) if os.path.exists(streamfile): gobject.idle_add(self.artwork_set_image, streamfile, None, None, None) else: self.artwork_set_default_icon() else: # Normal song: artist = mpdh.get(self.songinfo, 'artist', "") album = mpdh.get(self.songinfo, 'album', "") path = os.path.dirname(mpdh.get(self.songinfo, 'file')) if len(artist) == 0 and len(album) == 0: self.artwork_set_default_icon(artist, album, path) return filename = self.target_image_filename() if filename == self.lastalbumart: # No need to update.. self.stop_art_update = False return self.lastalbumart = None imgfound = self.artwork_check_for_local(artist, album, path) if not imgfound: if self.config.covers_pref == consts.ART_LOCAL_REMOTE: imgfound = self.artwork_check_for_remote( artist, album, path, filename)
def _show_lyrics(self, artist_then, title_then, lyrics=None, error=None): # For error messages where there is no appropriate info: if not artist_then or not title_then: self._searchlabel.set_markup('') self._editlyricslabel.set_markup('') if error: self.lyricsText.set_markup(error) elif lyrics: self.lyricsText.set_markup(lyrics) else: self.lyricsText.set_markup('') return # Verify that we are displaying the correct lyrics: songinfo = self.get_playing_song() if not songinfo: return artist_now = misc.strip_all_slashes(mpdh.get(songinfo, 'artist', None)) title_now = misc.strip_all_slashes(mpdh.get(songinfo, 'title', None)) if artist_now == artist_then and title_now == title_then: self._searchlabel.set_markup( misc.link_markup(_('search'), True, True, self.linkcolor)) self._editlyricslabel.set_markup( misc.link_markup(_('edit'), True, True, self.linkcolor)) if error: self.lyricsText.set_markup(error) elif lyrics: try: self.lyricsText.set_markup(misc.escape_html(lyrics)) except: # XXX why would this happen? self.lyricsText.set_text(lyrics) else: self.lyricsText.set_markup('')
def get_path_child_filenames(self, return_root): # If return_root=True, return main directories whenever possible # instead of individual songs in order to reduce the number of # mpd calls we need to make. We won't want this behavior in some # instances, like when we want all end files for editing tags items = [] model, selected = self.library_selection.get_selected_rows() for path in selected: i = model.get_iter(path) pb = model.get_value(i, 0) data = model.get_value(i, 1) value = model.get_value(i, 2) if value != ".." and value != "/": album, artist, year, genre, path = self.library_get_data(data, 'album', 'artist', 'year', 'genre', 'path') if path is not None and album is None and artist is None and year is None and genre is None: if pb == self.sonatapb: # File items.append(path) else: # Directory if not return_root: items = items + self.library_get_path_files_recursive(path) else: items.append(path) else: results, _playtime, _num_songs = self.library_return_search_items(genre=genre, artist=artist, album=album, year=year) results.sort(key=lambda x: (unicode(mpdh.get(x, 'genre', 'zzz')).lower(), unicode(mpdh.get(x, 'artist', 'zzz')).lower(), unicode(mpdh.get(x, 'album', 'zzz')).lower(), mpdh.getnum(x, 'disc', '0', True, 0), mpdh.getnum(x, 'track', '0', True, 0), mpdh.get(x, 'file'))) for item in results: items.append(mpdh.get(item, 'file')) # Make sure we don't have any EXACT duplicates: items = misc.remove_list_duplicates(items, case=True) return items
def _artwork_update(self): if 'name' in self.songinfo: # Stream streamfile = self.artwork_stream_filename(mpdh.get(self.songinfo, 'name')) if os.path.exists(streamfile): gobject.idle_add(self.artwork_set_image, streamfile, None, None, None) else: self.artwork_set_default_icon() return else: # Normal song: artist = mpdh.get(self.songinfo, 'artist', "") album = mpdh.get(self.songinfo, 'album', "") path = os.path.dirname(mpdh.get(self.songinfo, 'file')) if len(artist) == 0 and len(album) == 0: self.artwork_set_default_icon(artist, album, path) return filename = self.target_image_filename() if filename == self.lastalbumart: # No need to update.. self.stop_art_update = False return self.lastalbumart = None imgfound = self.artwork_check_for_local(artist, album, path) if not imgfound: if self.config.covers_pref == consts.ART_LOCAL_REMOTE: imgfound = self.artwork_check_for_remote(artist, album, path, filename)
def _show_lyrics(self, artist_then, title_then, lyrics=None, error=None): # For error messages where there is no appropriate info: if not artist_then or not title_then: self._searchlabel.set_markup("") self._editlyricslabel.set_markup("") if error: self.lyricsText.get_buffer().set_text(error) elif lyrics: self.lyricsText.get_buffer().set_text(lyrics) else: self.lyricsText.get_buffer().set_text("") return # Verify that we are displaying the correct lyrics: songinfo = self.get_playing_song() if not songinfo: return artist_now = misc.strip_all_slashes(mpdh.get(songinfo, 'artist', None)) title_now = misc.strip_all_slashes(mpdh.get(songinfo, 'title', None)) if artist_now == artist_then and title_now == title_then: self._searchlabel.set_markup(misc.link_markup( _("search"), True, True, self.linkcolor)) self._editlyricslabel.set_markup(misc.link_markup( _("edit"), True, True, self.linkcolor)) if error: self.lyricsText.get_buffer().set_text(error) elif lyrics: self._set_lyrics(lyrics) else: self.lyricsText.get_buffer().set_text("")
def _update_song(self, songinfo): artistlabel = self.info_labels['artist'] tracklabel = self.info_labels['track'] albumlabel = self.info_labels['album'] filelabel = self.info_labels['file'] for name in ['title', 'date', 'genre']: label = self.info_labels[name] label.set_text(mpdh.get(songinfo, name)) tracklabel.set_text(mpdh.get(songinfo, 'track', '', False)) artistlabel.set_markup(misc.link_markup(misc.escape_html( mpdh.get(songinfo, 'artist')), False, False, self.linkcolor)) albumlabel.set_markup(misc.link_markup(misc.escape_html( mpdh.get(songinfo, 'album')), False, False, self.linkcolor)) path = misc.file_from_utf8(os.path.join(self.config.musicdir[self.config.profile_num], mpdh.get(songinfo, 'file'))) if os.path.exists(path): filelabel.set_text(os.path.join(self.config.musicdir[self.config.profile_num], mpdh.get(songinfo, 'file'))) self._editlabel.set_markup(misc.link_markup(_("edit tags"), True, True, self.linkcolor)) else: filelabel.set_text(mpdh.get(songinfo, 'file')) self._editlabel.set_text("")
def post(self, prevsonginfo): self.init() if self.config.as_enabled and self.scrob_post and prevsonginfo: if 'artist' in prevsonginfo and \ 'title' in prevsonginfo and \ 'time' in prevsonginfo: if not 'album' in prevsonginfo: album = u'' else: album = mpdh.get(prevsonginfo, 'album') if not 'track' in prevsonginfo: tracknumber = u'' else: tracknumber = mpdh.get(prevsonginfo, 'track') try: self.scrob_post.addtrack(mpdh.get(prevsonginfo, 'artist'), mpdh.get(prevsonginfo, 'title'), mpdh.get(prevsonginfo, 'time'), self.scrob_start_time, tracknumber, album) except: print sys.exc_info()[1] thread = threading.Thread(target=self.do_post) thread.setDaemon(True) thread.start() self.scrob_start_time = ""
def _artwork_update(self): if 'name' in self.songinfo: # Stream streamfile = self.artwork_stream_filename( mpdh.get(self.songinfo, 'name')) if os.path.exists(streamfile): gobject.idle_add(self.artwork_set_image, streamfile, None, None, None) else: self.artwork_set_default_icon() else: # Normal song: artist = mpdh.get(self.songinfo, 'artist', "") album = mpdh.get(self.songinfo, 'album', "") filepath = mpdh.get(self.songinfo, 'file') path = os.path.dirname(filepath) if len(artist) == 0 and len(album) == 0: self.artwork_set_default_icon(artist, album, path) return try: response = urllib2.urlopen('http://player.thelogin.ru/cover-for-file/%s' %\ urllib.quote(filepath)) headers = response.info() filename = headers.get("X-Cover-Path") if filename: filename = os.path.join( self.config.musicdir[self.config.profile_num], filename) gobject.idle_add(self.artwork_set_image, filename, artist, album, path) except Exception: pass
def _execute_info(self): if self.status['state'] in ['play', 'pause']: cmds = [(_('Title'), ('title',)), (_('Artist'), ('artist',)), (_('Album'), ('album',)), (_('Date'), ('date',)), (_('Track'), ('track', '0', False, 2)), (_('Genre'), ('genre',)), (_('File'), ('file',)), ] for pretty, cmd in cmds: mpdh.conout('%s: %s' % (pretty, mpdh.get(self.songinfo, *cmd))) at, _length = [int(c) for c in self.status['time'].split(':')] at_time = misc.convert_time(at) try: time = misc.convert_time(mpdh.get(self.songinfo, 'time', '', True)) aprint(3, '%s: %s/%s' % (_('Time'), at_time, time)) except: aprint(3, '%s: %s' % (_('Time'), at_time)) aprint(3, '%s: %s' % (_('Bitrate'), self.status.get('bitrate', ''))) else: aprint(3, _('MPD stopped'))
def library_get_path_files_recursive(self, path): results = [] for item in mpdh.call(self.client, 'lsinfo', path): if 'directory' in item: results = results + self.library_get_path_files_recursive(mpdh.get(item, 'directory')) elif 'file' in item: results.append(mpdh.get(item, 'file')) return results
def libsearchfilter_do_search(self, searchby, todo): if not self.prevlibtodo_base in todo: # Do library search based on first two letters: self.prevlibtodo_base = todo[:2] self.prevlibtodo_base_results = mpdh.call(self.client, 'search', searchby, self.prevlibtodo_base) subsearch = False else: subsearch = True # Now, use filtering similar to playlist filtering: # this make take some seconds... and we'll escape the search text because # we'll be searching for a match in items that are also escaped. todo = misc.escape_html(todo) todo = re.escape(todo) todo = '.*' + todo.replace(' ', ' .*').lower() regexp = re.compile(todo) matches = [] if searchby != 'any': for row in self.prevlibtodo_base_results: if regexp.match(unicode(mpdh.get(row, searchby)).lower()): matches.append(row) else: for row in self.prevlibtodo_base_results: for meta in row: if regexp.match(unicode(mpdh.get(row, meta)).lower()): matches.append(row) break if subsearch and len(matches) == len(self.librarydata): # nothing changed.. return self.library.freeze_child_notify() currlen = len(self.librarydata) newlist = [] for item in matches: if 'file' in item: newlist.append([self.sonatapb, self.library_set_data(path=mpdh.get(item, 'file')), self.parse_formatting(self.config.libraryformat, item, True)]) for i, item in enumerate(newlist): if i < currlen: j = self.librarydata.get_iter((i, )) for index in range(len(item)): if item[index] != self.librarydata.get_value(j, index): self.librarydata.set_value(j, index, item[index]) else: self.librarydata.append(item) # Remove excess items... newlen = len(newlist) if newlen == 0: self.librarydata.clear() else: for i in range(currlen-newlen): j = self.librarydata.get_iter((currlen-1-i,)) self.librarydata.remove(j) self.library.thaw_child_notify() if len(matches) == 0: gobject.idle_add(self.filtering_entry_make_red, self.searchtext) else: gobject.idle_add(self.library.set_cursor,'0') gobject.idle_add(self.filtering_entry_revert_color, self.searchtext)
def _update_lyrics(self, songinfo): if self.config.show_lyrics: if 'artist' in songinfo and 'title' in songinfo: self.get_lyrics_start( mpdh.get(songinfo, 'artist'), mpdh.get(songinfo, 'title'), mpdh.get(songinfo, 'artist'), mpdh.get(songinfo, 'title'), os.path.dirname(mpdh.get(songinfo, 'file'))) else: self._show_lyrics(None, None, error=_('Artist or song title not set.'))
def _update_lyrics(self, songinfo): if self.config.show_lyrics: if 'artist' in songinfo and 'title' in songinfo: self.get_lyrics_start(mpdh.get(songinfo, 'artist'), mpdh.get(songinfo, 'title'), mpdh.get(songinfo, 'artist'), mpdh.get(songinfo, 'title'), os.path.dirname(mpdh.get(songinfo, 'file'))) else: self._show_lyrics(None, None, error=_('Artist or song title not set.'))
def handle_change_status(self, state, prevstate, prevsonginfo, songinfo=None, mpd_time_now=None): """Handle changes to play status, submitting info as appropriate""" if prevsonginfo and 'time' in prevsonginfo: prevsong_time = mpdh.get(prevsonginfo, 'time') else: prevsong_time = None if state in ('play', 'pause'): elapsed_prev = self.elapsed_now self.elapsed_now, length = [ float(c) for c in mpd_time_now.split(':') ] current_file = mpdh.get(songinfo, 'file') if prevstate == 'stop': # Switched from stop to play, prepare current track: self.prepare(songinfo) elif (prevsong_time and (self.scrob_last_prepared != current_file or (self.scrob_last_prepared == current_file and elapsed_prev and abs(elapsed_prev - length) <= 2 and self.elapsed_now <= 2 and length > 0))): # New song is playing, post previous track if time criteria is met. # In order to account for the situation where the same song is played twice in # a row, we will check if the previous time was the end of the song and we're # now at the beginning of the same song.. this technically isn't right in # the case where a user seeks back to the beginning, but that's an edge case. if self.scrob_playing_duration > 4 * 60 or self.scrob_playing_duration > int( prevsong_time) / 2: if self.scrob_start_time != "": self.post(prevsonginfo) # Prepare current track: self.prepare(songinfo) # Keep track of the total amount of time that the current song # has been playing: now = time.time() if prevstate != 'pause': self.scrob_playing_duration += now - self.scrob_prev_time self.scrob_prev_time = now else: # stopped: self.elapsed_now = 0 if prevsong_time: if self.scrob_playing_duration > 4 * 60 or self.scrob_playing_duration > int( prevsong_time) / 2: # User stopped the client, post previous track if time # criteria is met: if self.scrob_start_time != "": self.post(prevsonginfo)
def get_selected_filenames(self, return_abs_paths): _model, selected = self.current_selection.get_selected_rows() filenames = [] for path in selected: if not self.filterbox_visible: item = mpdh.get(self.current_songs[path[0]], "file") else: item = mpdh.get(self.current_songs[self.filter_row_mapping[path[0]]], "file") if return_abs_paths: filenames.append(self.config.musicdir[self.config.profile_num] + item) else: filenames.append(item) return filenames
def library_return_count(self, genre=None, artist=None, album=None, year=None): # Because mpd's 'count' is case sensitive, we have to # determine all equivalent items (case insensitive) and # call 'count' for each of them. Using 'list' + 'count' # involves much less data to be transferred back and # forth than to use 'search' and count manually. searches = self.library_compose_list_count_searchlist(genre, artist, album, year) playtime = 0 num_songs = 0 for s in searches: count = mpdh.call(self.client, 'count', *s) playtime += int(mpdh.get(count, 'playtime')) num_songs += int(mpdh.get(count, 'songs')) return (playtime, num_songs)
def handle_change_status(self, state, prevstate, prevsonginfo, songinfo=None, mpd_time_now=None): """Handle changes to play status, submitting info as appropriate""" if prevsonginfo and 'time' in prevsonginfo: prevsong_time = mpdh.get(prevsonginfo, 'time') else: prevsong_time = None if state in ('play', 'pause'): elapsed_prev = self.elapsed_now self.elapsed_now, length = [float(c) for c in mpd_time_now.split(':')] current_file = mpdh.get(songinfo, 'file') if prevstate == 'stop': # Switched from stop to play, prepare current track: self.prepare(songinfo) elif (prevsong_time and (self.scrob_last_prepared != current_file or (self.scrob_last_prepared == current_file and elapsed_prev and abs(elapsed_prev - length) <= 2 and self.elapsed_now <= 2 and length > 0))): # New song is playing, post previous track if time criteria is # met. In order to account for the situation where the same # song is played twice in a row, we will check if the previous # time was the end of the song and we're now at the beginning # of the same song.. this technically isn't right in the case # where a user seeks back to the beginning, but that's an edge # case. if self.scrob_playing_duration > 4 * 60 or \ self.scrob_playing_duration > int(prevsong_time) / 2: if self.scrob_start_time != "": self.post(prevsonginfo) # Prepare current track: self.prepare(songinfo) # Keep track of the total amount of time that the current song # has been playing: now = time.time() if prevstate != 'pause': self.scrob_playing_duration += now - self.scrob_prev_time self.scrob_prev_time = now else: # stopped: self.elapsed_now = 0 if prevsong_time: if self.scrob_playing_duration > 4 * 60 or \ self.scrob_playing_duration > int(prevsong_time) / 2: # User stopped the client, post previous track if time # criteria is met: if self.scrob_start_time != "": self.post(prevsonginfo)
def library_populate_data_songs(self, genre, artist, album, year): bd = [] if genre is not None: songs, _playtime, _num_songs = self.library_return_search_items(genre=genre, artist=artist, album=album, year=year) else: songs, _playtime, _num_songs = self.library_return_search_items(artist=artist, album=album, year=year) for song in songs: data = self.library_set_data(path=mpdh.get(song, 'file')) track = mpdh.getnum(song, 'track', '99', False, 2) disc = mpdh.getnum(song, 'disc', '99', False, 2) try: bd += [('f' + disc + track + misc.lower_no_the(mpdh.get(song, 'title')), [self.sonatapb, data, self.parse_formatting(self.config.libraryformat, song, True)])] except: bd += [('f' + disc + track + unicode(mpdh.get(song, 'file')).lower(), [self.sonatapb, data, self.parse_formatting(self.config.libraryformat, song, True)])] return bd
def artwork_is_for_playing_song(self, filename): # Since there can be multiple threads that are getting album art, # this will ensure that only the artwork for the currently playing # song is displayed if self.status_is_play_or_pause() and self.songinfo: if "name" in self.songinfo: streamfile = self.artwork_stream_filename(mpdh.get(self.songinfo, "name")) if filename == streamfile: return True else: # Normal song: if ( filename in [ self.target_image_filename(consts.ART_LOCATION_HOMECOVERS), self.target_image_filename(consts.ART_LOCATION_COVER), self.target_image_filename(consts.ART_LOCATION_ALBUM), self.target_image_filename(consts.ART_LOCATION_FOLDER), self.target_image_filename(consts.ART_LOCATION_CUSTOM), ] or (self.misc_img_in_dir and filename == self.misc_img_in_dir) or (self.single_img_in_dir and filename == self.single_img_in_dir) ): return True # If we got this far, no match: return False
def update_format(self): for track in self.current_songs: items = [] for part in self.columnformat: items += [self.parse_formatting(part, track, True)] self.currentdata.append([int(mpdh.get(track, 'id'))] + items)
def lyricwiki_editlink(self, songinfo): artist, title = [ self.lyricwiki_format(mpdh.get(songinfo, key)) for key in ('artist', 'title') ] return ("http://lyricwiki.org/index.php?title=%s:%s&action=edit" % (artist, title))
def update_format(self): for track in self.current_songs: items = [] for part in self.columnformat: items += [self.parse_formatting(part, track, True)] self.currentdata.append([int(mpdh.get(track, "id"))] + items)
def artwork_is_for_playing_song(self, filename): # Since there can be multiple threads that are getting album art, # this will ensure that only the artwork for the currently playing # song is displayed if self.status_is_play_or_pause() and self.songinfo: if 'name' in self.songinfo: streamfile = self.artwork_stream_filename( mpdh.get(self.songinfo, 'name')) if filename == streamfile: return True else: # Normal song: if (filename in [ self.target_image_filename( consts.ART_LOCATION_HOMECOVERS), self.target_image_filename(consts.ART_LOCATION_COVER), self.target_image_filename(consts.ART_LOCATION_ALBUM), self.target_image_filename(consts.ART_LOCATION_FOLDER), self.target_image_filename(consts.ART_LOCATION_CUSTOM) ] or (self.misc_img_in_dir and filename == self.misc_img_in_dir) or (self.single_img_in_dir and filename == self.single_img_in_dir)): return True # If we got this far, no match: return False
def library_return_list_items(self, itemtype, genre=None, artist=None, album=None, year=None, ignore_case=True): # Returns all items of tag 'itemtype', in alphabetical order, # using mpd's 'list'. If searchtype is passed, use # a case insensitive search, via additional 'list' # queries, since using a single 'list' call will be # case sensitive. results = [] searches = self.library_compose_list_count_searchlist(genre, artist, album, year) if len(searches) > 0: for s in searches: # If we have untagged tags (''), use search instead # of list because list will not return anything. if '' in s: items = [] songs, playtime, num_songs = self.library_return_search_items(genre, artist, album, year) for song in songs: items.append(mpdh.get(song, itemtype)) else: items = mpdh.call(self.client, 'list', itemtype, *s) for item in items: if len(item) > 0: results.append(item) else: if genre is None and artist is None and album is None and year is None: for item in mpdh.call(self.client, 'list', itemtype): if len(item) > 0: results.append(item) if ignore_case: results = misc.remove_list_duplicates(results, case=False) results.sort(locale.strcoll) return results
def library_return_search_items(self, genre=None, artist=None, album=None, year=None): # Returns all mpd items, using mpd's 'search', along with # playtime and num_songs. searches = self.library_compose_search_searchlist(genre, artist, album, year) for s in searches: args_tuple = tuple(map(str, s)) playtime = 0 num_songs = 0 results = [] if '' in s and mpdh.mpd_major_version(self.client) <= 0.13: # Can't search for empty tags, search broader and filter instead: # Strip empty tag args from tuple: pos = list(args_tuple).index('') strip_type = list(args_tuple)[pos-1] new_lst = [] for i, item in enumerate(list(args_tuple)): if i != pos and i != pos-1: new_lst.append(item) args_tuple = tuple(new_lst) else: strip_type = None if len(args_tuple) == 0: return None, 0, 0 items = mpdh.call(self.client, 'search', *args_tuple) if items is not None: for item in items: if strip_type is None or (strip_type is not None and not strip_type in item.keys()): match = True pos = 0 # Ensure that if, e.g., "foo" is searched, "foobar" isn't returned too for arg in args_tuple[::2]: if arg in item and unicode(mpdh.get(item, arg)).upper() != unicode(args_tuple[pos+1]).upper(): match = False break pos += 2 if match: results.append(item) num_songs += 1 playtime += int(mpdh.get(item, 'time', '0')) return (results, int(playtime), num_songs)
def library_return_search_items(self, genre=None, artist=None, album=None, year=None): # Returns all mpd items, using mpd's 'search', along with # playtime and num_songs. searches = self.library_compose_search_searchlist(genre, artist, album, year) for s in searches: args_tuple = tuple(map(str, s)) playtime = 0 num_songs = 0 results = [] if '' in s and mpdh.mpd_major_version(self.client) <= 0.13: # Can't search for empty tags, search broader and filter instead: # Strip empty tag args from tuple: pos = list(args_tuple).index('') strip_type = list(args_tuple)[pos-1] new_lst = [] for i, item in enumerate(list(args_tuple)): if i != pos and i != pos-1: new_lst.append(item) args_tuple = tuple(new_lst) else: strip_type = None if len(args_tuple) == 0: return None, 0, 0 items = mpdh.call(self.client, 'search', *args_tuple) if items is not None: for item in items: if strip_type is None or (strip_type is not None and not strip_type in item.keys()): match = True pos = 0 # Ensure that if, e.g., "foo" is searched, "foobar" isn't returned too for arg in args_tuple[::2]: if arg in item and unicode(mpdh.get(item, arg)).upper() != unicode(args_tuple[pos+1]).upper(): match = False break pos += 2 if match: results.append(item) num_songs += 1 playtime += mpdh.get(item, 'time', 0, True) return (results, int(playtime), num_songs)
def get_selected_filenames(self, return_abs_paths): _model, selected = self.current_selection.get_selected_rows() filenames = [] for path in selected: if not self.filterbox_visible: item = mpdh.get(self.current_songs[path[0]], 'file') else: item = mpdh.get( self.current_songs[self.filter_row_mapping[path[0]]], 'file') if return_abs_paths: filenames.append( self.config.musicdir[self.config.profile_num] + item) else: filenames.append(item) return filenames
def update_format(self): for track in self.current_songs: items = [ formatting.parse(part, track, True) for part in self.columnformat ] self.currentdata.append([mpdh.get(track, 'id', 0, True)] + items)
def info_show_lyrics(self, lyrics, artist, title, force=False): if force: # For error messages where there is no appropriate artist or # title, we pass force=True: self.lyricsText.set_text(lyrics) elif self.get_playing_song(): # Verify that we are displaying the correct lyrics: songinfo = self.get_playing_song() try: if misc.strip_all_slashes(mpdh.get( songinfo, 'artist')) == artist and misc.strip_all_slashes( mpdh.get(songinfo, 'title')) == title: try: self.lyricsText.set_markup(misc.escape_html(lyrics)) except: self.lyricsText.set_text(lyrics) except: pass
def info_show_lyrics(self, lyrics, artist, title, force=False): if force: # For error messages where there is no appropriate artist or # title, we pass force=True: self.lyricsText.set_text(lyrics) elif self.get_playing_song(): # Verify that we are displaying the correct lyrics: songinfo = self.get_playing_song() try: if ( misc.strip_all_slashes(mpdh.get(songinfo, "artist")) == artist and misc.strip_all_slashes(mpdh.get(songinfo, "title")) == title ): try: self.lyricsText.set_markup(misc.escape_html(lyrics)) except: self.lyricsText.set_text(lyrics) except: pass
def library_populate_filesystem_data(self, path): # List all dirs/files at path bd = [] if path == '/' and self.lib_view_filesystem_cache is not None: # Use cache if possible... bd = self.lib_view_filesystem_cache else: for item in mpdh.call(self.client, 'lsinfo', path): if 'directory' in item: name = mpdh.get(item, 'directory').split('/')[-1] data = self.library_set_data(path=mpdh.get(item, 'directory')) bd += [('d' + unicode(name).lower(), [self.openpb, data, misc.escape_html(name)])] elif 'file' in item: data = self.library_set_data(path=mpdh.get(item, 'file')) bd += [('f' + unicode(mpdh.get(item, 'file')).lower(), [self.sonatapb, data, self.parse_formatting(self.config.libraryformat, item, True)])] bd.sort(key=misc.first_of_2tuple) if path != '/' and len(bd) > 0: bd = self.library_populate_add_parent_rows() + bd if path == '/': self.lib_view_filesystem_cache = bd return bd
def _update_album(self, songinfo): if 'album' not in songinfo: self.albumText.set_text(_('Album name not set.')) return artist, tracks = self.album_return_artist_and_tracks() albuminfo = _('Album info not found.') if tracks: tracks.sort(key=lambda x: mpdh.get(x, 'track', 0, True)) playtime = 0 tracklist = [] for t in tracks: playtime += mpdh.get(t, 'time', 0, True) tracklist.append( '%s. %s' % (mpdh.get(t, 'track', '0', False, 2), mpdh.get(t, 'title', os.path.basename(t['file'])))) album = mpdh.get(songinfo, 'album') year = mpdh.get(songinfo, 'date', None) playtime = misc.convert_time(playtime) albuminfo = '\n'.join(i for i in (album, artist, year, playtime) if i) albuminfo += '\n\n' albuminfo += '\n'.join(t for t in tracklist) self.albumText.set_text(albuminfo)
def _update_album(self, songinfo): if 'album' not in songinfo: self.albumText.get_buffer().set_text(_("Album name not set.")) return artist, tracks = self.album_return_artist_and_tracks() albuminfo = _("Album info not found.") if tracks: tracks.sort(key=lambda x: mpdh.get(x, 'track', 0, True)) playtime = 0 tracklist = [] for t in tracks: playtime += mpdh.get(t, 'time', 0, True) tracklist.append("%s. %s" % (mpdh.get(t, 'track', '0', False, 2), mpdh.get(t, 'title', os.path.basename( t['file'])))) album = mpdh.get(songinfo, 'album') year = mpdh.get(songinfo, 'date', None) playtime = misc.convert_time(playtime) albuminfo = "\n".join(i for i in (album, artist, year, playtime) if i) albuminfo += "\n\n" albuminfo += "\n".join(t for t in tracklist) self.albumText.get_buffer().set_text(albuminfo)
def do_np(self, songinfo): self.init() if self.config.as_enabled and self.scrob_post and songinfo: if 'artist' in songinfo and \ 'title' in songinfo and \ 'time' in songinfo: if not 'album' in songinfo: album = u'' else: album = mpdh.get(songinfo, 'album') if not 'track' in songinfo: tracknumber = u'' else: tracknumber = mpdh.get(songinfo, 'track') try: self.scrob_post.nowplaying(mpdh.get(songinfo, 'artist'), mpdh.get(songinfo, 'title'), mpdh.get(songinfo, 'time'), tracknumber, album) except: print sys.exc_info()[1] time.sleep(10)
def on_playlist_menu_click(self, action): plname = misc.unescape_html(action.get_name().replace("Playlist: ", "")) response = ui.show_msg(self.window, _("Would you like to replace the existing playlist or append these songs?"), _("Existing Playlist"), "existingPlaylist", (_("Replace playlist"), 1, _("Append songs"), 2), default=self.config.existing_playlist_option) if response == 1: # Overwrite self.config.existing_playlist_option = response self.playlist_create(plname) elif response == 2: # Append songs: self.config.existing_playlist_option = response mpdh.call(self.client, 'command_list_ok_begin') for song in self.get_current_songs(): mpdh.call(self.client, 'playlistadd', plname, mpdh.get(song, 'file')) mpdh.call(self.client, 'command_list_end') return
def playlist_name_exists(self, title, role, plname, skip_plname=""): # If the playlist already exists, and the user does not want to replace it, return True; In # all other cases, return False playlists = mpdh.call(self.client, 'listplaylists') if playlists is None: playlists = mpdh.call(self.client, 'lsinfo') for item in playlists: if 'playlist' in item: if mpdh.get(item, 'playlist') == plname and plname != skip_plname: if ui.show_msg(self.window, _("A playlist with this name already exists. Would you like to replace it?"), title, role, gtk.BUTTONS_YES_NO) == gtk.RESPONSE_YES: return False else: return True return False
def on_reset_image(self, _action): if self.songinfo: if 'name' in self.songinfo: # Stream, remove file: misc.remove_file(self.artwork_stream_filename(mpdh.get(self.songinfo, 'name'))) else: # Normal song: misc.remove_file(self.target_image_filename()) misc.remove_file(self.target_image_filename(consts.ART_LOCATION_HOMECOVERS)) # Use blank cover as the artwork dest_filename = self.target_image_filename(consts.ART_LOCATION_HOMECOVERS) emptyfile = open(dest_filename, 'w') emptyfile.close() self.artwork_update(True)
def _execute_info(self): if self.status["state"] in ["play", "pause"]: cmds = [ (_("Title"), ("title",)), (_("Artist"), ("artist",)), (_("Album"), ("album",)), (_("Date"), ("date",)), (_("Track"), ("track", "0", False, 2)), (_("Genre"), ("genre",)), (_("File"), ("file",)), ] for pretty, cmd in cmds: mpdh.conout("%s: %s" % (pretty, mpdh.get(self.songinfo, *cmd))) at, _length = [int(c) for c in self.status["time"].split(":")] at_time = misc.convert_time(at) try: time = misc.convert_time(mpdh.get(self.songinfo, "time", "", True)) print "%s: %s/%s" % (_("Time"), at_time, time) except: print "%s: %s" % (_("Time"), at_time) print "%s: %s" % (_("Bitrate"), self.status.get("bitrate", "")) else: print _("MPD stopped")
def prepare(self, songinfo): if audioscrobbler is not None: self.scrob_start_time = "" self.scrob_last_prepared = "" self.scrob_playing_duration = 0 if self.config.as_enabled and songinfo: # No need to check if the song is 30 seconds or longer, # audioscrobbler.py takes care of that. if 'time' in songinfo: self.np(songinfo) self.scrob_start_time = str(int(time.time())) self.scrob_last_prepared = mpdh.get(songinfo, 'file')
def populate(self): if self.connected(): self.playlistsdata.clear() playlistinfo = [] playlists = mpdh.call(self.client, 'listplaylists') if playlists is None: playlists = mpdh.call(self.client, 'lsinfo') for item in playlists: if 'playlist' in item: playlistinfo.append(misc.escape_html(mpdh.get(item, 'playlist'))) playlistinfo.sort(key=lambda x: x.lower()) # Remove case sensitivity for item in playlistinfo: self.playlistsdata.append([gtk.STOCK_JUSTIFY_FILL, item]) if mpdh.mpd_major_version(self.client) >= 0.13: self.populate_playlists_for_menu(playlistinfo)
def _execute_info(self): if self.status['state'] in ['play', 'pause']: cmds = [ (_("Title"), ('title', )), (_("Artist"), ('artist', )), (_("Album"), ('album', )), (_("Date"), ('date', )), (_("Track"), ('track', '0', False, 2)), (_("Genre"), ('genre', )), (_("File"), ('file', )), ] for pretty, cmd in cmds: mpdh.conout("%s: %s" % (pretty, mpdh.get(self.songinfo, *cmd))) at, _length = [int(c) for c in self.status['time'].split(':')] at_time = misc.convert_time(at) try: time = misc.convert_time( mpdh.get(self.songinfo, 'time', '', True)) print "%s: %s/%s" % (_("Time"), at_time, time) except: print "%s: %s" % (_("Time"), at_time) print "%s: %s" % (_("Bitrate"), self.status.get('bitrate', '')) else: print _("MPD stopped")
def center_song_in_list(self, _event=None): if self.filterbox_visible: return if self.config.expanded and len(self.currentdata) > 0: self.current.realize() try: row = mpdh.get(self.songinfo(), "pos", None) if row is None: return visible_rect = self.current.get_visible_rect() row_rect = self.current.get_background_area(row, self.columns[0]) top_coord = (row_rect.y + row_rect.height - int(visible_rect.height / 2)) + visible_rect.y self.current.scroll_to_point(-1, top_coord) except: pass
def library_return_count(self, genre=None, artist=None, album=None, year=None): # Because mpd's 'count' is case sensitive, we have to # determine all equivalent items (case insensitive) and # call 'count' for each of them. Using 'list' + 'count' # involves much less data to be transferred back and # forth than to use 'search' and count manually. searches = self.library_compose_list_count_searchlist(genre, artist, album, year) playtime = 0 num_songs = 0 for s in searches: if '' in s and mpdh.mpd_major_version(self.client) <= 0.13: # Can't return count for empty tags, use search instead: _results, playtime, num_songs = self.library_return_search_items(genre=genre, artist=artist, album=album, year=year) else: count = mpdh.call(self.client, 'count', *s) playtime += int(mpdh.get(count, 'playtime')) num_songs += int(mpdh.get(count, 'songs')) return (playtime, num_songs)
def _execute_info(self): if self.status['state'] in ['play', 'pause']: cmds = [(_("Title"), ('title',)), (_("Artist"), ('artist',)), (_("Album"), ('album',)), (_("Date"), ('date',)), (_("Track"), ('track', '0', False, 2)), (_("Genre"), ('genre',)), (_("File"), ('file',)), ] for pretty, cmd in cmds: mpdh.conout("%s: %s" % (pretty, mpdh.get(self.songinfo, *cmd))) at, _length = [int(c) for c in self.status['time'].split(':')] at_time = misc.convert_time(at) try: time = misc.convert_time(mpdh.get(self.songinfo, 'time', '', True)) print "%s: %s/%s" % (_("Time"), at_time, time) except: print "%s: %s" % (_("Time"), at_time) print "%s: %s" % (_("Bitrate"), self.status.get('bitrate', '')) else: print _("MPD stopped")