1# Copyright 2013 Christoph Reiter 2# 3# This program is free software; you can redistribute it and/or modify 4# it under the terms of the GNU General Public License as published by 5# the Free Software Foundation; either version 2 of the License, or 6# (at your option) any later version. 7 8import os 9from io import BytesIO 10 11from mutagen import asf 12 13from tests import TestCase, get_data_path 14from quodlibet.formats.wma import WMAFile, unpack_image, pack_image 15from quodlibet.formats._image import APICType, EmbeddedImage 16 17from .helper import get_temp_copy 18 19 20class TWMAFile(TestCase): 21 22 def setUp(self): 23 self.f = get_temp_copy(get_data_path('test.wma')) 24 self.song = WMAFile(self.f) 25 26 self.f2 = get_temp_copy(get_data_path('test-2.wma')) 27 self.song2 = WMAFile(self.f2) 28 29 self.f3 = get_temp_copy(get_data_path('test.asf')) 30 self.song3 = WMAFile(self.f3) 31 32 def tearDown(self): 33 os.unlink(self.f) 34 os.unlink(self.f2) 35 os.unlink(self.f3) 36 37 def test_basic(self): 38 self.song["title"] = u"SomeTestValue" 39 self.song.write() 40 self.song.reload() 41 self.assertEqual(self.song("title"), u"SomeTestValue") 42 43 def test_multi(self): 44 self.song["genre"] = u"Rock\nPop" 45 self.song.write() 46 self.song.reload() 47 # XXX: mutagen doesn't preserve order.. fix it! 48 self.assertEqual(set(self.song.list("genre")), {u"Rock", u"Pop"}) 49 50 def test_length(self): 51 self.assertAlmostEqual(self.song("~#length"), 3.7120, 3) 52 self.assertAlmostEqual(self.song2("~#length"), 3.684, 3) 53 self.assertAlmostEqual(self.song3("~#length"), 11.38, 2) 54 55 def test_channels(self): 56 assert self.song("~#channels") == 2 57 assert self.song2("~#channels") == 2 58 assert self.song3("~#channels") == 1 59 60 def test_bitrate(self): 61 self.assertEqual(self.song("~#bitrate"), 64) 62 self.assertEqual(self.song2("~#bitrate"), 38) 63 self.assertEqual(self.song3("~#bitrate"), 5) 64 65 def test_sample_rate(self): 66 assert self.song("~#samplerate") == 48000 67 assert self.song2("~#samplerate") == 44100 68 assert self.song3("~#samplerate") == 8000 69 70 def test_write(self): 71 self.song.write() 72 self.song2.write() 73 self.song3.write() 74 75 def test_can_change(self): 76 self.assertTrue(self.song.can_change("title")) 77 self.assertFalse(self.song.can_change("foobar")) 78 self.assertTrue("albumartist" in self.song.can_change()) 79 80 def test_format(self): 81 self.assertEqual(self.song("~format"), "ASF") 82 self.assertEqual(self.song2("~format"), "ASF") 83 self.assertEqual(self.song3("~format"), "ASF") 84 85 def test_codec(self): 86 self.assertEqual(self.song("~codec"), 87 u"Windows Media Audio 9 Standard") 88 self.assertEqual(self.song2("~codec"), 89 u"Windows Media Audio 9 Professional") 90 self.assertEqual(self.song3("~codec"), 91 u"Intel G.723") 92 93 def test_encoding(self): 94 self.assertEqual( 95 self.song("~encoding"), 96 u"Windows Media Audio 9.1\n64 kbps, 48 kHz, stereo 2-pass CBR") 97 self.assertEqual( 98 self.song2("~encoding"), 99 (u"Windows Media Audio 9.1 Professional\n192 kbps, 44 kHz, " 100 "2 channel 24 bit 2-pass VBR")) 101 self.assertEqual(self.song3("~encoding"), 102 u"Microsoft G.723.1\n8 kHz Mono, 5333 Bit/s") 103 104 def test_mb_release_track_id(self): 105 tag = asf.ASF(self.f) 106 tag["MusicBrainz/Release Track Id"] = [u"foo"] 107 tag.save() 108 song = WMAFile(self.f) 109 self.assertEqual(song("musicbrainz_releasetrackid"), u"foo") 110 song["musicbrainz_releasetrackid"] = u"bla" 111 song.write() 112 tag = asf.ASF(self.f) 113 self.assertEqual(tag["MusicBrainz/Release Track Id"], [u"bla"]) 114 115 def test_invalid(self): 116 path = get_data_path('empty.xm') 117 self.assertTrue(os.path.exists(path)) 118 self.assertRaises(Exception, WMAFile, path) 119 120 def test_get_images(self): 121 tag = asf.ASF(self.f2) 122 tag["WM/Picture"] = [tag["WM/Picture"][0], tag["WM/Picture"][0]] 123 tag.save() 124 self.song2.reload() 125 126 images = self.song2.get_images() 127 self.assertTrue(images and len(images) == 2) 128 129 def test_get_image(self): 130 self.assertFalse(self.song.get_primary_image()) 131 132 image = self.song2.get_primary_image() 133 self.assertTrue(image) 134 self.assertEqual(image.mime_type, "image/jpeg") 135 self.assertTrue(image.read()) 136 137 def test_get_image_invalid_data(self): 138 tag = asf.ASF(self.f) 139 tag["WM/Picture"] = [asf.ASFValue(b"nope", asf.BYTEARRAY)] 140 tag.save() 141 142 self.assertFalse(self.song.has_images) 143 self.song.reload() 144 self.assertTrue(self.song.has_images) 145 146 image = self.song.get_primary_image() 147 self.assertFalse(image) 148 149 def test_unpack_image_min(self): 150 data = b"\x03" + b"\x00" * 4 + b"\x00" * 4 151 mime, desc, data, type_ = unpack_image(data) 152 self.assertEqual(mime, u"") 153 self.assertEqual(desc, u"") 154 self.assertEqual(data, b"") 155 self.assertEqual(type_, 3) 156 157 def test_unpack_image_invalid(self): 158 self.assertRaises(ValueError, unpack_image, b"") 159 self.assertRaises(ValueError, unpack_image, b"\x00" * 6) 160 self.assertRaises(ValueError, unpack_image, b"\x00" * 8) 161 self.assertRaises(ValueError, unpack_image, b"\x00" * 100) 162 163 def test_pack_image(self): 164 d = pack_image( 165 u"image/jpeg", u"Description", b"foo", APICType.COVER_FRONT) 166 mime, desc, data, type_ = unpack_image(d) 167 self.assertEqual(mime, u"image/jpeg") 168 self.assertEqual(desc, u"Description") 169 self.assertEqual(data, b"foo") 170 self.assertEqual(type_, APICType.COVER_FRONT) 171 172 def test_clear_images(self): 173 # cover case 174 image = self.song2.get_primary_image() 175 self.assertTrue(image) 176 self.song2.clear_images() 177 self.assertFalse(self.song2.has_images) 178 self.song2.reload() 179 image = self.song2.get_primary_image() 180 self.assertFalse(image) 181 182 # no cover case 183 self.song.clear_images() 184 185 def test_set_image(self): 186 fileobj = BytesIO(b"foo") 187 image = EmbeddedImage(fileobj, "image/jpeg", 10, 10, 8) 188 self.assertFalse(self.song.has_images) 189 self.song.set_image(image) 190 self.assertTrue(self.song.has_images) 191 192 image = self.song.get_primary_image() 193 self.assertEqual(image.mime_type, "image/jpeg") 194 self.assertEqual(image.read(), b"foo") 195 196 def test_can_change_images(self): 197 self.assertTrue(self.song.can_change_images) 198 199 def test_can_multiple_values(self): 200 self.assertTrue("artist" in self.song.can_multiple_values()) 201 self.assertTrue(self.song.can_multiple_values("genre")) 202