from datetime import datetime from quodlibet import print_d from quodlibet.formats import AudioFile from quodlibet.query import Query, QueryType from quodlibet.query._match import Tag, Inter, Union, Numcmp, NumexprTag, \ Numexpr, True_, False_ INVERSE_OPS = { operator.le: operator.gt, operator.gt: operator.le, operator.lt: operator.ge, operator.ge: operator.lt } _DUMMY_AF = AudioFile() _CLOCK = time.time def convert_time(t): return datetime.strftime(datetime.fromtimestamp(int(t)), '%Y-%m-%d %H:%S') # Convert QL to Soundcloud tags with optional value mapper _QL_TO_SC = { 'genre': ('genres', None), 'length': ('duration', lambda x: int((x or 0) * 1000)), 'date': ('created_at', convert_time), 'tags': ('tags', None), 'bpm': ('bpm', None), 'artist': ('q', None),
def parse(self): try: doc = feedparser.parse(self.uri) except: return False try: album = doc.channel.title except AttributeError: return False if album: self.name = album else: self.name = _("Unknown") defaults = AudioFile({"feed": self.uri}) try: self.__fill_af(doc.channel, defaults) except: return False entries = [] uris = set() for entry in doc.entries: try: for enclosure in entry.enclosures: try: if ("audio" in enclosure.type or "ogg" in enclosure.type or formats.filter(enclosure.url)): uri = enclosure.url.encode('ascii', 'replace') try: size = enclosure.length except AttributeError: size = 0 entries.append((uri, entry, size)) uris.add(uri) break except AttributeError: pass except AttributeError: pass for entry in list(self): if entry["~uri"] not in uris: self.remove(entry) else: uris.remove(entry["~uri"]) entries.reverse() for uri, entry, size in entries: if uri in uris: song = RemoteFile(uri) song["~#size"] = size song.fill_metadata = False song.update(defaults) song["album"] = self.name try: self.__fill_af(entry, song) except: pass else: self.insert(0, song) self.__lastgot = time.time() return bool(uris)
def test_Menu(self): self.create_plugin(name='Name', desc='Desc', funcs=['plugin_song']) self.handler.Menu(None, [AudioFile()])
# -*- coding: utf-8 -*- # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation from collections import defaultdict from quodlibet.formats import AudioFile from quodlibet.order.reorder import OrderWeighted, OrderShuffle from quodlibet.qltk.songmodel import PlaylistModel from tests import TestCase r0 = AudioFile({'~#rating': 0}) r1 = AudioFile({'~#rating': 0.33}) r2 = AudioFile({'~#rating': 0.66}) r3 = AudioFile({'~#rating': 1.0}) class TOrderWeighted(TestCase): def test_weighted(self): pl = PlaylistModel() pl.set([r3, r1, r2, r0]) order = OrderWeighted() scores = defaultdict(int) for i in range(500): order.reset(pl) cur = pl.current_iter for j in range(3, -1, -1): cur = order.next_explicit(pl, cur) scores[pl[cur][0]] += j
# Copyright 2017 Christoph Reiter # 2021 halfbrained@github # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. from gi.repository import Gtk from quodlibet.formats import AudioFile from quodlibet.util.songwrapper import SongWrapper from tests.plugin import PluginTestCase AUDIO_FILE = SongWrapper(AudioFile({'~filename': "/tmp/foobar"})) class Dummy: dummy_val = "str!" def dummy_meth(self, arg, varg=101): pass DUMMY_COMPLETIONS = [ ('dummy_meth', ' (arg, varg=101)'), ('dummy_val', ''), ] NAMESPACE_COMPLETIONS = ('dummy', '')
def test_bookmark_invalid(self): af = AudioFile({"~bookmark": ("Not Valid\n1:40 Mark 2\n" "-20 Not Valid 2\n1:20 Mark 1")}) self.failUnlessEqual( [(80, "Mark 1"), (100, "Mark 2"), (-1, "Not Valid"), (-1, "-20 Not Valid 2")], af.bookmarks)
# -*- coding: utf-8 -*- # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation from gi.repository import Gtk from tests import TestCase from quodlibet import config from quodlibet.formats import AudioFile from quodlibet.util.path import fsnative from quodlibet.qltk.delete import DeleteDialog, TrashDialog, TrashMenuItem SONG = AudioFile({"~filename": fsnative(u"/dev/null")}) SONG.sanitize() class TDeleteDialog(TestCase): def setUp(self): config.init() def tearDown(self): config.quit() def test_delete_songs(self): dialog = DeleteDialog.for_songs(None, []) dialog.destroy() def test_delete_files(self): dialog = DeleteDialog.for_files(None, [])
def test_mountpoint_no_value(self): af = AudioFile({"~filename": fsnative(u"foo")}) assert not Query(u"~mountpoint=bla").search(af)
def test_search_almostequal(self): a, b = AudioFile({"~#rating": 0.771}), AudioFile({"~#rating": 0.769}) self.failUnless(Query("#(rating = 0.77)").search(a)) self.failUnless(Query("#(rating = 0.77)").search(b))