1# -*- coding: utf-8 -*-
2
3import os
4
5from mutagen.id3 import ID3, TIT2
6from mutagen.musepack import Musepack, MusepackInfo, MusepackHeaderError
7from mutagen._compat import cBytesIO
8from tests import TestCase, DATA_DIR, get_temp_copy
9
10
11class TMusepack(TestCase):
12
13    def setUp(self):
14        self.sv8 = Musepack(os.path.join(DATA_DIR, "sv8_header.mpc"))
15        self.sv7 = Musepack(os.path.join(DATA_DIR, "click.mpc"))
16        self.sv5 = Musepack(os.path.join(DATA_DIR, "sv5_header.mpc"))
17        self.sv4 = Musepack(os.path.join(DATA_DIR, "sv4_header.mpc"))
18
19    def test_bad_header(self):
20        self.failUnlessRaises(
21            MusepackHeaderError,
22            Musepack, os.path.join(DATA_DIR, "almostempty.mpc"))
23
24    def test_channels(self):
25        self.failUnlessEqual(self.sv8.info.channels, 2)
26        self.failUnlessEqual(self.sv7.info.channels, 2)
27        self.failUnlessEqual(self.sv5.info.channels, 2)
28        self.failUnlessEqual(self.sv4.info.channels, 2)
29
30    def test_sample_rate(self):
31        self.failUnlessEqual(self.sv8.info.sample_rate, 44100)
32        self.failUnlessEqual(self.sv7.info.sample_rate, 44100)
33        self.failUnlessEqual(self.sv5.info.sample_rate, 44100)
34        self.failUnlessEqual(self.sv4.info.sample_rate, 44100)
35
36    def test_bitrate(self):
37        self.failUnlessEqual(self.sv8.info.bitrate, 609)
38        self.failUnlessEqual(self.sv7.info.bitrate, 194530)
39        self.failUnlessEqual(self.sv5.info.bitrate, 39)
40        self.failUnlessEqual(self.sv4.info.bitrate, 39)
41
42    def test_length(self):
43        self.failUnlessAlmostEqual(self.sv8.info.length, 1.49, 1)
44        self.failUnlessAlmostEqual(self.sv7.info.length, 0.07, 2)
45        self.failUnlessAlmostEqual(self.sv5.info.length, 26.3, 1)
46        self.failUnlessAlmostEqual(self.sv4.info.length, 26.3, 1)
47
48    def test_gain(self):
49        self.failUnlessAlmostEqual(self.sv8.info.title_gain, -4.668, 3)
50        self.failUnlessAlmostEqual(self.sv8.info.title_peak, 0.5288, 3)
51        self.failUnlessEqual(
52            self.sv8.info.title_gain, self.sv8.info.album_gain)
53        self.failUnlessEqual(
54            self.sv8.info.title_peak, self.sv8.info.album_peak)
55        self.failUnlessAlmostEqual(self.sv7.info.title_gain, 9.27, 6)
56        self.failUnlessAlmostEqual(self.sv7.info.title_peak, 0.1149, 4)
57        self.failUnlessEqual(
58            self.sv7.info.title_gain, self.sv7.info.album_gain)
59        self.failUnlessEqual(
60            self.sv7.info.title_peak, self.sv7.info.album_peak)
61        self.failUnlessRaises(AttributeError, getattr, self.sv5, 'title_gain')
62
63    def test_not_my_file(self):
64        self.failUnlessRaises(
65            MusepackHeaderError, Musepack,
66            os.path.join(DATA_DIR, "empty.ogg"))
67        self.failUnlessRaises(
68            MusepackHeaderError, Musepack,
69            os.path.join(DATA_DIR, "emptyfile.mp3"))
70
71    def test_almost_my_file(self):
72        self.failUnlessRaises(
73            MusepackHeaderError, MusepackInfo, cBytesIO(b"MP+" + b"\x00" * 32))
74        self.failUnlessRaises(
75            MusepackHeaderError,
76            MusepackInfo,
77            cBytesIO(b"MP+" + b"\x00" * 100))
78        self.failUnlessRaises(
79            MusepackHeaderError,
80            MusepackInfo,
81            cBytesIO(b"MPCK" + b"\x00" * 100))
82
83    def test_pprint(self):
84        self.sv8.pprint()
85        self.sv7.pprint()
86        self.sv5.pprint()
87        self.sv4.pprint()
88
89    def test_mime(self):
90        self.failUnless("audio/x-musepack" in self.sv7.mime)
91
92    def test_zero_padded_sh_packet(self):
93        # https://github.com/quodlibet/mutagen/issues/198
94        data = (b"MPCKSH\x10\x95 Q\xa2\x08\x81\xb8\xc9T\x00\x1e\x1b"
95                b"\x00RG\x0c\x01A\xcdY\x06?\x80Z\x06EI")
96
97        fileobj = cBytesIO(data)
98        info = MusepackInfo(fileobj)
99        self.assertEqual(info.channels, 2)
100        self.assertEqual(info.samples, 3024084)
101
102
103class TMusepackWithID3(TestCase):
104
105    def setUp(self):
106        self.filename = get_temp_copy(os.path.join(DATA_DIR, "click.mpc"))
107
108    def tearDown(self):
109        os.unlink(self.filename)
110
111    def test_ignore_id3(self):
112        id3 = ID3()
113        id3.add(TIT2(encoding=0, text='id3 title'))
114        id3.save(self.filename)
115        f = Musepack(self.filename)
116        f['title'] = 'apev2 title'
117        f.save()
118        id3 = ID3(self.filename)
119        self.failUnlessEqual(id3['TIT2'], 'id3 title')
120        f = Musepack(self.filename)
121        self.failUnlessEqual(f['title'], 'apev2 title')
122