def updateEdited(self, data): if self.__searchResults: return self.blockSignals(True) artists = [ to_string(tag.get('artist', artist)) for artist, tag in data ] self.updateDeleted(artists=[to_string(z[0]) for z in data]) get_albums = self.library.get_albums newartists = [] for artist in set(artists): artist_item = self.findItems(artist, Qt.MatchExactly) if artist_item: artist_item = artist_item[0] albums = get_albums(artist) tree_albums = artist_item.albums children = (ChildItem(album, artist, artist_item) for album in albums if album not in tree_albums) map(partial(select_add_child, artist_item), children) self.expandItem(artist_item) else: newartists.append(artist) if newartists: self.fillFromLib(self.library, newartists) self.blockSignals(False)
def updateEdited(self, data): if self.__searchResults: return self.blockSignals(True) artists = [to_string(tag.get('artist', artist)) for artist, tag in data] self.updateDeleted(artists = [to_string(z[0]) for z in data]) get_albums = self.library.get_albums newartists = [] for artist in set(artists): artist_item = self.findItems(artist, Qt.MatchExactly) if artist_item: artist_item = artist_item[0] albums = get_albums(artist) tree_albums = artist_item.albums children = (ChildItem(album, artist, artist_item) for album in albums if album not in tree_albums) map(partial(select_add_child, artist_item), children) self.expandItem(artist_item) else: newartists.append(artist) if newartists: self.fillFromLib(self.library, newartists) self.blockSignals(False)
def split_by_tag(tracks, main='artist', secondary='album'): if secondary: ret = defaultdict(lambda: defaultdict(lambda: [])) [ret[to_string(track.get(main))] [to_string(track.get(secondary))].append(track) for track in tracks] else: ret = defaultdict(lambda: []) [ret[to_string(track.get(main))].append(track) for track in tracks] return ret
def delete(self, track): artist = to_string(track.get('artist', u'')) album = to_string(track.get('album', u'')) self._cached[artist][album].remove(track) self._tracks.remove(track) if not self._cached[artist][album]: del(self._cached[artist][album]) if not self._cached[artist]: del(self._cached[artist]) self.edited = True
def delete(self, track): artist = to_string(track.get('artist', u'')) album = to_string(track.get('album', u'')) self._cached[artist][album].remove(track) self._tracks.remove(track) if not self._cached[artist][album]: del (self._cached[artist][album]) if not self._cached[artist]: del (self._cached[artist]) self.edited = True
def split_by_tag(tracks, main='artist', secondary='album'): if secondary: ret = defaultdict(lambda: defaultdict(lambda: [])) [ ret[to_string(track.get(main))][to_string( track.get(secondary))].append(track) for track in tracks ] else: ret = defaultdict(lambda: []) [ret[to_string(track.get(main))].append(track) for track in tracks] return ret
def parse_arg(audio, text): if not isinstance(text, basestring): return text if text[0] == u'%' and text[-1] == u'%': return to_string(audio.get(text[1:-1], u'')) elif text in FIELDS: return to_string(audio.get(text, u'')) else: if text[0] == u'"' and text[-1] == u'"': text = text[1:-1] return findfunc.parsefunc(text, audio) return u""
def runFunction (self, text=None, m_tags=None, state=None, tags=None, r_tags=None): func = self.function varnames = func.func_code.co_varnames[:func.func_code.co_argcount] if not varnames: return func() s_audio = stringtags(m_tags) if tags is None else tags m_audio = m_tags state = {} if state is None else state m_text = to_list(text) text = to_string(text) reserved = {'tags': s_audio, 'm_tags': m_audio, 'state': state, 'r_tags': r_tags, 'm_text': m_text} if varnames[0] in reserved: reserved = {'tags': s_audio, 'm_tags': m_audio, 'state': state, 'r_tags': r_tags, 'text': to_string(text), 'm_text': m_text} topass = get_function_arguments("", func, self.args, reserved, False, *[s_audio, state]) return func(**topass) else: reserved = {'tags': s_audio, 'm_tags': m_audio, 'state': state, 'r_tags': r_tags} topass = get_function_arguments("", func, [text] + self.args, reserved, False, *[s_audio, state]) try: first_arg = [z for z in varnames if z not in reserved][0] except IndexError: return if not first_arg.startswith('m_'): text = [to_string(z) for z in to_list(m_text)] ret = [] for z in m_text: topass[first_arg] = z ret.append(func(**topass)) temp = [] append = temp.append [append(z) for z in ret if z not in temp] return temp else: topass[first_arg] return func(**topass)
def brute_force_results(audios, retrieved): matched = {} audios = sorted(audios, natcasecmp, lambda f: to_string(f.get('track', f['__filename']))) retrieved = sorted(retrieved, natcasecmp, lambda t: to_string(t.get('track', t.get('title' , u'')))) for audio, result in zip(audios, retrieved): matched[audio] = result return matched
def brute_force_results(audios, retrieved): matched = {} audios = sorted(audios, natcasecmp, lambda f: to_string(f.get('track', f['__filename']))) retrieved = sorted( retrieved, natcasecmp, lambda t: to_string(t.get('track', t.get('title', u'')))) for audio, result in zip(audios, retrieved): matched[audio] = result return matched
def save(self, justrename=False): libtags = self._libtags tags = self.__tags newartist = to_string(tags.get('artist', [u''])) oldartist = libtags.get('artist', u'') newalbum = to_string(tags.get('album', [u''])) oldalbum = libtags.get('album', u'') self._libtags.update(self._tolibformat()) self._libtags.write() if (newartist != oldartist) or (newalbum != oldalbum): self.library.update(oldartist, oldalbum, libtags) self.library.edited = True self.update_tag_list()
def save(self, justrename = False): libtags = self._libtags tags = self.__tags newartist = to_string(tags.get('artist', [u''])) oldartist = libtags.get('artist', u'') newalbum = to_string(tags.get('album', [u''])) oldalbum = libtags.get('album', u'') self._libtags.update(self._tolibformat()) self._libtags.write() if (newartist != oldartist) or (newalbum != oldalbum): self.library.update(oldartist, oldalbum, libtags) self.library.edited = True self.update_tag_list()
def replace_tracknumbers(files, tracks): if len(files) != len(tracks): return files = sorted(files, cmp=natcasecmp, key=lambda f: to_string(f.get('track', f[FILENAME]))) try: tracks = sorted(tracks, cmp=natcasecmp, key=itemgetter('track')) tracks = sorted(tracks, cmp=natcasecmp, key=itemgetter('discnumber')) except KeyError: return if len(files) == len(tracks): discnum = 1 track_count = 0 offset = 0 for f, t in zip(files, tracks): track_count += 1 try: new_discnum = to_int(t['discnumber']) except (ValueError, TypeError): continue if new_discnum > discnum: offset = track_count - 1 discnum = new_discnum try: f_tracknum = to_int(f['track']) t_tracknum = to_int(t['track']) except (ValueError, TypeError, KeyError): continue if f_tracknum > t_tracknum: f['track'] = [unicode(f_tracknum - offset)]
def search_replace(parent=None): selectedfiles = status['selectedfiles'] audio, selected = status['firstselection'] try: text = to_string(selected.values()[0]) except IndexError: text = translate('Defaults', u'') func = puddlestuff.findfunc.Function('replace') func.args = [text, text, False, False] func.tag = ['__selected'] dialog = actiondlg.CreateFunction(prevfunc=func, parent=parent, selected_fields=selected.keys(), example=audio, text=text) dialog.connect(dialog, SIGNAL("valschanged"), partial(run_func, selectedfiles)) dialog.setModal(True) dialog.controls[0].combo.setFocus() dialog.show()
def get_match_str(info): artist = album = None if info.get('artist'): artist = to_string(info['artist']) if info.get('album'): album = to_string(info['album']) if artist and album: return MATCH_ARTIST_ALBUM.arg(artist).arg(album) elif artist: return MATCH_ARTIST.arg(artist) elif album: return MATCH_ALBUM.arg(album) else: return MATCH_NO_INFO
def replace_tracknumbers(files, tracks): if len(files) != len(tracks): return files = sorted(files, cmp=natcasecmp, key=lambda f: to_string(f.get('track', f[FILENAME]))) try: tracks = sorted(tracks, cmp=natcasecmp, key=itemgetter('track')) tracks = sorted(tracks, cmp=natcasecmp, key=itemgetter('discnumber')) except KeyError: return if len(files) == len(tracks): discnum = 1 track_count = 0 offset = 0 for f, t in zip(files, tracks): track_count += 1 try: new_discnum = to_int(t['discnumber']) except (ValueError, TypeError): continue if new_discnum > discnum: offset = track_count - 1 discnum = new_discnum try: f_tracknum = to_int(f['track']) t_tracknum = to_int(t['track']) except (ValueError, TypeError, KeyError): continue if f_tracknum > t_tracknum: f['track'] = [unicode(f_tracknum - offset )]
def updateDeleted(self, tracks=None, artists=None): if self.__searchResults: return if tracks: data = set( [to_string(track.get['artist'], u'') for track in tracks]) else: data = set(artists) lib_artists = self.library.artists get_albums = self.library.get_albums index = self.indexOfTopLevelItem take_item = self.takeTopLevelItem for artist in data: artist_item = self.findItems(artist, Qt.MatchExactly)[0] if artist in lib_artists: albums = get_albums(artist) remove = artist_item.removeChild children = artist_item.children toremove = [ch for ch in children if ch.album not in albums] [remove(child) for child in toremove] else: take_item(index(artist_item))
def updateDeleted(self, tracks=None, artists = None): if self.__searchResults: return if tracks: data = set([to_string(track.get['artist'], u'') for track in tracks]) else: data = set(artists) lib_artists = self.library.artists get_albums = self.library.get_albums index = self.indexOfTopLevelItem take_item = self.takeTopLevelItem for artist in data: artist_item = self.findItems(artist, Qt.MatchExactly)[0] if artist in lib_artists: albums = get_albums(artist) remove = artist_item.removeChild children = artist_item.children toremove = [ch for ch in children if ch.album not in albums] [remove(child) for child in toremove] else: take_item(index(artist_item))
def id_in_tag(tag): if 'acoustid_fingerprint' in tag: fp = to_string(tag['acoustid_fingerprint']) else: return if '__length' in tag: duration = audioinfo.lnglength(tag['__length']) else: return return (duration, fp)
def calculate_discid(album): #from quodlibet's cddb plugin by Michael Urman album = sorted(album, key=sort_func('__filename', u'')) album = sorted(album, key=sort_func('track', u'1')) lengths = [audioinfo.lnglength(to_string(song['__length'])) for song in album] total_time = 0 offsets = [] for length in lengths: offsets.append(total_time) total_time += length checksum = sum(map(sumdigits, offsets)) discid = ((checksum % 0xff) << 24) | (total_time << 8) | len(album) return [discid, len(album)] + [75 * o for o in offsets] + [total_time]
def _settag(self, row, field, value, status=None, preview=False, check=False, multi=False): tb = self.table tb.setSortingEnabled(False) if row >= tb.rowCount(): tb.insertRow(row) field_item = StatusWidgetItem(field, status, self._colors, preview) tb.setItem(row, 0, field_item) if not multi and (len(value) == 1 or isinstance(value, basestring)): valitem = StatusWidgetItem(to_string(value), status, self._colors, preview) tb.setItem(row, 1, valitem) else: valitem = StatusWidgetCombo(value, status, self._colors, preview) tb.setCellWidget(row, 1, valitem) else: field_item = tb.item(row, 0) field_item.setText(field) field_item.status = status val_item = self.get_item(row, 1) val_item.setText(value) val_item.status = status if check: lowered_tag = field.lower() for row in xrange(tb.rowCount()): item = tb.item(row, 0) text = unicode(item.text()) if text != field and text.lower() == lowered_tag: item.setText(field) if item.status not in [ADD, REMOVE]: item.status = EDIT try: tb.item(row, 1).status = EDIT except AttributeError: tb.cellWidget(row, 1).status = EDIT tb.setSortingEnabled(True) return field_item
def calculate_discid(album): #from quodlibet's cddb plugin by Michael Urman album = sorted(album, key=sort_func('__filename', u'')) album = sorted(album, key=sort_func('track', u'1')) lengths = [ audioinfo.lnglength(to_string(song['__length'])) for song in album ] total_time = 0 offsets = [] for length in lengths: offsets.append(total_time) total_time += length checksum = sum(map(sumdigits, offsets)) discid = ((checksum % 0xff) << 24) | (total_time << 8) | len(album) return [discid, len(album)] + [75 * o for o in offsets] + [total_time]
def apply_regexps(audio, regexps=None): if regexps is None: regexps = DEFAULT_REGEXP audio = deepcopy(audio) changed = False for field, (regexp, output) in regexps.iteritems(): if field not in audio: continue text = to_string(audio[field]) try: val = replace_regex(audio, text, regexp, output) if val: audio[field] = val if not changed and val != text: changed = val except puddlestuff.findfunc.FuncError: continue return changed, audio
def check_result(result, audios): track_nums = filter(None, [to_string(audio.get('track', None)) for audio in audios]) if result.tracks is None: return True if track_nums: max_num = 0 for num in track_nums: try: num = int(num) except (TypeError, ValueError): continue max_num = num if num > max_num else max_num if max_num != 0 and max_num == len(result.tracks): return True if len(audios) == len(result.tracks): return True return False
def check_result(result, audios): track_nums = filter( None, [to_string(audio.get('track', None)) for audio in audios]) if result.tracks is None: return True if track_nums: max_num = 0 for num in track_nums: try: num = int(num) except (TypeError, ValueError): continue max_num = num if num > max_num else max_num if max_num != 0 and max_num == len(result.tracks): return True if len(audios) == len(result.tracks): return True return False
'~picture': lambda value: {'__picture': value}, }) time_fields = ['__added', '__lastplayed', '__laststarted',] timefunc = lambda key: lambda value : {'~#%s' % key[2:]: lngtime(value)} revmapping = dict([(key, timefunc(key)) for key in time_fields]) revmapping.update({ 'track': lambda value: {'tracknumber': value}, '__bitrate' : lambda value: {'~#bitrate': lngfrequency(value)}, '__length': lambda value: {'~#length': lnglength(value)}, 'playcount': lambda value: {'~#playcount': int(value)}, 'rating': lambda value: {'~#rating': float(value)}, '__skipcount': lambda value: {'~#skipcount': int(value)}, '__mountpoint': lambda value: {'~mountpoint': value}, '__modified': lambda value : {'~#mtime': lngtime(value)}, '__picture': lambda value: {'~picture': to_string(value)}, }) class Tag(MockTag): """Use as base for all tag classes.""" mapping = audioinfo.mapping.get('puddletag', {}) revmapping = audioinfo.revmapping.get('puddletag', {}) IMAGETAGS = () def __init__(self, libclass, libtags): MockTag.__init__(self) self.__tags = CaselessDict() tags = self.__tags tags.update(self.load(libtags['~filename'])[0])
def add_track(track): artist = to_string(track.get(artist_field, u'')) album = to_string(track.get(album_field, u'')) grouped[artist][album].append(track)
def runFunction(self, text=None, m_tags=None, state=None, tags=None, r_tags=None): func = self.function varnames = func.func_code.co_varnames[:func.func_code.co_argcount] if not varnames: return func() s_audio = stringtags(m_tags) if tags is None else tags m_audio = m_tags state = {} if state is None else state m_text = to_list(text) text = to_string(text) reserved = { 'tags': s_audio, 'm_tags': m_audio, 'state': state, 'r_tags': r_tags, 'm_text': m_text } if varnames[0] in reserved: reserved = { 'tags': s_audio, 'm_tags': m_audio, 'state': state, 'r_tags': r_tags, 'text': to_string(text), 'm_text': m_text } topass = get_function_arguments("", func, self.args, reserved, False, *[s_audio, state]) return func(**topass) else: reserved = { 'tags': s_audio, 'm_tags': m_audio, 'state': state, 'r_tags': r_tags } topass = get_function_arguments("", func, [text] + self.args, reserved, False, *[s_audio, state]) try: first_arg = [z for z in varnames if z not in reserved][0] except IndexError: return if not first_arg.startswith('m_'): text = [to_string(z) for z in to_list(m_text)] ret = [] for z in m_text: topass[first_arg] = z ret.append(func(**topass)) temp = [] append = temp.append [append(z) for z in ret if z not in temp] return temp else: topass[first_arg] return func(**topass)
def func(audio): track = to_string(audio.get(key, [default])) try: return int(track) except: return track
def sort(self, order=None, reverse=False): sortfunc = lambda item: u''.join([ to_string(item.itemData.get(key, u'')) for key in order]).lower() self.childItems.sort(natcasecmp, sortfunc, reverse)
if info.get('artist'): artist = to_string(info['artist']) if info.get('album'): album = to_string(info['album']) if artist and album: return MATCH_ARTIST_ALBUM.arg(artist).arg(album) elif artist: return MATCH_ARTIST.arg(artist) elif album: return MATCH_ALBUM.arg(album) else: return MATCH_NO_INFO get_lower = lambda f, key, default=u'': to_string(f.get(key,default)).lower() def ratio_compare(d1, d2, key): return ratio(get_lower(d1, key, u'a'), get_lower(d2, key, u'b')) def match_files(files, tracks, minimum=0.7, keys=None, jfdi=False, existing=False, as_index=False): if not keys: keys = ['artist', 'title'] if 'track' in keys and len(keys) > 1: keys = keys[::] keys.remove('track') ret = {} replace_tracknumbers(files, tracks) assigned = {}
def sort(self, order=None, reverse=False): sortfunc = lambda item: u''.join( [to_string(item.itemData.get(key, u'')) for key in order]).lower() self.childItems.sort(natcasecmp, sortfunc, reverse)
def to_int(v): return int(to_string(v))
artist = to_string(info['artist']) if info.get('album'): album = to_string(info['album']) if artist and album: return MATCH_ARTIST_ALBUM.arg(artist).arg(album) elif artist: return MATCH_ARTIST.arg(artist) elif album: return MATCH_ALBUM.arg(album) else: return MATCH_NO_INFO get_lower = lambda f, key, default=u'': to_string(f.get(key, default)).lower() def ratio_compare(d1, d2, key): return ratio(get_lower(d1, key, u'a'), get_lower(d2, key, u'b')) def match_files(files, tracks, minimum=0.7, keys=None, jfdi=False, existing=False, as_index=False): if not keys:
'~#playcount': int(value) }, 'rating': lambda value: { '~#rating': float(value) }, '__skipcount': lambda value: { '~#skipcount': int(value) }, '__mountpoint': lambda value: { '~mountpoint': value }, '__modified': lambda value: { '~#mtime': lngtime(value) }, '__picture': lambda value: { '~picture': to_string(value) }, }) class Tag(MockTag): """Use as base for all tag classes.""" mapping = audioinfo.mapping.get('puddletag', {}) revmapping = audioinfo.revmapping.get('puddletag', {}) IMAGETAGS = () def __init__(self, libclass, libtags): MockTag.__init__(self) self.__tags = CaselessDict() tags = self.__tags