class TOperonImageSet(TOperonBase): # <image-file> <file> [<files>] def setUp(self): super(TOperonImageSet, self).setUp() from gi.repository import GdkPixbuf h, self.filename = mkstemp(".png") os.close(h) wide = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 150, 10) wide.savev(self.filename, "png", [], []) self.fcover = get_temp_copy(get_data_path('test-2.wma')) self.cover = MusicFile(self.fcover) self.fcover2 = get_temp_copy(get_data_path('test-2.wma')) self.cover2 = MusicFile(self.fcover2) def tearDown(self): os.unlink(self.fcover) os.unlink(self.filename) super(TOperonImageSet, self).tearDown() def test_misc(self): self.check_true(["image-set", "-h"], True, False) self.check_false(["image-set", self.fcover], False, True) self.check_false(["image-set"], False, True) self.check_false(["image-set", self.filename], False, True) def test_not_supported(self): path = get_data_path('test.mid') out, err = self.check_false( ["image-set", self.filename, path], False, True) self.assertTrue("supported" in err) def test_set(self): self.check_true(["image-set", self.filename, self.fcover], False, False) self.check_true(["-v", "image-set", self.filename, self.fcover], False, True) self.cover.reload() images = self.cover.get_images() self.assertEqual(len(images), 1) with open(self.filename, "rb") as h: self.assertEqual(h.read(), images[0].read()) def test_set_two(self): self.check_true( ["image-set", self.filename, self.fcover, self.fcover2], False, False) with open(self.filename, "rb") as h: image_data = h.read() for audio in [self.cover, self.cover2]: audio.reload() image = audio.get_images()[0] self.assertEqual(image.read(), image_data)
class TOperonImageClear(TOperonBase): # <image-file> <file> [<files>] def setUp(self): super(TOperonImageClear, self).setUp() fd, self.fcover = mkstemp(".wma") os.close(fd) shutil.copy(os.path.join(DATA_DIR, 'test-2.wma'), self.fcover) self.cover = MusicFile(self.fcover) def tearDown(self): os.unlink(self.fcover) super(TOperonImageClear, self).tearDown() def test_misc(self): self.check_true(["image-clear", "-h"], True, False) self.check_true(["image-clear", self.fcover], False, False) self.check_false(["image-clear"], False, True) def test_not_supported(self): path = os.path.join(DATA_DIR, 'test.mid') out, err = self.check_false(["image-clear", path], False, True) self.assertTrue("supported" in err) def test_clear(self): images = self.cover.get_images() self.assertEqual(len(images), 1) self.check_true(["image-clear", self.fcover], False, False) self.cover.reload() images = self.cover.get_images() self.assertEqual(len(images), 0)
def setUp(self): super(TOperonImageExtract, self).setUp() h, self.fcover = mkstemp(".wma") os.close(h) shutil.copy(os.path.join(DATA_DIR, 'test-2.wma'), self.fcover) self.cover = MusicFile(self.fcover)
class TOperonImageSet(TOperonBase): # <image-file> <file> [<files>] def setUp(self): super(TOperonImageSet, self).setUp() from gi.repository import GdkPixbuf h, self.filename = mkstemp(".png") os.close(h) wide = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 150, 10) wide.savev(self.filename, "png", [], []) self.fcover = get_temp_copy(os.path.join(DATA_DIR, 'test-2.wma')) self.cover = MusicFile(self.fcover) self.fcover2 = get_temp_copy(os.path.join(DATA_DIR, 'test-2.wma')) self.cover2 = MusicFile(self.fcover2) def tearDown(self): os.unlink(self.fcover) os.unlink(self.filename) super(TOperonImageSet, self).tearDown() def test_misc(self): self.check_true(["image-set", "-h"], True, False) self.check_false(["image-set", self.fcover], False, True) self.check_false(["image-set"], False, True) self.check_false(["image-set", self.filename], False, True) def test_not_supported(self): path = os.path.join(DATA_DIR, 'test.mid') out, err = self.check_false(["image-set", self.filename, path], False, True) self.assertTrue("supported" in err) def test_set(self): self.check_true(["image-set", self.filename, self.fcover], False, False) self.check_true(["-v", "image-set", self.filename, self.fcover], False, True) self.cover.reload() images = self.cover.get_images() self.assertEqual(len(images), 1) with open(self.filename, "rb") as h: self.assertEqual(h.read(), images[0].read()) def test_set_two(self): self.check_true( ["image-set", self.filename, self.fcover, self.fcover2], False, False) with open(self.filename, "rb") as h: image_data = h.read() for audio in [self.cover, self.cover2]: audio.reload() image = audio.get_images()[0] self.assertEqual(image.read(), image_data)
class TOperonImageClear(TOperonBase): # <image-file> <file> [<files>] def setUp(self): super(TOperonImageClear, self).setUp() self.fcover = get_temp_copy(get_data_path('test-2.wma')) self.cover = MusicFile(self.fcover) def tearDown(self): os.unlink(self.fcover) super(TOperonImageClear, self).tearDown() def test_misc(self): self.check_true(["image-clear", "-h"], True, False) self.check_true(["image-clear", self.fcover], False, False) self.check_false(["image-clear"], False, True) def test_not_supported(self): path = get_data_path('test.mid') out, err = self.check_false(["image-clear", path], False, True) self.assertTrue("supported" in err) def test_clear(self): images = self.cover.get_images() self.assertEqual(len(images), 1) self.check_true(["image-clear", self.fcover], False, False) self.cover.reload() images = self.cover.get_images() self.assertEqual(len(images), 0)
class TOperonImageExtract(TOperonBase): # [--dry-run] [--primary] [-d <destination>] <file> [<files>] def setUp(self): super(TOperonImageExtract, self).setUp() h, self.fcover = mkstemp(".wma") os.close(h) shutil.copy(os.path.join(DATA_DIR, 'test-2.wma'), self.fcover) self.cover = MusicFile(self.fcover) def tearDown(self): os.unlink(self.fcover) super(TOperonImageExtract, self).tearDown() def test_misc(self): self.check_true(["image-extract", "-h"], True, False) self.check_true(["image-extract", self.f], False, False) self.check_true(["image-extract", self.f, self.f2], False, False) self.check_false(["image-extract"], False, True) def test_extract_all(self): target_dir = os.path.dirname(self.fcover) self.check_true(["image-extract", "-d", target_dir, self.fcover], False, False) self.assertEqual(len(self.cover.get_images()), 1) image = self.cover.get_primary_image() name = os.path.splitext(os.path.basename(self.fcover))[0] expected = "%s-00.%s" % (name, image.extensions[0]) expected_path = os.path.join(target_dir, expected) self.assertTrue(os.path.exists(expected_path)) with open(expected_path, "rb") as h: self.assertEqual(h.read(), image.file.read()) def test_extract_primary(self): target_dir = os.path.dirname(self.fcover) self.check_true( ["image-extract", "-d", target_dir, "--primary", self.fcover], False, False) self.assertEqual(len(self.cover.get_images()), 1) image = self.cover.get_primary_image() name = os.path.splitext(os.path.basename(self.fcover))[0] expected = "%s.%s" % (name, image.extensions[0]) expected_path = os.path.join(target_dir, expected) self.assertTrue(os.path.exists(expected_path)) with open(expected_path, "rb") as h: self.assertEqual(h.read(), image.file.read())
def setUp(self): config.init() self.f = get_temp_copy(get_data_path('silence-44-s.ogg')) self.f2 = get_temp_copy(get_data_path('silence-44-s.mp3')) self.s = MusicFile(self.f) self.s2 = MusicFile(self.f2) fd, self.f3 = mkstemp(".mp3") os.write(fd, b"garbage") os.close(fd)
def setUp(self): config.init() self.f = get_temp_copy(os.path.join(DATA_DIR, 'silence-44-s.ogg')) self.f2 = get_temp_copy(os.path.join(DATA_DIR, 'silence-44-s.mp3')) self.s = MusicFile(self.f) self.s2 = MusicFile(self.f2) fd, self.f3 = mkstemp(".mp3") os.write(fd, "garbage") os.close(fd)
class TAudioFileAllBase(object): FILE = None def setUp(self): fd, filename = mkstemp(os.path.splitext(self.FILE)[-1]) os.close(fd) shutil.copy(self.FILE, filename) self.song = MusicFile(filename) self.filename = filename def tearDown(self): try: os.remove(self.filename) except OSError: pass def test_clear_images_noent(self): os.remove(self.filename) self.assertRaises(AudioFileError, self.song.clear_images) def test_set_image_noent(self): os.remove(self.filename) image = EmbeddedImage(None, "image/png") self.assertRaises(AudioFileError, self.song.set_image, image) def test_get_primary_image_noent(self): os.remove(self.filename) self.assertTrue(self.song.get_primary_image() is None) def test_get_images_noent(self): os.remove(self.filename) self.assertEqual(self.song.get_images(), []) def test_write_noent(self): os.remove(self.filename) try: self.song.write() except AudioFileError: pass def test_load_noent(self): os.remove(self.filename) self.assertRaises(AudioFileError, type(self.song), self.filename) @classmethod def create_tests(cls): for i, file_ in enumerate(FILES): new_type = type(cls.__name__ + str(i), (cls, TestCase), {"FILE": file_}) assert new_type.__name__ not in globals() globals()[new_type.__name__] = new_type
def setUp(self): super(TOperonImageSet, self).setUp() from gi.repository import GdkPixbuf h, self.filename = mkstemp(".png") os.close(h) wide = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 150, 10) wide.savev(self.filename, "png", [], []) h, self.fcover = mkstemp(".wma") os.close(h) shutil.copy(os.path.join(DATA_DIR, 'test-2.wma'), self.fcover) self.cover = MusicFile(self.fcover)
def test_reload_externally_modified(self): config.set("editing", "save_to_songs", True) fn = self.quux("~filename") + ".mp3" shutil.copy(get_data_path('silence-44-s.mp3'), fn) orig = MusicFile(fn) copy = MusicFile(fn) orig["~#rating"] = SOME_RATING copy["~#rating"] = ANOTHER_RATING orig.write() orig.reload() copy.reload() # should pick up the change to the file assert orig("~#rating") == SOME_RATING, "reloading failed" assert copy( "~#rating") == SOME_RATING, "should have picked up external change"
def setUp(self): super(TOperonImageSet, self).setUp() from gi.repository import GdkPixbuf h, self.filename = mkstemp(".png") os.close(h) wide = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 150, 10) wide.savev(self.filename, "png", [], []) self.fcover = get_temp_copy(get_data_path('test-2.wma')) self.cover = MusicFile(self.fcover) self.fcover2 = get_temp_copy(get_data_path('test-2.wma')) self.cover2 = MusicFile(self.fcover2)
class TAudioFileAllBase(object): FILE = None def setUp(self): self.filename = get_temp_copy(self.FILE) self.song = MusicFile(self.filename) def tearDown(self): try: os.remove(self.filename) except OSError: pass def test_clear_images_noent(self): os.remove(self.filename) self.assertRaises(AudioFileError, self.song.clear_images) def test_set_image_noent(self): os.remove(self.filename) image = EmbeddedImage(None, "image/png") self.assertRaises(AudioFileError, self.song.set_image, image) def test_get_primary_image_noent(self): os.remove(self.filename) self.assertTrue(self.song.get_primary_image() is None) def test_get_images_noent(self): os.remove(self.filename) self.assertEqual(self.song.get_images(), []) def test_write_noent(self): os.remove(self.filename) try: self.song.write() except AudioFileError: pass def test_load_noent(self): os.remove(self.filename) self.assertRaises(AudioFileError, type(self.song), self.filename) @classmethod def create_tests(cls): for i, file_ in enumerate(FILES): new_type = type(cls.__name__ + str(i), (cls, TestCase), {"FILE": file_}) assert new_type.__name__ not in globals() globals()[new_type.__name__] = new_type
def get_all_music_files(paths, ignore_hidden=True): '''Recursively search in one or more paths for music files. By default, hidden files and directories are ignored.''' filenames = set() for p in paths: if os.path.isdir(p): for root, dirs, files in walk(p, followlinks=True, topdown=True): logging.debug("Walking %s", root) if ignore_hidden: files = [f for f in files if not is_hidden_path(f)] for dirname in dirs[:]: if is_hidden_path(dirname): dirs.remove(dirname) filenames.update(norm(os.path.join(root, f)) for f in files) else: filenames.add(norm(p)) logging.debug("Found %d files", len(filenames)) # Try to load every file as an audio file, and filter the # ones that aren't actually audio files for filename in filenames: if os.path.isfile(filename): logging.debug("Loading %r", filename) mf = MusicFile(filename) if mf is not None: yield mf
def test_decode_all(self): """Decode all kinds of formats using Gstreamer, to check if they all work and to notify us if a plugin is missing on platforms where we control the packaging. """ files = [ "coverart.wv", "empty.aac", "empty.flac", "empty.ogg", "empty.opus", "silence-44-s.mpc", "silence-44-s.sv8.mpc", "silence-44-s.tta", "test.mid", "test.spc", "test.vgm", "test.wma", "silence-44-s.spx", "empty.xm", ] for file_ in files: path = os.path.join(DATA_DIR, file_) song = MusicFile(path) if song is not None: self._check(song)
class TOperonImageSet(TOperonBase): # <image-file> <file> [<files>] def setUp(self): super(TOperonImageSet, self).setUp() from gi.repository import GdkPixbuf h, self.filename = mkstemp(".png") os.close(h) wide = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, 150, 10) wide.savev(self.filename, "png", [], []) h, self.fcover = mkstemp(".wma") os.close(h) shutil.copy(os.path.join(DATA_DIR, 'test-2.wma'), self.fcover) self.cover = MusicFile(self.fcover) def tearDown(self): os.unlink(self.fcover) os.unlink(self.filename) super(TOperonImageSet, self).tearDown() def test_misc(self): self.check_true(["image-set", "-h"], True, False) self.check_false(["image-set", self.fcover], False, True) self.check_false(["image-set"], False, True) self.check_false(["image-set", self.filename], False, True) def test_not_supported(self): path = os.path.join(DATA_DIR, 'test.mid') out, err = self.check_false( ["image-set", self.filename, path], False, True) self.assertTrue("supported" in err) def test_set(self): self.check_true(["image-set", self.filename, self.fcover], False, False) self.check_true(["-v", "image-set", self.filename, self.fcover], False, True) self.cover.reload() images = self.cover.get_images() self.assertEqual(len(images), 1) with open(self.filename, "rb") as h: self.assertEqual(h.read(), images[0].file.read())
def __init__(self, track, pltag=None): if isinstance(track, str): self.track = MusicFile(track) elif isinstance(track, quodlibet.formats._audio.AudioFile): self.track = track else: raise TypeError("track must be either a quodlibet audiofile or a path to a music file.") self.pltag = pltag or 'playlist'
def load_song(self, path): """Load a song. Raises CommandError in case it fails""" self.log("Load file: %r" % path) song = MusicFile(path) if not song: raise CommandError(_("Failed to load file: %r") % path) return song
def test_analyze_silence(self): song = MusicFile(get_data_path("silence-44-s.ogg")) self.failIf(song("~replaygain_track_gain")) self._analyse_song(song) self.failUnlessAlmostEqual(song("~#replaygain_track_peak"), 0.0, msg="Track peak should be 0.0") track_gain = song("~#replaygain_track_gain") self.failUnless(track_gain, msg="No Track Gain added") # For one-song album, track == album self.failUnlessEqual(track_gain, song('~#replaygain_album_gain'))
def test_analyze_sinewave(self): song = MusicFile(get_data_path("sine-110hz.flac")) self.failUnlessEqual(song("~#length"), 2) self.failIf(song("~replaygain_track_gain")) self._analyse_song(song) self.failUnlessAlmostEqual(song("~#replaygain_track_peak"), 1.0, msg="Track peak should be 1.0") track_gain = song("~#replaygain_track_gain") self.failUnless(track_gain, msg="No Track Gain added") self.failUnless(re.match(r'\-[0-9]\.[0-9]{1,2}', str(track_gain))) # For one-song album, track == album self.failUnlessEqual(track_gain, song('~#replaygain_album_gain'))
def test_analyze_silence(self): pipeline = self.mod.analyze.FingerPrintPipeline() song = MusicFile(get_data_path("silence-44-s.ogg")) done = [] def callback(self, *args): done.extend(args) pipeline.start(song, callback) t = time.time() while not done and time.time() - t < self.TIMEOUT: Gtk.main_iteration_do(False) self.assertTrue(done) s, result, error = done # silence doesn't produce a fingerprint self.assertTrue(error) self.assertFalse(result) self.assertTrue(song is s)
class PLTrack(object): '''Extends MusicFile with convenience methods for accessing playlists.''' def __init__(self, track, pltag=None): if isinstance(track, str): self.track = MusicFile(track) elif isinstance(track, quodlibet.formats._audio.AudioFile): self.track = track else: raise TypeError("track must be either a quodlibet audiofile or a path to a music file.") self.pltag = pltag or 'playlist' def get_playlists(self): """Get the set of playlists of which this track is a member.""" playlists = self.track.get(self.pltag) if playlists: return tuple(playlists.split("\n")) else: return tuple()
def test_analyze_pool(self): pool = self.mod.analyze.FingerPrintPool() song = MusicFile(os.path.join(DATA_DIR, "silence-44-s.ogg")) events = [] def handler(*args): events.append(args) pool.connect("fingerprint-started", handler, "start") pool.connect("fingerprint-done", handler, "done") pool.connect("fingerprint-error", handler, "error") pool.push(song) t = time.time() while len(events) < 2 and time.time() - t < self.TIMEOUT: Gtk.main_iteration_do(False) self.assertEqual(len(events), 2) self.assertEqual(events[0][-1], "start") self.assertEqual(events[1][-1], "error")
def test_decode_all(self): """Decode all kinds of formats using Gstreamer, to check if they all work and to notify us if a plugin is missing on platforms where we control the packaging. """ files = [ "coverart.wv", "empty.aac", "empty.flac", "empty.ogg", "empty.opus", "silence-44-s.mpc", "silence-44-s.sv8.mpc", "silence-44-s.tta", # "test.mid", "test.spc", "test.vgm", "test.wma", "empty.xm", "h264_aac.mp4", "h265_aac.mp4" ] if not matches_flatpak_runtime("*org.gnome.*/3.32"): # https://gitlab.com/freedesktop-sdk/freedesktop-sdk/issues/809 files.append("silence-44-s.spx") errors = [] for file_ in files: path = get_data_path(file_) song = MusicFile(path) if song is not None: error = self._check(song) if error: errors.append((song("~format"), error)) if errors: raise Exception("Decoding failed %r" % errors)
def add_filename(self, filename, add=True): """Add a song to the library based on filename. If 'add' is true, the song will be added and the 'added' signal may be fired. Example (add=False): load many songs and call Library.add(songs) to add all in one go. The song is returned if it is in the library after this call. Otherwise, None is returned. """ song = None if filename not in self._contents: song = MusicFile(filename) if song and add: self.add([song]) else: print_d("Already got file %r." % filename) song = self._contents[filename] return song
def test_decode_all(self): """Decode all kinds of formats using Gstreamer, to check if they all work and to notify us if a plugin is missing on platforms where we control the packaging. """ files = [ "coverart.wv", "empty.aac", "empty.flac", "empty.ogg", "empty.opus", "silence-44-s.mpc", "silence-44-s.sv8.mpc", "silence-44-s.tta", # "test.mid", "test.spc", "test.vgm", "test.wma", "silence-44-s.spx", "empty.xm", "h264_aac.mp4", "h265_aac.mp4" ] errors = [] for file_ in files: path = get_data_path(file_) song = MusicFile(path) if song is not None: error = self._check(song) if error: errors.append((song("~format"), error)) if errors: raise Exception("Decoding failed %r" % errors)
def setUp(self): super(TOperonImageClear, self).setUp() self.fcover = get_temp_copy(os.path.join(DATA_DIR, 'test-2.wma')) self.cover = MusicFile(self.fcover)
def test_reload_fail(self): audio = MusicFile(os.path.join(DATA_DIR, 'silence-44-s.mp3')) audio["title"] = u"foo" audio.sanitize(fsnative(u"/dev/null")) self.assertRaises(AudioFileError, audio.reload) self.assertEqual(audio["title"], u"foo")
def setUp(self): fd, filename = mkstemp(os.path.splitext(self.FILE)[-1]) os.close(fd) shutil.copy(self.FILE, filename) self.song = MusicFile(filename) self.filename = filename
def test_reload(self): audio = MusicFile(os.path.join(DATA_DIR, 'silence-44-s.mp3')) audio["title"] = u"foo" audio.reload() self.assertNotEqual(audio.get("title"), u"foo")
def setUp(self): super(TOperonImageClear, self).setUp() self.fcover = get_temp_copy(get_data_path('test-2.wma')) self.cover = MusicFile(self.fcover)
def setUp(self): self.filename = get_temp_copy(self.FILE) self.song = MusicFile(self.filename)
def test_reload(self): audio = MusicFile(get_data_path('silence-44-s.mp3')) audio["title"] = u"foo" audio.reload() self.assertNotEqual(audio.get("title"), u"foo")
def setUp(self): super().setUp() self.fcover = get_temp_copy(get_data_path('test-2.wma')) self.cover = MusicFile(self.fcover)
def test_reload_fail(self): audio = MusicFile(get_data_path('silence-44-s.mp3')) audio["title"] = u"foo" audio.sanitize(fsnative(u"/dev/null")) self.assertRaises(AudioFileError, audio.reload) self.assertEqual(audio["title"], u"foo")