Exemplo n.º 1
0
def getsubmission(tfile):
    data = open(tfile).read()
    torrent = decode(data)
    tname = torrent['info']['name']

    for file in torrent["info"]["files"]:
        name = "/".join(file["path"])
        flac_re = re.compile(".flac")
        if flac_re.search(name) != None:
            flacname=name
            log_re = re.compile(".log")
        if log_re.search(name) !=None:
            logname=name
    
    fpath = os.path.join(tname,flacname)
    lpath = os.path.join(tname,logname)

    audio = FLAC(fpath)
    print audio.keys()
    if not audio.has_key('musicbrainz_albumid'):
        print "ReleaseID tag is not set. Has this flac been tagged by picard?"
        return(-1)

    albumid = audio['musicbrainz_albumid'][0]
    print albumid

    q = ws.Query()
    try:
        inc = ws.ReleaseIncludes(artist=True, releaseEvents=True, labels=True,
                                 discs=True, tracks=True)
        release = q.getReleaseById(albumid, inc)
    except ws.WebServiceError, e:
        print 'Error:', e
        return(-1)
Exemplo n.º 2
0
    def _extract(self, path: Path):
        """
        Extract meta-data from music file like name and artists.
        This method uses mutagen lib to open the file.
        :param path: Path object with filename
        :return: List with meta-data
        """
        # Parameters
        file = None
        title_tag = ""
        artist_tag = ""

        # Return
        data = {
            'title': "",
            'artists': "",
            'duration': 0.0
        }

        # Check sufix and open music file
        if path.suffix == '.mp3':
            # MP3 File
            file = MP3(path)
            title_tag = "TIT2"
            artist_tag = "TPE1"

        elif path.suffix in ['.m4a', '.mp4']:
            # MPEG4 File
            file = MP4(path)
            title_tag = chr(169) + "nam"
            artist_tag = chr(169) + "ART"

        elif path.suffix == '.flac':
            # FLAC File
            file = FLAC(path)
            title_tag = "title"
            artist_tag = "artist"

        # Check opening success and read data
        if file is not None:
            # Get music title
            if title_tag in file.keys():
                title = file.get(title_tag)
                data['title'] = (str(title[0] if len(title) > 0 else "")) if isinstance(title, list) else str(title)

            # Get music artists (separated with '/')
            if artist_tag in file.keys():
                artist = file.get(artist_tag)
                data['artists'] = "/".join(artist) if isinstance(artist, list) else str(artist)

            # Get music lenght (seconds)
            data['duration'] = float(file.info.length)

        return data
Exemplo n.º 3
0
    def get_album_and_artist(self):
        """ Return FLAC tags for album and artist"""

        self.audio_files.sort()

        for file in self.audio_files:
            try:
                tags = FLAC(file)
                if tags:
                    if "album" in tags.keys() and "artist" in tags.keys():
                        return (tags["album"][0], tags["artist"][0])
                        break  # If we found ID3 tag info from a file, no reason to query the rest in a directory.
            except mutagen.flac.FLACNoHeaderError:
                continue
        return (None, None)
Exemplo n.º 4
0
def check_flac_tags(full_path, e):

    t = {} # "proper" tags

    tags = FLAC(full_path)

    unallowed = set(tags.keys()).difference(flac_allow)

    if unallowed:
        for item in unallowed:
            e.append("Unallowed tag: '" + item + "' - remove")

    # "minimal" tags
    for item in 'album', 'tracknumber', 'title', 'date':
        t[item] = tags[item][0]

    # Handle multiple artist tags in single track
    if len(tags['artist']) > 1:
        t['artist'] = ", ".join(tags['artist'])
    else:
        t['artist'] = tags['artist'][0]

    # "optional" tags
    for item in 'tracktotal', 'genre', 'albumartist', 'discnumber', 'disctotal':
        if item in tags:
            t[item] = tags[item][0]
        else:
            t[item] = None

    return t, e
Exemplo n.º 5
0
def media_info(f):
    aid_re = re.compile("brainz.*album.*id",re.I)
    has_info = 0
    ext = os.path.splitext(f)[-1]
    if ext == ".mp3":
        has_info = 1
        info = ID3(f)
        format = "MP3"
    if ext == ".flac":
        has_info = 1
        info = FLAC(f)
        format = "FLAC"
    if ext == ".ogg":
        has_info = 1
        info = OggVorbis(f)
        format = "OGG"

    if not has_info:
        return {}
    for k in info.keys():
        if re.search(aid_re,k) != None:
            aid = info[k]
            if type(aid) ==mutagen.id3.TXXX:
                aid = aid.__unicode__()
            if type(aid) == type([0]):
                aid = aid[0]
    
    info_d = {}
    info_d['mbid'] = aid
    return info_d
Exemplo n.º 6
0
    def get_album_and_artist(self):
        """ Return FLAC tags for album and artist"""

        self.audio_files.sort()

        for file in self.audio_files:
            try:
                tags = FLAC(file)
                if tags:
                    if "album" in tags.keys() and "artist" in tags.keys():
                        logger.debug(u'album -> {album}, artist -> {artist}'.format(album=tags["album"][0], artist=tags["artist"][0]))
                        return (tags["album"][0], tags["artist"][0])
                        break # If we found ID3 tag info from a file, no reason to query the rest in a directory.  
            except mutagen.flac.FLACNoHeaderError:
                logger.error(u'No FLAC Header data')
                continue
        return (None, None)
Exemplo n.º 7
0
def copy_id3tag(src, des):
    from subprocess import call

    f = FLAC(src)
    args = ["neroAacTag", des]
    for key in f.keys():
        args.extend([_rectify(key) + "=" + f[key][0],])
    print args
    call(args)
Exemplo n.º 8
0
def get_artwork(filename):
	if not filename.endswith(".flac"):
		print "This program is strictly intended for use with flac files" 
		exit(1)
	
	flacinfo = FLAC(filename) 
	if 'album' not in flacinfo.keys() or 'album' not in flacinfo.keys(): 
		print("Missing album or artist" + filename)
		
	artist=flacinfo["artist"][0].encode('utf-8')
	album=flacinfo["album"][0].encode('utf-8')
	print artist,album

	folder  =  os.path.dirname(os.path.realpath(filename))

	coverpath = "".join([folder, os.path.sep, "cover.jpg"])
	if os.path.isfile(coverpath): return

	cmd = "glyrc cover --artist \'{0}\' --album \'{1}\' --write \'{2}\'".format(artist,  album, coverpath)
	out = get_shell_cmd_output(cmd)
	print(out)
Exemplo n.º 9
0
    def extract_taginfo(self):
        taginfo  = { }

        try :
            tagproxy = FLAC(self.filename)
        except ValueError :
            return { }

        for key in tagproxy.keys():
            taginfo[key.lower()] = tagproxy[key][0]

        return taginfo
Exemplo n.º 10
0
  def loadmeta(self):
    for i in range(0,self.tracktotal):
      if self.tracktotal>99:
        ii="{:03d}".format(i+1)
      else:
        ii="{:02d}".format(i+1)
      self.trackmeta.append({})
      if self.format == 'DTS':
        # DTS
        f=os.path.join(self.icache.getroot(), self.albumdir, ii + " " + self.trackname[i] + ".dts")
        dts = APEv2(f)

        # guard
        if 'Track' in dts.keys():
          tmp = dts['Track']
          (tracknumber, tracktotal) = str(tmp).split('/')
          numnumber = int(tracknumber, 10)
          numtotal = int(tracktotal, 10)
          if numtotal != self.tracktotal or numnumber != (i+1):
            raise Exception("TUNE-CHAOS: %s" % self.albumdir)
        else:
          raise Exception("TUNE-CHAOS: %s" % self.albumdir)

        # album
        if 'Album' in dts.keys():
          self.trackmeta[i]['album'] = [ str(xx) for xx in dts['Album'] ]
        # artist
        if 'Artist' in dts.keys():
          self.trackmeta[i]['artist'] = [ str(xx) for xx in dts['Artist'] ]
        # year
        if 'Year' in dts.keys():
          self.trackmeta[i]['date'] = [ str(xx) for xx in dts['Year'] ]
        # title
        if 'Title' in dts.keys():
          self.trackmeta[i]['title'] = [ str(xx) for xx in dts['Title'] ]
      else:
        # FLAC
        f=os.path.join(self.icache.getroot(), self.albumdir, ii + " " + self.trackname[i] + ".flac")
        ff = FLAC(f)
        for t in ff.keys():
          self.trackmeta[i][t.lower()]=ff[t]
        for t in SUPPRESS_TAGS:
          if t in self.trackmeta[i].keys():
            del self.trackmeta[i][t]

      if self.tracktotal>99:
        self.trackmeta[i]['tracknumber'] = [ "{:03d}".format(i+1) ]
        self.trackmeta[i]['tracktotal'] = [ "{:03d}".format(self.tracktotal) ]
      else:
        self.trackmeta[i]['tracknumber'] = [ "{:02d}".format(i+1) ]
        self.trackmeta[i]['tracktotal'] = [ "{:02d}".format(self.tracktotal) ]
    return None
Exemplo n.º 11
0
def get_artwork(filename):
    if not filename.endswith(".flac"):
        print "This program is strictly intended for use with flac files"
        exit(1)

    flacinfo = FLAC(filename)
    if 'album' not in flacinfo.keys() or 'album' not in flacinfo.keys():
        print("Missing album or artist" + filename)

    artist = flacinfo["artist"][0].encode('utf-8')
    album = flacinfo["album"][0].encode('utf-8')
    print artist, album

    folder = os.path.dirname(os.path.realpath(filename))

    coverpath = "".join([folder, os.path.sep, "cover.jpg"])
    if os.path.isfile(coverpath): return

    cmd = "glyrc cover --artist \'{0}\' --album \'{1}\' --write \'{2}\'".format(
        artist, album, coverpath)
    out = get_shell_cmd_output(cmd)
    print(out)
Exemplo n.º 12
0
def printFLAC(flacFile):
	from mutagen.flac import FLAC, Picture

	audio = FLAC(flacFile)
	print "--FLAC--------------------------------------------"
	for tag in audio.keys():
		for text in audio[tag]:
			if 'APIC' in tag:
				print("Tag %s" % (tag) )
			else:
				print("Tag %s: %s" % (tag, text) )
	pics = audio.pictures		
	for p in pics:
		print("Bild gefunden. Typ %s: %s" % (p.type, p.desc) )
Exemplo n.º 13
0
    def _get_tag(self):
        if self.suffix == '.flac':
            try:
                audio = FLAC(self.path)
                self.artist = audio['artist'][0]
                self.title = audio['title'][0]
                if audio.get('genre'):
                    self.local_genres = audio['genre'][0]
                if audio.get('date'):
                    self.local_year = audio['date'][0]

                if audio.pictures:
                    self.cover_embedded = True
            except (FLACNoHeaderError, Exception) as e:
                pass

        if self.suffix == '.mp3':
            try:
                audio = EasyID3(self.path)
                self.artist = audio['artist'][0]
                self.title = audio['title'][0]
                if audio.get('genre'):
                    self.local_genres = audio['genre'][0]
                if audio.get('date'):
                    self.local_year = audio['date'][0]

                audio = MP3(self.path)
                for k in audio.keys():
                    if u'covr' in k or u'APIC' in k:
                        self.cover_embedded = True

            except (HeaderNotFoundError, MutagenError, KeyError) as e:
                pass

        if self.suffix == '.m4a':
            try:

                audio = MP4(self.path)
                self.artist = audio['\xa9ART'][0]
                self.title = audio['\xa9nam'][0]
                if audio.get('\xa9gen'):
                    self.local_genres = audio['\xa9gen'][0]
                if audio.get('\xa9day'):
                    self.local_year = audio['\xa9day'][0]
                if audio.get('covr'):
                    self.cover_embedded = True
            except (KeyError, MP4StreamInfoError, MutagenError) as e:
                pass
Exemplo n.º 14
0
class TFLAC(TestCase):
    SAMPLE = os.path.join(DATA_DIR, "silence-44-s.flac")

    def setUp(self):
        self.NEW = get_temp_copy(self.SAMPLE)
        self.flac = FLAC(self.NEW)

    def tearDown(self):
        os.unlink(self.NEW)

    def test_zero_samples(self):
        # write back zero sample count and load again
        self.flac.info.total_samples = 0
        self.flac.save()
        new = FLAC(self.flac.filename)
        assert new.info.total_samples == 0
        assert new.info.bitrate == 0
        assert new.info.length == 0.0

    def test_bitrate(self):
        assert self.flac.info.bitrate == 101430
        old_file_size = os.path.getsize(self.flac.filename)
        self.flac.save(padding=lambda x: 9999)
        new_flac = FLAC(self.flac.filename)
        assert os.path.getsize(new_flac.filename) > old_file_size
        assert new_flac.info.bitrate == 101430

    def test_padding(self):
        for pad in [0, 42, 2**24 - 1, 2**24]:
            self.flac.save(padding=lambda x: pad)
            new = FLAC(self.flac.filename)
            expected = min(2**24 - 1, pad)
            self.assertEqual(new.metadata_blocks[-1].length, expected)

    def test_save_multiple_padding(self):
        # we don't touch existing padding blocks on save, but will
        # replace them in the file with one at the end

        def num_padding(f):
            blocks = f.metadata_blocks
            return len([b for b in blocks if isinstance(b, Padding)])

        num_blocks = num_padding(self.flac)
        self.assertEqual(num_blocks, 1)
        block = Padding()
        block.length = 42
        self.flac.metadata_blocks.append(block)
        block = Padding()
        block.length = 24
        self.flac.metadata_blocks.append(block)
        self.flac.save()
        self.assertEqual(num_padding(self.flac), num_blocks + 2)

        new = FLAC(self.flac.filename)
        self.assertEqual(num_padding(new), 1)
        self.assertTrue(isinstance(new.metadata_blocks[-1], Padding))

    def test_increase_size_new_padding(self):
        self.assertEqual(self.flac.metadata_blocks[-1].length, 3060)
        value = u"foo" * 100
        self.flac[u"foo"] = [value]
        self.flac.save()
        new = FLAC(self.NEW)
        self.assertEqual(new.metadata_blocks[-1].length, 2752)
        self.assertEqual(new[u"foo"], [value])

    def test_delete(self):
        self.failUnless(self.flac.tags)
        self.flac.delete()
        self.assertTrue(self.flac.tags is not None)
        self.assertFalse(self.flac.tags)
        flac = FLAC(self.NEW)
        self.assertTrue(flac.tags is None)

    def test_module_delete(self):
        delete(self.NEW)
        flac = FLAC(self.NEW)
        self.failIf(flac.tags)

    def test_info(self):
        self.failUnlessAlmostEqual(FLAC(self.NEW).info.length, 3.7, 1)

    def test_keys(self):
        self.failUnlessEqual(list(self.flac.keys()),
                             list(self.flac.tags.keys()))

    def test_values(self):
        self.failUnlessEqual(list(self.flac.values()),
                             list(self.flac.tags.values()))

    def test_items(self):
        self.failUnlessEqual(list(self.flac.items()),
                             list(self.flac.tags.items()))

    def test_vc(self):
        self.failUnlessEqual(self.flac['title'][0], 'Silence')

    def test_write_nochange(self):
        f = FLAC(self.NEW)
        f.save()
        with open(self.SAMPLE, "rb") as a:
            with open(self.NEW, "rb") as b:
                self.failUnlessEqual(a.read(), b.read())

    def test_write_changetitle(self):
        f = FLAC(self.NEW)
        if PY3:
            self.assertRaises(TypeError, f.__setitem__, b'title',
                              b"A New Title")
        else:
            f[b"title"] = b"A New Title"
            f.save()
            f = FLAC(self.NEW)
            self.failUnlessEqual(f[b"title"][0], b"A New Title")

    def test_write_changetitle_unicode_value(self):
        f = FLAC(self.NEW)
        if PY3:
            self.assertRaises(TypeError, f.__setitem__, b'title',
                              u"A Unicode Title \u2022")
        else:
            f[b"title"] = u"A Unicode Title \u2022"
            f.save()
            f = FLAC(self.NEW)
            self.failUnlessEqual(f[b"title"][0], u"A Unicode Title \u2022")

    def test_write_changetitle_unicode_key(self):
        f = FLAC(self.NEW)
        f[u"title"] = b"A New Title"
        if PY3:
            self.assertRaises(ValueError, f.save)
        else:
            f.save()
            f = FLAC(self.NEW)
            self.failUnlessEqual(f[u"title"][0], b"A New Title")

    def test_write_changetitle_unicode_key_and_value(self):
        f = FLAC(self.NEW)
        f[u"title"] = u"A Unicode Title \u2022"
        f.save()
        f = FLAC(self.NEW)
        self.failUnlessEqual(f[u"title"][0], u"A Unicode Title \u2022")

    def test_force_grow(self):
        f = FLAC(self.NEW)
        f["faketag"] = ["a" * 1000] * 1000
        f.save()
        f = FLAC(self.NEW)
        self.failUnlessEqual(f["faketag"], ["a" * 1000] * 1000)

    def test_force_shrink(self):
        self.test_force_grow()
        f = FLAC(self.NEW)
        f["faketag"] = "foo"
        f.save()
        f = FLAC(self.NEW)
        self.failUnlessEqual(f["faketag"], ["foo"])

    def test_add_vc(self):
        f = FLAC(os.path.join(DATA_DIR, "no-tags.flac"))
        self.failIf(f.tags)
        f.add_tags()
        self.failUnless(f.tags == [])
        self.failUnlessRaises(ValueError, f.add_tags)

    def test_add_vc_implicit(self):
        f = FLAC(os.path.join(DATA_DIR, "no-tags.flac"))
        self.failIf(f.tags)
        f["foo"] = "bar"
        self.failUnless(f.tags == [("foo", "bar")])
        self.failUnlessRaises(ValueError, f.add_tags)

    def test_ooming_vc_header(self):
        # issue 112: Malformed FLAC Vorbis header causes out of memory error
        # https://github.com/quodlibet/mutagen/issues/112
        self.assertRaises(error, FLAC,
                          os.path.join(DATA_DIR, 'ooming-header.flac'))

    def test_with_real_flac(self):
        if not have_flac:
            return
        self.flac["faketag"] = "foobar" * 1000
        self.flac.save()
        self.failIf(call_flac("-t", self.flac.filename) != 0)

    def test_save_unknown_block(self):
        block = MetadataBlock(b"test block data")
        block.code = 99
        self.flac.metadata_blocks.append(block)
        self.flac.save()

    def test_load_unknown_block(self):
        self.test_save_unknown_block()
        flac = FLAC(self.NEW)
        self.failUnlessEqual(len(flac.metadata_blocks), 7)
        self.failUnlessEqual(flac.metadata_blocks[5].code, 99)
        self.failUnlessEqual(flac.metadata_blocks[5].data, b"test block data")

    def test_two_vorbis_blocks(self):
        self.flac.metadata_blocks.append(self.flac.metadata_blocks[1])
        self.flac.save()
        self.failUnlessRaises(error, FLAC, self.NEW)

    def test_missing_streaminfo(self):
        self.flac.metadata_blocks.pop(0)
        self.flac.save()
        self.failUnlessRaises(error, FLAC, self.NEW)

    def test_load_invalid_flac(self):
        self.failUnlessRaises(error, FLAC, os.path.join(DATA_DIR, "xing.mp3"))

    def test_save_invalid_flac(self):
        self.failUnlessRaises(error, self.flac.save,
                              os.path.join(DATA_DIR, "xing.mp3"))

    def test_pprint(self):
        self.failUnless(self.flac.pprint())

    def test_double_load(self):
        blocks = list(self.flac.metadata_blocks)
        self.flac.load(self.flac.filename)
        self.failUnlessEqual(blocks, self.flac.metadata_blocks)

    def test_seektable(self):
        self.failUnless(self.flac.seektable)

    def test_cuesheet(self):
        self.failUnless(self.flac.cuesheet)

    def test_pictures(self):
        self.failUnless(self.flac.pictures)

    def test_add_picture(self):
        f = FLAC(self.NEW)
        c = len(f.pictures)
        f.add_picture(Picture())
        f.save()
        f = FLAC(self.NEW)
        self.failUnlessEqual(len(f.pictures), c + 1)

    def test_clear_pictures(self):
        f = FLAC(self.NEW)
        c1 = len(f.pictures)
        c2 = len(f.metadata_blocks)
        f.clear_pictures()
        f.save()
        f = FLAC(self.NEW)
        self.failUnlessEqual(len(f.metadata_blocks), c2 - c1)

    def test_ignore_id3(self):
        id3 = ID3()
        id3.add(TIT2(encoding=0, text='id3 title'))
        id3.save(self.NEW)
        f = FLAC(self.NEW)
        f['title'] = 'vc title'
        f.save()
        id3 = ID3(self.NEW)
        self.failUnlessEqual(id3['TIT2'].text, ['id3 title'])
        f = FLAC(self.NEW)
        self.failUnlessEqual(f['title'], ['vc title'])

    def test_delete_id3(self):
        id3 = ID3()
        id3.add(TIT2(encoding=0, text='id3 title'))
        id3.save(self.NEW, v1=2)
        f = FLAC(self.NEW)
        f['title'] = 'vc title'
        f.save(deleteid3=True)
        self.failUnlessRaises(ID3NoHeaderError, ID3, self.NEW)
        f = FLAC(self.NEW)
        self.failUnlessEqual(f['title'], ['vc title'])

    def test_save_on_mp3(self):
        path = os.path.join(DATA_DIR, "silence-44-s.mp3")
        self.assertRaises(error, self.flac.save, path)

    def test_mime(self):
        self.failUnless("audio/x-flac" in self.flac.mime)

    def test_variable_block_size(self):
        FLAC(os.path.join(DATA_DIR, "variable-block.flac"))

    def test_load_flac_with_application_block(self):
        FLAC(os.path.join(DATA_DIR, "flac_application.flac"))
Exemplo n.º 15
0
        except:
            print("wav to flac error")

        # convert tag file to flac
        cli_args = [
            'ffmpeg', '-i', tag_path[i], '-ac', '2', '-acodec', 'flac',
            'tag.flac'
        ]
        try:
            subprocess.check_output(cli_args)
        except:
            print("convert tag flac error")

        # read tag info
        tag_info = FLAC('tag.flac')
        key_list = tag_info.keys()

        # write tag info
        audio_flac = FLAC(flac_path[i])
        audio_flac.clear()
        audio_flac.clear_pictures()
        for key in key_list:
            audio_flac[key] = tag_info[key]

        # write cover image info
        if os.path.exists('./cover.jpg'):
            img = fimg()
            img.type = 3
            img.mime = 'image/jpg'
            img.desc = 'front cover'
            img.colors = 0
Exemplo n.º 16
0
class TFLAC(TestCase):
    SAMPLE = os.path.join("tests", "data", "silence-44-s.flac")
    NEW = SAMPLE + ".new"

    def setUp(self):
        shutil.copy(self.SAMPLE, self.NEW)
        self.failUnlessEqual(open(self.SAMPLE, "rb").read(),
                             open(self.NEW, "rb").read())
        self.flac = FLAC(self.NEW)

    def test_delete(self):
        self.failUnless(self.flac.tags)
        self.flac.delete()
        self.failIf(self.flac.tags)
        flac = FLAC(self.NEW)
        self.failIf(flac.tags)

    def test_module_delete(self):
        delete(self.NEW)
        flac = FLAC(self.NEW)
        self.failIf(flac.tags)

    def test_info(self):
        self.failUnlessAlmostEqual(FLAC(self.NEW).info.length, 3.7, 1)

    def test_keys(self):
        self.failUnlessEqual(
            list(self.flac.keys()), list(self.flac.tags.keys()))

    def test_values(self):
        self.failUnlessEqual(
            list(self.flac.values()), list(self.flac.tags.values()))

    def test_items(self):
        self.failUnlessEqual(
            list(self.flac.items()), list(self.flac.tags.items()))

    def test_vc(self):
        self.failUnlessEqual(self.flac['title'][0], 'Silence')

    def test_write_nochange(self):
        f = FLAC(self.NEW)
        f.save()
        self.failUnlessEqual(open(self.SAMPLE, "rb").read(),
                             open(self.NEW, "rb").read())

    def test_write_changetitle(self):
        f = FLAC(self.NEW)
        if PY3:
            self.assertRaises(
                TypeError, f.__setitem__, b'title', b"A New Title")
        else:
            f[b"title"] = b"A New Title"
            f.save()
            f = FLAC(self.NEW)
            self.failUnlessEqual(f[b"title"][0], b"A New Title")

    def test_write_changetitle_unicode_value(self):
        f = FLAC(self.NEW)
        if PY3:
            self.assertRaises(
                TypeError, f.__setitem__, b'title', u"A Unicode Title \u2022")
        else:
            f[b"title"] = u"A Unicode Title \u2022"
            f.save()
            f = FLAC(self.NEW)
            self.failUnlessEqual(f[b"title"][0], u"A Unicode Title \u2022")

    def test_write_changetitle_unicode_key(self):
        f = FLAC(self.NEW)
        f[u"title"] = b"A New Title"
        if PY3:
            self.assertRaises(ValueError, f.save)
        else:
            f.save()
            f = FLAC(self.NEW)
            self.failUnlessEqual(f[u"title"][0], b"A New Title")

    def test_write_changetitle_unicode_key_and_value(self):
        f = FLAC(self.NEW)
        f[u"title"] = u"A Unicode Title \u2022"
        f.save()
        f = FLAC(self.NEW)
        self.failUnlessEqual(f[u"title"][0], u"A Unicode Title \u2022")

    def test_force_grow(self):
        f = FLAC(self.NEW)
        f["faketag"] = ["a" * 1000] * 1000
        f.save()
        f = FLAC(self.NEW)
        self.failUnlessEqual(f["faketag"], ["a" * 1000] * 1000)

    def test_force_shrink(self):
        self.test_force_grow()
        f = FLAC(self.NEW)
        f["faketag"] = "foo"
        f.save()
        f = FLAC(self.NEW)
        self.failUnlessEqual(f["faketag"], ["foo"])

    def test_add_vc(self):
        f = FLAC(os.path.join("tests", "data", "no-tags.flac"))
        self.failIf(f.tags)
        f.add_tags()
        self.failUnless(f.tags == [])
        self.failUnlessRaises(ValueError, f.add_tags)

    def test_add_vc_implicit(self):
        f = FLAC(os.path.join("tests", "data", "no-tags.flac"))
        self.failIf(f.tags)
        f["foo"] = "bar"
        self.failUnless(f.tags == [("foo", "bar")])
        self.failUnlessRaises(ValueError, f.add_tags)

    def test_ooming_vc_header(self):
        # issue 112: Malformed FLAC Vorbis header causes out of memory error
        # http://code.google.com/p/mutagen/issues/detail?id=112
        self.assertRaises(IOError, FLAC, os.path.join('tests', 'data',
                                                      'ooming-header.flac'))

    def test_with_real_flac(self):
        if not have_flac:
            return
        self.flac["faketag"] = "foobar" * 1000
        self.flac.save()
        badval = os.system("tools/notarealprogram 2> %s" % devnull)
        value = os.system("flac -t %s 2> %s" % (self.flac.filename, devnull))
        self.failIf(value and value != badval)

    def test_save_unknown_block(self):
        block = MetadataBlock(b"test block data")
        block.code = 99
        self.flac.metadata_blocks.append(block)
        self.flac.save()

    def test_load_unknown_block(self):
        self.test_save_unknown_block()
        flac = FLAC(self.NEW)
        self.failUnlessEqual(len(flac.metadata_blocks), 7)
        self.failUnlessEqual(flac.metadata_blocks[5].code, 99)
        self.failUnlessEqual(flac.metadata_blocks[5].data, b"test block data")

    def test_two_vorbis_blocks(self):
        self.flac.metadata_blocks.append(self.flac.metadata_blocks[1])
        self.flac.save()
        self.failUnlessRaises(IOError, FLAC, self.NEW)

    def test_missing_streaminfo(self):
        self.flac.metadata_blocks.pop(0)
        self.flac.save()
        self.failUnlessRaises(IOError, FLAC, self.NEW)

    def test_load_invalid_flac(self):
        self.failUnlessRaises(
            IOError, FLAC, os.path.join("tests", "data", "xing.mp3"))

    def test_save_invalid_flac(self):
        self.failUnlessRaises(
            IOError, self.flac.save, os.path.join("tests", "data", "xing.mp3"))

    def test_pprint(self):
        self.failUnless(self.flac.pprint())

    def test_double_load(self):
        blocks = list(self.flac.metadata_blocks)
        self.flac.load(self.flac.filename)
        self.failUnlessEqual(blocks, self.flac.metadata_blocks)

    def test_seektable(self):
        self.failUnless(self.flac.seektable)

    def test_cuesheet(self):
        self.failUnless(self.flac.cuesheet)

    def test_pictures(self):
        self.failUnless(self.flac.pictures)

    def test_add_picture(self):
        f = FLAC(self.NEW)
        c = len(f.pictures)
        f.add_picture(Picture())
        f.save()
        f = FLAC(self.NEW)
        self.failUnlessEqual(len(f.pictures), c + 1)

    def test_clear_pictures(self):
        f = FLAC(self.NEW)
        c1 = len(f.pictures)
        c2 = len(f.metadata_blocks)
        f.clear_pictures()
        f.save()
        f = FLAC(self.NEW)
        self.failUnlessEqual(len(f.metadata_blocks), c2 - c1)

    def test_ignore_id3(self):
        id3 = ID3()
        id3.add(TIT2(encoding=0, text='id3 title'))
        id3.save(self.NEW)
        f = FLAC(self.NEW)
        f['title'] = 'vc title'
        f.save()
        id3 = ID3(self.NEW)
        self.failUnlessEqual(id3['TIT2'].text, ['id3 title'])
        f = FLAC(self.NEW)
        self.failUnlessEqual(f['title'], ['vc title'])

    def test_delete_id3(self):
        id3 = ID3()
        id3.add(TIT2(encoding=0, text='id3 title'))
        id3.save(self.NEW, v1=2)
        f = FLAC(self.NEW)
        f['title'] = 'vc title'
        f.save(deleteid3=True)
        self.failUnlessRaises(ID3NoHeaderError, ID3, self.NEW)
        f = FLAC(self.NEW)
        self.failUnlessEqual(f['title'], ['vc title'])

    def test_mime(self):
        self.failUnless("audio/x-flac" in self.flac.mime)

    def test_variable_block_size(self):
        FLAC(os.path.join("tests", "data", "variable-block.flac"))

    def test_load_flac_with_application_block(self):
        FLAC(os.path.join("tests", "data", "flac_application.flac"))

    def tearDown(self):
        os.unlink(self.NEW)
Exemplo n.º 17
0
def add_song(fpath,
             g_songs,
             g_artists,
             g_albums,
             lans='auto',
             delimiter='',
             expand_artist_songs=False):
    """
    parse music file metadata with Easymp3 and return a song
    model.
    """
    try:
        if fpath.endswith('mp3') or fpath.endswith('ogg') or fpath.endswith(
                'wma'):
            metadata = EasyMP3(fpath)
        elif fpath.endswith('m4a') or fpath.endswith('m4v') or fpath.endswith(
                'mp4'):
            metadata = EasyMP4(fpath)
        elif fpath.endswith('flac'):
            metadata = FLAC(fpath)
        elif fpath.endswith('ape'):
            metadata = APEv2(fpath)
        elif fpath.endswith('wav'):
            metadata = dict()
    except MutagenError as e:
        logger.warning('Mutagen parse metadata failed, ignore.\n'
                       'file: {}, exception: {}'.format(fpath, str(e)))
        return None

    metadata_dict = dict(metadata)
    for key in metadata.keys():
        metadata_dict[key] = core_lans(metadata_dict[key][0], lans)
    if 'title' not in metadata_dict:
        title = os.path.split(fpath)[-1].split('.')[0]
        metadata_dict['title'] = core_lans(title, lans)
    metadata_dict.update(
        dict(
            url=fpath,
            duration=metadata.info.length * 1000  # milesecond
        ))

    try:
        if fpath.endswith('flac'):
            data = FLACMetadataSongSchema().load(metadata_dict)
        elif fpath.endswith('ape'):
            data = APEMetadataSongSchema().load(metadata_dict)
        else:
            data = EasyMP3MetadataSongSchema().load(metadata_dict)
    except ValidationError:
        logger.exception('解析音乐文件({}) 元数据失败'.format(fpath))
        return

    # NOTE: use {title}-{artists_name}-{album_name} as song identifier
    title = data['title']
    album_name = data['album_name']
    artist_name_list = [
        name.strip() for name in re.split(r'[,&]', data['artists_name'])
    ]
    artists_name = ','.join(artist_name_list)
    duration = data['duration']
    album_artist_name = data['album_artist_name']

    # 生成 song model
    # 用来生成 id 的字符串应该尽量减少无用信息,这样或许能减少 id 冲突概率
    # 加入分隔符'-'在一定概率上更能确保不发生哈希值重复
    song_id_str = delimiter.join(
        [title, artists_name, album_name,
         str(int(duration))])
    song_id = gen_id(song_id_str)
    if song_id not in g_songs:
        # 剩下 album, lyric 三个字段没有初始化
        song = LSongModel(
            identifier=song_id,
            artists=[],
            title=title,
            url=fpath,
            duration=duration,
            comments=[],
            # 下面这些字段不向外暴露
            genre=data['genre'],
            cover=data['cover'],
            date=data['date'],
            desc=data['desc'],
            disc=data['disc'],
            track=data['track'])
        g_songs[song_id] = song
    else:
        song = g_songs[song_id]
        logger.warning('Duplicate song: %s %s', song.url, fpath)
        return

    # 生成 album artist model
    album_artist_id = gen_id(album_artist_name)
    if album_artist_id not in g_artists:
        album_artist = create_artist(album_artist_id, album_artist_name)
        g_artists[album_artist_id] = album_artist
    else:
        album_artist = g_artists[album_artist_id]

    # 生成 album model
    album_id_str = delimiter.join([album_name, album_artist_name])
    album_id = gen_id(album_id_str)
    # cover_data, cover_fmt = read_audio_cover(fpath)
    # if cover_data is None:
    #     cover = None
    # else:
    #     cover = Media(reverse(song, '/cover/data'), type_=MediaType.image)
    if album_id not in g_albums:
        album = create_album(album_id, album_name, None)
        g_albums[album_id] = album
    else:
        album = g_albums[album_id]

    # 处理专辑的歌手信息和歌曲信息,专辑歌手的专辑列表信息
    if album not in album_artist.albums:
        album_artist.albums.append(album)
    if album_artist not in album.artists:
        album.artists.append(album_artist)
    if song not in album.songs:
        album.songs.append(song)

    # 处理歌曲的歌手和专辑信息,以及歌手的歌曲列表和参与作品
    song.album = album
    for artist_name in artist_name_list:
        artist_id = gen_id(artist_name)
        if artist_id in g_artists:
            artist = g_artists[artist_id]
        else:
            artist = create_artist(identifier=artist_id, name=artist_name)
            g_artists[artist_id] = artist
        if artist not in song.artists:
            song.artists.append(artist)
        if song not in artist.songs:
            artist.songs.append(song)

        # 处理歌曲歌手的参与作品信息(不与前面的重复)
        if album not in artist.albums and album not in artist.contributed_albums:
            artist.contributed_albums.append(album)

    # 处理专辑歌手的歌曲信息: 有些作词人出合辑很少出现在歌曲歌手里(可选)
    if expand_artist_songs and song not in album_artist.songs:
        album_artist.songs.append(song)
Exemplo n.º 18
0
class FlacFile(audiofile.AudioFile):
    def __init__(self, filename):
        super(FlacFile, self).__init__(filename)


    def loadFile(self):
        try:
            self.audio = FLAC(self.filename)
            self.loadMetaData()
            self.fileOpen = True
        except BaseException:
            self.fileOpen = False
            logging.error("FEHLER bei %s" % (self.filename))
            exc_type, exc_value, exc_traceback = sys.exc_info()
            lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
            for line in lines:
                logging.error(line)
        return


    def loadMetaData(self):
        """
            Die FLAC-metadata werden eingelesen.
            Ursprünglich wurden die Daten einzeln
            behandelt. Mitlerweile wird das alles
            durch Ersatzvariablen in der Config-
            Datei behandelt.
            Für ein paar Sachen kann es aber
            noch ganz nütlich sein, die Felder
            einzeln aufzubereiten (z.B. TrackNr)
        """

        for tag in self.audio.keys():
            self.tags[tag] = self.audio[tag]
            for text in self.audio[tag]:

                if tag == 'title':
                    if self.debug: logging.debug('Title? {0}: {1}'.format(tag, text.encode('UTF-8')))
                    self.setTitle(text)
                elif tag == 'artist':
                    if self.debug: logging.debug('Artist? {0}: {1}'.format(tag, text.encode('UTF-8')))
                    self.setArtist(text)
                elif tag == 'album':
                    if self.debug: logging.debug('Album? {0}: {1}'.format(tag, text.encode('UTF-8')))
                    self.setAlbum(text)
                elif tag == 'tracknumber':
                    if self.debug: logging.debug('Track? {0}: {1}'.format(tag, text.encode('UTF-8')))
                    self.setTrack(text)
                elif tag == 'tracktotal':
                    if self.debug: logging.debug('Tracks? {0}: {1}'.format(tag, text.encode('UTF-8')))
                    self.setTrackTotal(text)
                elif tag == 'discnumber':
                    if self.debug: logging.debug('Discnumber? {0}: {1}'.format(tag, text.encode('UTF-8')))
                    self.setDiscNo(text)
                elif tag == 'cddb':
                    if self.debug: logging.debug('CDDB? {0}: {1}'.format(tag, text.encode('UTF-8')))
                    self.setCDDB(text)
                elif tag == 'date':
                    if self.debug: logging.debug('Year? {0}: {1}'.format(tag, text.encode('UTF-8')))
                    self.setYear(text)
                elif tag == 'lyrics':
                    if self.debug: logging.debug('Lyrics? {0}: {1}'.format(tag, text.encode('UTF-8')))
                elif 'comment' in tag:
                    if self.debug: logging.debug('Comment? {0}: {1}'.format(tag, text.encode('UTF-8')))
                    self.setComments(text)
                else:
                    if self.debug: logging.debug('Unhandled Tag {0}: {1}'.format(tag, text.encode('UTF-8')))

        if self.debug: logging.debug("LENGTH? %s" % (self.audio.info.length))


    def loadFrontCover(self):
        pics = self.audio.pictures
        if self.debug: logging.debug('Insgesamt %s Bilder' % (len(pics)))
        datei = None
        logo = None
        if len(pics) > 0:
            # Versuchen ein Frontcover laut Deklaration zu finden
            # oder, wenn es nur ein Bild gibt, dieses nehmen
            for p in pics:
                if p.type == 3 or len(pics) == 1:
                    datei = self.getTempPic(p.data)
                    break

            # Wenn nix gefunden wurde, nehmen wir das erste Bild
            if not datei:
                for p in pics:
                    datei = self.getTempPic(p.data)
                    break

        if datei:
            self.setCover(pygame.image.load(datei))
        else:
            self.setCover(pygame.image.load(self.LEERCD))
        return

    def loadLogo(self):
        pics = self.audio.pictures
        if self.debug: logging.debug('Insgesamt %s Bilder' % (len(pics)))
        logo = None
        if len(pics) > 0:
            # try to fetch a logo-pic
            if self.debug: logging.debug('Try to fetch bandlogo from %s pics ' % (len(pics)))
            for p in pics:
                if p.type == 19:
                    if self.debug: logging.debug('Bandlogo found! ')
                    logo = self.getTempPic(p.data)
                    break

        if logo:
            self.setLogo(pygame.image.load(logo))
        return


    def loadStoredPictures(self):
        diaMode = self.guiPlayer.slide_mode

        if self.debug: logging.debug('DiaMode: %s' % (diaMode))
        pics = self.audio.pictures
        if self.debug: logging.info('Insgesamt %s Bilder' % (len(pics)))
        # wenn nur ein Bild vorhanden ->
        # abbrechen, denn dies wurde als Frontcover
        # behandelt
        if len(pics) <= 1:
            return

        foundBackcover = False
        for p in pics:
            if self.debug: logging.debug('Bild gefunden. Typ {0}: {1}'.format(p.type, p.desc.encode('UTF-8')))
            if not p.type == 3 and not p.type == 19:
                if (diaMode == 3 or diaMode == 5) or (p.type > 3 and p.type < 7):
                    datei = self.getTempPic(p.data)
                    if p.type == 4 and not foundBackcover and diaMode > 3:
                        foundBackcover = True
                        self.setBackcover(pygame.image.load(datei))
                    else:
                        self.setMiscPic(pygame.image.load(datei))

        if self.debug: logging.info('done.')
        return
Exemplo n.º 19
0
def copyFLAC(flacFile, mpgFile):
    from mutagen.flac import FLAC, Picture
    from mutagen.mp3 import MP3
    from mutagen.id3 import ID3

    bChange = False
    # audioMP3 = MP3('smiley.mp3', ID3=EasyID3)
    audioMP3 = MP3()
    audioMP3.add_tags(ID3=CompatID3)
    bNew = True

    audioFLAC = FLAC(flacFile)
    if audioFLAC.has_key('tracktotal'):
        tracktotal = audioFLAC["tracktotal"][0]
    else:
        tracktotal = 0

    if not audioFLAC.has_key('albumartist'):
        audioFLAC["albumartist"] = audioFLAC["artist"]

    if not audioFLAC.has_key('compilation'):
        audioFLAC["compilation"] = 0

    print "--FLAC--------------------------------------------"

    for tag in audioFLAC.keys():
        # print >> sys.stdout, "--> verarbeite Key: ", tag

        # if 'APIC' in tag:
        # 	print 'Tag {0}'.format(tag)
        # else:
        #	print >> sys.stdout, "--> verarbeite Key: Tag {0}: {1}".format(tag, textTag.encode('UTF-8'))
        if tag == "tracktotal": pass
        else:
            # id3.add(mutagen.id3.COMM(encoding=3,text=relationshipLink, lang="eng", desc="MusicGrabberSig"))
            # Tag COMM:Kommentar:'DEU': von Vinyl

            if tag == "tracknumber":
                audioFLAC[tag] = '{0}/{1}'.format(audioFLAC[tag][0],
                                                  tracktotal)
                # audioFLAC[tag]='{0}/{1}'.format(audioFLAC[tag], tracktotal)

            searchTag = tag
            if "comment" in tag: searchTag = 'COMMENTS'
            if "description" in tag: searchTag = 'COMMENTS'

            # if not str.upper(tag) in id3Trans.flacFrames:
            if not hasFrame(searchTag):
                if "replaygain" in tag: continue
                print >> sys.stderr, "Key nicht gefunden: ", tag
                continue

            id3Frame = getFrame(searchTag)
            # audioMP3[id3Frame] = audioFLAC[tag]
            # for textTag in audioFLAC[tag]:
            # print >> sys.stderr, "tag: %s  frame: %s " % (tag, id3Frame.__name__)
            if "comment" in tag:
                # audioMP3.add(id3Frame(encoding=3, text= audioFLAC[tag], lang="DEU", desc="Kommentar"))
                try:
                    audioMP3[id3Frame.__name__] = id3Frame(3,
                                                           text=audioFLAC[tag],
                                                           lang="DEU",
                                                           desc="Kommentar")
                except:
                    pass
            else:
                audioMP3[id3Frame.__name__] = id3Frame(3, text=audioFLAC[tag])
                # audioMP3.add(id3Frame(encoding=3, text= audioFLAC[tag]))
            bChange = True
            # print u'Tag {0}: {1} --> MP3 zugefuegt'.format(id3Frame, audioFLAC[tag])

    if bChange == True:
        #		print dir(audioMP3)
        # if bNew : audioMP3.save(mpgFile,v1=2)
        # else : audioMP3.save(v1=2)
        audioMP3.tags.update_to_v23()
        if bNew: audioMP3.tags.save(filename=mpgFile, v2=3)
        else: audioMP3.tags.save(v2=3)

    print '-' * 40
Exemplo n.º 20
0
class flac(TagParser):
    """
    Class for processing Ogg FLAC file tags
    """
    def __init__(self, codec, path):
        super(flac, self).__init__(codec, path, tag_map=FLAC_STANDARD_TAGS)

        try:
            self.entry = FLAC(path)
        except IOError as e:
            raise TagError('Error opening {}: {}'.format(path, str(e)))
        except FLACNoHeaderError as e:
            raise TagError('Error opening {}: {}'.format(path, str(e)))

        self.albumart_obj = None
        self.track_numbering = FLACNumberingTag(self, 'TRACKNUMBER')
        self.disk_numbering = FLACNumberingTag(self, 'DISKNUMBER')

    def __getitem__(self, item):
        if item == 'tracknumber':
            return [format_unicode_string_value('{:d}'.format(self.track_numbering.value))]

        if item == 'totaltracks':
            return [format_unicode_string_value('{:d}'.format(self.track_numbering.total))]

        if item == 'disknumber':
            return [format_unicode_string_value('{:d}'.format(self.disk_numbering.value))]

        if item == 'totaldisks':
            return [format_unicode_string_value('{:d}'.format(self.disk_numbering.total))]

        return super(flac, self).__getitem__(item)

    def __delitem__(self, item):
        try:
            item = item.split('=', 1)[0]
        except ValueError:
            pass

        fields = self.__tag2fields__(item)
        for tag in fields:
            if tag not in self.entry.keys():
                continue

            del self.entry[tag]
            self.modified = True

    def __field2tag__(self, field):
        return super(flac, self).__field2tag__(field.upper())

    def keys(self):
        """
        Return tag names sorted with self.sort_keys()
        """
        keys = super(flac, self).keys()

        if 'TOTALTRACKS' in keys:
            keys.remove('TOTALTRACKS')
        if 'TOTALDISKS' in keys:
            keys.remove('TOTALDISKS')
        if 'TRACKNUMBER' in [x.upper() for x in keys]:
            if self.track_numbering.total is not None:
                keys.append('totaltracks')
        if 'DISKNUMBER' in [x.upper() for x in keys]:
            if self.disk_numbering.total is not None:
                keys.append('totaldisks')
        if FLAC_ALBUMART_TAG in [x.upper() for x in keys]:
            keys.remove(FLAC_ALBUMART_TAG)
        for replaygain_tag_fields in FLAC_REPLAYGAIN_TAGS.values():
            for tag in replaygain_tag_fields:
                if tag in keys:
                    keys.remove(tag)
        return [x.lower() for x in self.sort_keys(keys)]

    def has_key(self, tag):
        return tag.lower() in self.keys()

    def set_tag(self, item, value):
        """
        All flac tags are str strings, and there can be multiple
        tags with same name.
        We do special precessing for track and disk numbering.
        """
        if item == 'tracknumber':
            self.track_numbering.value = value
            return
        if item == 'totaltracks':
            self.track_numbering.total = value
            return
        if item == 'disknumber':
            self.disk_numbering.value = value
            return
        if item == 'totaldisks':
            self.disk_numbering.total = value
            return

        if not isinstance(value, list):
            value = [value]

        tags = self.__tag2fields__(item)
        item = tags[0]

        for tag in tags:
            if tag in self.entry:
                if tag in OGG_MULTIPLE_VALUES_TAGS and value not in self.entry[tag]:
                    value = self.entry[tag] + value

                del self.entry[tag]

        entries = []
        for v in value:
            if item in FLAC_TAG_FORMATTERS:
                entries.append(FLAC_TAG_FORMATTERS[item](v))
            else:
                entries.append(format_unicode_string_value(v))
        self.entry[item] = entries
        self.modified = True
Exemplo n.º 21
0
def copyFLAC(flacFile, mpgFile):		
	from mutagen.flac import FLAC, Picture
	from mutagen.mp3 import MP3
	from mutagen.id3 import ID3

	bChange = False
	# audioMP3 = MP3('smiley.mp3', ID3=EasyID3)
	audioMP3 = MP3()
	audioMP3.add_tags(ID3=CompatID3)
	bNew = True

	audioFLAC = FLAC(flacFile)
	if audioFLAC.has_key('tracktotal'):
	    tracktotal = audioFLAC["tracktotal"][0]
	else:
	    tracktotal = 0

	if not audioFLAC.has_key('albumartist'):
	    audioFLAC["albumartist"] = audioFLAC["artist"]

	if not audioFLAC.has_key('compilation'):
	    audioFLAC["compilation"] = 0
	
	
	print "--FLAC--------------------------------------------"


	for tag in audioFLAC.keys():
		# print >> sys.stdout, "--> verarbeite Key: ", tag
		
		# if 'APIC' in tag:
		# 	print 'Tag {0}'.format(tag)
		# else:
		#	print >> sys.stdout, "--> verarbeite Key: Tag {0}: {1}".format(tag, textTag.encode('UTF-8'))
		if tag == "tracktotal": pass
		else:
			# id3.add(mutagen.id3.COMM(encoding=3,text=relationshipLink, lang="eng", desc="MusicGrabberSig"))
			# Tag COMM:Kommentar:'DEU': von Vinyl

			if tag == "tracknumber": 
				audioFLAC[tag]='{0}/{1}'.format(audioFLAC[tag][0], tracktotal)
				# audioFLAC[tag]='{0}/{1}'.format(audioFLAC[tag], tracktotal)

			searchTag = tag
			if "comment" in tag: searchTag = 'COMMENTS'
			if "description" in tag: searchTag = 'COMMENTS'

			# if not str.upper(tag) in id3Trans.flacFrames:
			if not hasFrame(searchTag):  
				if "replaygain" in tag: continue
				print >> sys.stderr, "Key nicht gefunden: ", tag
				continue

			id3Frame = getFrame(searchTag)
			# audioMP3[id3Frame] = audioFLAC[tag]
			# for textTag in audioFLAC[tag]:
			# print >> sys.stderr, "tag: %s  frame: %s " % (tag, id3Frame.__name__)
			if "comment" in tag: 
				# audioMP3.add(id3Frame(encoding=3, text= audioFLAC[tag], lang="DEU", desc="Kommentar"))
				try: audioMP3[id3Frame.__name__] = id3Frame(3, text=audioFLAC[tag], lang="DEU", desc="Kommentar")
				except: pass
			else:
				audioMP3[id3Frame.__name__] = id3Frame(3, text=audioFLAC[tag])
				# audioMP3.add(id3Frame(encoding=3, text= audioFLAC[tag]))
			bChange = True
			# print u'Tag {0}: {1} --> MP3 zugefuegt'.format(id3Frame, audioFLAC[tag])
		
	
	if bChange == True:
#		print dir(audioMP3)
		# if bNew : audioMP3.save(mpgFile,v1=2)
		# else : audioMP3.save(v1=2)
		audioMP3.tags.update_to_v23()
		if bNew : audioMP3.tags.save(filename=mpgFile, v2=3)
		else : audioMP3.tags.save(v2=3)

	print '-'*40
Exemplo n.º 22
0
 def create_library(self, source_path, source_type="usb"):
     # Todo - add regex to remove numbers from the begining of filenames to get song name (\d{1,3}|)( - |)(?P<song_Name>.+)
     self.library_ready = False
     new_library = []
     for root, d_names, f_names in os.walk(str(source_path)):
         for fileName in f_names:
             audio = None
             foundType = [
                 musicType for musicType in MUSIC_TYPES
                 if (musicType.lower() in fileName.lower())
             ]
             if bool(foundType):
                 song_path = str(root) + "/" + str(fileName)
                 if True:
                     # try:  # Removed to find error
                     if "flac" in str(foundType[0]):  # add flac filter
                         audio = FLAC(song_path)
                         # LOG.info("Checking FLAC Tags" + str(audio))
                     elif "aac" in str(foundType[0]):  # add flac filter:
                         audio = AAC(song_path)
                         # LOG.info("Checking aac Tags" + str(audio))
                     elif "mp3" in str(foundType[0]):  # add flac filter:
                         try:
                             audio = EasyID3(song_path)
                         except ID3NoHeaderError:
                             LOG.info("No ID Tags Found... " + song_path)
                             audio = {}
                         # LOG.info("Checking mp3 Tags" + str(audio))
                     elif "m4a" in str(foundType[0]):  # add flac filter:
                         audio = MP4(song_path)
                         # LOG.info("Checking m4a Tags" + str(audio))
                     if audio is not None:  # An ID3 tag found
                         if 'title' not in audio.keys():
                             trim_length = (len(str(foundType[0])) + 1) * -1
                             self.song_label = str(fileName)[:trim_length]
                         else:
                             self.song_label = audio['title'][0]
                             #LOG.info("Validating title: " + self.song_label)
                         if 'artist' not in audio.keys():
                             if 'Contributing artists' in audio.keys():
                                 self.song_artist = audio[
                                     'Contributing artists'][0]
                             else:
                                 self.song_artist = ""
                         else:
                             self.song_artist = audio['artist'][0]
                             #LOG.info("Validating artist: " + self.song_artist)
                         if 'album' not in audio.keys():
                             self.song_album = ""
                         else:
                             self.song_album = audio['album'][0]
                     else:  # There was no ID3 Tag found, use filename as song title
                         trim_length = (len(str(foundType[0])) + 1) * -1
                         self.song_label = str(fileName)[:trim_length]
                         self.song_artist = ""
                         self.song_album = ""
             info = {
                 "location": song_path,
                 "label": self.song_label,
                 "artist": self.song_artist,
                 "album": self.song_album,
                 "source": str(source_type)
             }
             new_library.append(info)
     song_count = len(new_library)
     if song_count == 0:
         self.speak_dialog('no.files',
                           data={"source": str(source_type)},
                           expect_response=False)
     else:
         self.speak_dialog('scan.complete',
                           data={
                               "count": str(song_count),
                               "source": str(source_type)
                           },
                           expect_response=False)
     wait_while_speaking()
     LOG.info("Added: " + str(song_count) + " to the library from the " +
              str(source_type) + " Device")
     self.library_ready = True
     return new_library
Exemplo n.º 23
0
class MusicFile(object):

    """
    initialisation function
    @param the absolute path of the file
    @raise A NotAMusicFileException if the file cannot be read as a musicFile
    """

    def __init__(self, path):
        try:
            logging.debug("Trying mp3")
            self.tags = MP3(path, ID3=EasyID3)
            #self.tags = EasyID3(path)
        except mutagen.mp3.HeaderNotFoundError:
            try:
                logging.debug("Trying flac")
                self.tags = FLAC(path)
            except FLACNoHeaderError:
                try:
                    logging.debug("Trying general")
                    self.tags = EasyID3(path)
                except ID3NoHeaderError:
                    raise NotAMusicFileException
        self.path = path

    """
    sanitize method, clean the tag using the following technique
    just idea for the moment
    """
    def sanitize_with_musicBrainz(self):
        titleName = self['title']
        artistName = self['artist']
        albumName = self['album']
        q = Query()
        try:
            logging.debug("Querying with title:{},artist:{},album:{}"
            .format(titleName, artistName, albumName))
            f = TrackFilter(title=titleName, artistName=artistName,
            releaseTitle=albumName, limit=2)
            results = q.getTracks(f)
            logging.debug("results are " + str(results))
        except WebServiceError as e:
            logging.error("Failed to contact musicbrainz server.")
            if str(e)[:15]=="HTTP Error 503:":
                logging.info("Pausing for a moment, \
                the musicbrainz server doesn't handle too much request")
                sleep(60)
            return self.sanitize_with_musicBrainz()
        self.treat_musicbrainz_result(results)

    """
    A simple way to sort the results obtain by a query to the musicbrainz
    database and put them into the correct tag
    @return True if the results can be put into the corresponding tag
            False otherwise
    """
    def treat_musicbrainz_result(self, results):
        if len(results) == 0:
            logging.debug("No result found")
            return False
        for result in results:
            logging.debug("A result was found")
            if result.score == 100:
                track = result.track
                logging.debug("A perfect match seems to be found !!")
                possible_releases = track.getReleases()
                if len(possible_releases) != 1:
                    logging.debug("Multiple album, I will try to guess")
                    for rel in possible_releases:
                        print(dir(rel))
                        exit(0)
                    return False
                else:
                    release = possible_releases[0]
                logging.debug(dir(track))
                logging.debug("tags are :" + str(track.getTags()))
                dir(track)
                self['title'] = track.title
                self['artist'] = track.artist.name
                self['album'] = release.getTitle()
                #self.tags['album'] =
                return

    """
    guess the title from the sound using the sound fingerprint
    using acoustID api
    """
    def guess_sound(self):
        if 'title' in self and 'artist' in self:
            logging.debug("We already have title and artist for this one")
            return
        logging.debug(self.path)
        logging.debug(ACOUSTID_KEY)
        try:
            match = acoustid.match(ACOUSTID_KEY, self.path)
        except:
            return
        for score, recording_id, title, artist in match:
            if score > 0.99:
                #we are quite sure this result match
                logging.debug("Match Found score:%s, title:%s, artist:%s",
                score, title, artist)
                self['title'] = title
                self['artist'] = artist
            else:
                #the result are not sure enough
                logging.debug("The result doesn't seems sure enough.")

    """
    guess the tags from the path
    """
    def guess_path(self):
        if self['artist'] and self['album'] and self['title']:
            logging.debug("Cannot guess any further with only the title")
            return
        #let's try to find album name or artist name from the path, if it's
        #not already set
        clean_path = path_split(self.path)
        logging.debug("Trying to guess on %s" % str(clean_path))
        logging.debug("Clean title:%s" % clean_title(clean_path[-1]))
        #try to guess the album if not already set
        if not self['title']:  # Our worst case
            #we remove all trailing number, trailing '-'
            #and the extension and try to find it in our database
            possible_title = clean_path[-1]
            logging.debug("Title could be {}".format(possible_title))

    """
    get the tag, the name of the tag must be in the value of USEFUL_TAG
    @param the name of the tag
    @return the value of the tag
    """
    def __getitem__(self, key):
        try:
            #return the first item as default
            tag = self.tags[key]
        except KeyError:
            return None
        if not tag:  # if tag is empty
            return None
        else:
            return tag[0]

    """
    set the tag, the name of the tag must be in the value of USEFUL_TAG
    @param the key of the tag
    the new value of the tag
    """
    def __setitem__(self, key, value):
        #set the tag without writing them
        self.tags[key] = str(value)

    def keys(self):
        return self.tags.keys()

    """
    test if the music file contain a certain tag
    """
    def has_key(self, tag):
        return tag in self.tags

    """
    print all tags that mutagen can find
    @param maximum length of all the content
    """
    def __str__(self, maxsize=100):
        ret = [self.path]
        for k in self.tags.keys():
            ret += ["\t %s:%s" % (k, self[k])]
        return "\n".join(ret)

    """
    move this music file in the good place
    """
    def move(self, new_basedir, path_format):
        formatted_path = path_format.format(**self.tags)
        new_dir = os.join(new_basedir, formatted_path)
        try:
            mkdir_p(new_dir)
        except OSError:
            logging.info("Directory %s already exist" % new_dir)
        #extract the extension
        try:
            ext = self.get_extension()
        except:  # TODO specify error
            logging.error("Moving file %s failed, extension is undefined"
            % self.path)
            return
        formatted_path = path_format.format(self.tags)
        new_filename = os.path.join(new_basedir, formatted_path + ext)
        try:
            os.mv(self.path, new_filename)
        except OSError:
            logging.error("Moving file %s failed, cannot move the file")

    """
    return the extension of this file according to it's name
    it can be not accurate if the extention doesn't correspond to
    the real file type.
    """
    def get_extension(self):
        return os.path.splitext(self.path)[-1]

    """
        capitalize all tag by default or a list of specific tag
    """
    def capitalize_tag(self, tag=None):
        for tag in self.tags:
            self.tags[tag] = [string.capwords(i) for i in self.tags[tag]]

    """
    save modification to the id3 tag
    """
    def save(self):
        self.tags.save()

    """
    Get the length of the track in milisecond
    """
    def length(self):
        return int(self.tags.info.length)

    """
    Get the bitrate of the track
    """
    def bitrate(self):
        return int(self.tags.info.bitrate)

    """
    """
    def has_mandatory_tag(self):
        for tag in OBLIGATORY_TAG:
            if tag not in self:
                return False
        return True
Exemplo n.º 24
0
class TFLAC(TestCase):
    SAMPLE = os.path.join(DATA_DIR, "silence-44-s.flac")

    def setUp(self):
        self.NEW = get_temp_copy(self.SAMPLE)
        self.flac = FLAC(self.NEW)

    def tearDown(self):
        os.unlink(self.NEW)

    def test_zero_samples(self):
        # write back zero sample count and load again
        self.flac.info.total_samples = 0
        self.flac.save()
        new = FLAC(self.flac.filename)
        assert new.info.total_samples == 0
        assert new.info.bitrate == 0
        assert new.info.length == 0.0

    def test_bitrate(self):
        assert self.flac.info.bitrate == 101430
        old_file_size = os.path.getsize(self.flac.filename)
        self.flac.save(padding=lambda x: 9999)
        new_flac = FLAC(self.flac.filename)
        assert os.path.getsize(new_flac.filename) > old_file_size
        assert new_flac.info.bitrate == 101430

    def test_padding(self):
        for pad in [0, 42, 2**24 - 1, 2 ** 24]:
            self.flac.save(padding=lambda x: pad)
            new = FLAC(self.flac.filename)
            expected = min(2**24 - 1, pad)
            self.assertEqual(new.metadata_blocks[-1].length, expected)

    def test_save_multiple_padding(self):
        # we don't touch existing padding blocks on save, but will
        # replace them in the file with one at the end

        def num_padding(f):
            blocks = f.metadata_blocks
            return len([b for b in blocks if isinstance(b, Padding)])

        num_blocks = num_padding(self.flac)
        self.assertEqual(num_blocks, 1)
        block = Padding()
        block.length = 42
        self.flac.metadata_blocks.append(block)
        block = Padding()
        block.length = 24
        self.flac.metadata_blocks.append(block)
        self.flac.save()
        self.assertEqual(num_padding(self.flac), num_blocks + 2)

        new = FLAC(self.flac.filename)
        self.assertEqual(num_padding(new), 1)
        self.assertTrue(isinstance(new.metadata_blocks[-1], Padding))

    def test_increase_size_new_padding(self):
        self.assertEqual(self.flac.metadata_blocks[-1].length, 3060)
        value = u"foo" * 100
        self.flac[u"foo"] = [value]
        self.flac.save()
        new = FLAC(self.NEW)
        self.assertEqual(new.metadata_blocks[-1].length, 2752)
        self.assertEqual(new[u"foo"], [value])

    def test_delete(self):
        self.failUnless(self.flac.tags)
        self.flac.delete()
        self.assertTrue(self.flac.tags is not None)
        self.assertFalse(self.flac.tags)
        flac = FLAC(self.NEW)
        self.assertTrue(flac.tags is None)

    def test_delete_change_reload(self):
        self.flac.delete()
        self.flac.tags["FOO"] = ["BAR"]
        self.flac.save()
        assert FLAC(self.flac.filename)["FOO"] == ["BAR"]

        # same with delete failing due to IO etc.
        with pytest.raises(MutagenError):
            self.flac.delete(os.devnull)
        self.flac.tags["FOO"] = ["QUUX"]
        self.flac.save()
        assert FLAC(self.flac.filename)["FOO"] == ["QUUX"]

    def test_module_delete(self):
        delete(self.NEW)
        flac = FLAC(self.NEW)
        self.failIf(flac.tags)

    def test_info(self):
        self.failUnlessAlmostEqual(FLAC(self.NEW).info.length, 3.7, 1)

    def test_keys(self):
        self.failUnlessEqual(
            list(self.flac.keys()), list(self.flac.tags.keys()))

    def test_values(self):
        self.failUnlessEqual(
            list(self.flac.values()), list(self.flac.tags.values()))

    def test_items(self):
        self.failUnlessEqual(
            list(self.flac.items()), list(self.flac.tags.items()))

    def test_vc(self):
        self.failUnlessEqual(self.flac['title'][0], 'Silence')

    def test_write_nochange(self):
        f = FLAC(self.NEW)
        f.save()
        with open(self.SAMPLE, "rb") as a:
            with open(self.NEW, "rb") as b:
                self.failUnlessEqual(a.read(), b.read())

    def test_write_changetitle(self):
        f = FLAC(self.NEW)
        if PY3:
            self.assertRaises(
                TypeError, f.__setitem__, b'title', b"A New Title")
        else:
            f[b"title"] = b"A New Title"
            f.save()
            f = FLAC(self.NEW)
            self.failUnlessEqual(f[b"title"][0], b"A New Title")

    def test_write_changetitle_unicode_value(self):
        f = FLAC(self.NEW)
        if PY3:
            self.assertRaises(
                TypeError, f.__setitem__, b'title', u"A Unicode Title \u2022")
        else:
            f[b"title"] = u"A Unicode Title \u2022"
            f.save()
            f = FLAC(self.NEW)
            self.failUnlessEqual(f[b"title"][0], u"A Unicode Title \u2022")

    def test_write_changetitle_unicode_key(self):
        f = FLAC(self.NEW)
        f[u"title"] = b"A New Title"
        if PY3:
            self.assertRaises(ValueError, f.save)
        else:
            f.save()
            f = FLAC(self.NEW)
            self.failUnlessEqual(f[u"title"][0], b"A New Title")

    def test_write_changetitle_unicode_key_and_value(self):
        f = FLAC(self.NEW)
        f[u"title"] = u"A Unicode Title \u2022"
        f.save()
        f = FLAC(self.NEW)
        self.failUnlessEqual(f[u"title"][0], u"A Unicode Title \u2022")

    def test_force_grow(self):
        f = FLAC(self.NEW)
        f["faketag"] = ["a" * 1000] * 1000
        f.save()
        f = FLAC(self.NEW)
        self.failUnlessEqual(f["faketag"], ["a" * 1000] * 1000)

    def test_force_shrink(self):
        self.test_force_grow()
        f = FLAC(self.NEW)
        f["faketag"] = "foo"
        f.save()
        f = FLAC(self.NEW)
        self.failUnlessEqual(f["faketag"], ["foo"])

    def test_add_vc(self):
        f = FLAC(os.path.join(DATA_DIR, "no-tags.flac"))
        self.failIf(f.tags)
        f.add_tags()
        self.failUnless(f.tags == [])
        self.failUnlessRaises(ValueError, f.add_tags)

    def test_add_vc_implicit(self):
        f = FLAC(os.path.join(DATA_DIR, "no-tags.flac"))
        self.failIf(f.tags)
        f["foo"] = "bar"
        self.failUnless(f.tags == [("foo", "bar")])
        self.failUnlessRaises(ValueError, f.add_tags)

    def test_ooming_vc_header(self):
        # issue 112: Malformed FLAC Vorbis header causes out of memory error
        # https://github.com/quodlibet/mutagen/issues/112
        self.assertRaises(error, FLAC, os.path.join(DATA_DIR,
                                                    'ooming-header.flac'))

    def test_with_real_flac(self):
        if not have_flac:
            return
        self.flac["faketag"] = "foobar" * 1000
        self.flac.save()
        self.failIf(call_flac("-t", self.flac.filename) != 0)

    def test_save_unknown_block(self):
        block = MetadataBlock(b"test block data")
        block.code = 99
        self.flac.metadata_blocks.append(block)
        self.flac.save()

    def test_load_unknown_block(self):
        self.test_save_unknown_block()
        flac = FLAC(self.NEW)
        self.failUnlessEqual(len(flac.metadata_blocks), 7)
        self.failUnlessEqual(flac.metadata_blocks[5].code, 99)
        self.failUnlessEqual(flac.metadata_blocks[5].data, b"test block data")

    def test_two_vorbis_blocks(self):
        self.flac.metadata_blocks.append(self.flac.metadata_blocks[1])
        self.flac.save()
        self.failUnlessRaises(error, FLAC, self.NEW)

    def test_missing_streaminfo(self):
        self.flac.metadata_blocks.pop(0)
        self.flac.save()
        self.failUnlessRaises(error, FLAC, self.NEW)

    def test_load_invalid_flac(self):
        self.failUnlessRaises(
            error, FLAC, os.path.join(DATA_DIR, "xing.mp3"))

    def test_save_invalid_flac(self):
        self.failUnlessRaises(
            error, self.flac.save, os.path.join(DATA_DIR, "xing.mp3"))

    def test_pprint(self):
        self.failUnless(self.flac.pprint())

    def test_double_load(self):
        blocks = list(self.flac.metadata_blocks)
        self.flac.load(self.flac.filename)
        self.failUnlessEqual(blocks, self.flac.metadata_blocks)

    def test_seektable(self):
        self.failUnless(self.flac.seektable)

    def test_cuesheet(self):
        self.failUnless(self.flac.cuesheet)

    def test_pictures(self):
        self.failUnless(self.flac.pictures)

    def test_add_picture(self):
        f = FLAC(self.NEW)
        c = len(f.pictures)
        f.add_picture(Picture())
        f.save()
        f = FLAC(self.NEW)
        self.failUnlessEqual(len(f.pictures), c + 1)

    def test_clear_pictures(self):
        f = FLAC(self.NEW)
        c1 = len(f.pictures)
        c2 = len(f.metadata_blocks)
        f.clear_pictures()
        f.save()
        f = FLAC(self.NEW)
        self.failUnlessEqual(len(f.metadata_blocks), c2 - c1)

    def test_ignore_id3(self):
        id3 = ID3()
        id3.add(TIT2(encoding=0, text='id3 title'))
        id3.save(self.NEW)
        f = FLAC(self.NEW)
        f['title'] = 'vc title'
        f.save()
        id3 = ID3(self.NEW)
        self.failUnlessEqual(id3['TIT2'].text, ['id3 title'])
        f = FLAC(self.NEW)
        self.failUnlessEqual(f['title'], ['vc title'])

    def test_delete_id3(self):
        id3 = ID3()
        id3.add(TIT2(encoding=0, text='id3 title'))
        id3.save(self.NEW, v1=2)
        f = FLAC(self.NEW)
        f['title'] = 'vc title'
        f.save(deleteid3=True)
        self.failUnlessRaises(ID3NoHeaderError, ID3, self.NEW)
        f = FLAC(self.NEW)
        self.failUnlessEqual(f['title'], ['vc title'])

    def test_save_on_mp3(self):
        path = os.path.join(DATA_DIR, "silence-44-s.mp3")
        self.assertRaises(error, self.flac.save, path)

    def test_mime(self):
        self.failUnless("audio/x-flac" in self.flac.mime)

    def test_variable_block_size(self):
        FLAC(os.path.join(DATA_DIR, "variable-block.flac"))

    def test_load_flac_with_application_block(self):
        FLAC(os.path.join(DATA_DIR, "flac_application.flac"))
Exemplo n.º 25
0
            # insertion des infos en tables
            InsertSQLAudio(AllInfo)

        # -----------------------------------------
        # insertion des fichiers FLAC en table
        # -----------------------------------------
        elif ".FLAC" in filename or ".flac" in filename:

            i = i + 1

            MutaFLAC = FLAC(path + "/" + filename)
            AllInfo = {'Duree': MutaFLAC.info.length}

            #print filename," - ",MutaFLAC['title'][0], MutaFLAC['album'][0]

            if 'artist' in MutaFLAC.keys():
                AllInfo['Artist'] = MutaFLAC['artist'][0]
            else:
                AllInfo['Artist'] = "Unknown"

            if 'album' in MutaFLAC.keys():
                AllInfo['Album'] = MutaFLAC['album'][0]
            else:
                AllInfo['Album'] = "Unknown"

            if 'title' in MutaFLAC.keys():
                AllInfo['Titre'] = MutaFLAC['title'][0]
            else:
                AllInfo['Titre'] = "Unknown"

            if 'tracknumber' in MutaFLAC.keys():
Exemplo n.º 26
0
class TFLAC(TestCase):
    SAMPLE = os.path.join("tests", "data", "silence-44-s.flac")
    NEW = SAMPLE + ".new"
    def setUp(self):
        shutil.copy(self.SAMPLE, self.NEW)
        self.failUnlessEqual(open(self.SAMPLE).read(), open(self.NEW).read())
        self.flac = FLAC(self.NEW)

    def test_delete(self):
        self.failUnless(self.flac.tags)
        self.flac.delete()
        self.failIf(self.flac.tags)
        flac = FLAC(self.NEW)
        self.failIf(flac.tags)

    def test_module_delete(self):
        delete(self.NEW)
        flac = FLAC(self.NEW)
        self.failIf(flac.tags)

    def test_info(self):
        self.failUnlessAlmostEqual(FLAC(self.NEW).info.length, 3.7, 1)

    def test_keys(self):
        self.failUnlessEqual(self.flac.keys(), self.flac.tags.keys())

    def test_values(self):
        self.failUnlessEqual(self.flac.values(), self.flac.tags.values())

    def test_items(self):
        self.failUnlessEqual(self.flac.items(), self.flac.tags.items())

    def test_vc(self):
        self.failUnlessEqual(self.flac['title'][0], 'Silence')

    def test_write_nochange(self):
        f = FLAC(self.NEW)
        f.save()
        self.failUnlessEqual(open(self.SAMPLE).read(), open(self.NEW).read())

    def test_write_changetitle(self):
        f = FLAC(self.NEW)
        f["title"] = "A New Title"
        f.save()
        f = FLAC(self.NEW)
        self.failUnlessEqual(f["title"][0], "A New Title")

    def test_write_changetitle_unicode_value(self):
        f = FLAC(self.NEW)
        f["title"] = u"A Unicode Title \u2022"
        f.save()
        f = FLAC(self.NEW)
        self.failUnlessEqual(f["title"][0], u"A Unicode Title \u2022")

    def test_write_changetitle_unicode_key(self):
        f = FLAC(self.NEW)
        f[u"title"] = "A New Title"
        f.save()
        f = FLAC(self.NEW)
        self.failUnlessEqual(f[u"title"][0], "A New Title")

    def test_write_changetitle_unicode_key_and_value(self):
        f = FLAC(self.NEW)
        f[u"title"] = u"A Unicode Title \u2022"
        f.save()
        f = FLAC(self.NEW)
        self.failUnlessEqual(f[u"title"][0], u"A Unicode Title \u2022")

    def test_force_grow(self):
        f = FLAC(self.NEW)
        f["faketag"] = ["a" * 1000] * 1000
        f.save()
        f = FLAC(self.NEW)
        self.failUnlessEqual(f["faketag"], ["a" * 1000] * 1000)

    def test_force_shrink(self):
        self.test_force_grow()
        f = FLAC(self.NEW)
        f["faketag"] = "foo"
        f.save()
        f = FLAC(self.NEW)
        self.failUnlessEqual(f["faketag"], ["foo"])

    def test_add_vc(self):
        f = FLAC(os.path.join("tests", "data", "no-tags.flac"))
        self.failIf(f.tags)
        f.add_tags()
        self.failUnless(f.tags == [])
        self.failUnlessRaises(ValueError, f.add_tags)

    def test_add_vc_implicit(self):
        f = FLAC(os.path.join("tests", "data", "no-tags.flac"))
        self.failIf(f.tags)
        f["foo"] = "bar"
        self.failUnless(f.tags == [("foo", "bar")])
        self.failUnlessRaises(ValueError, f.add_tags)

    def test_ooming_vc_header(self):
        # issue 112: Malformed FLAC Vorbis header causes out of memory error
        # http://code.google.com/p/mutagen/issues/detail?id=112
        self.assertRaises(IOError, FLAC, os.path.join('tests', 'data',
                                                      'ooming-header.flac'))

    def test_with_real_flac(self):
        if not have_flac: return
        self.flac["faketag"] = "foobar" * 1000
        self.flac.save()
        badval = os.system("tools/notarealprogram 2> %s" % devnull)
        value = os.system("flac -t %s 2> %s" % (self.flac.filename, devnull))
        self.failIf(value and value != badval)

    def test_save_unknown_block(self):
        block = MetadataBlock("test block data")
        block.code = 99
        self.flac.metadata_blocks.append(block)
        self.flac.save()

    def test_load_unknown_block(self):
        self.test_save_unknown_block()
        flac = FLAC(self.NEW)
        self.failUnlessEqual(len(flac.metadata_blocks), 7)
        self.failUnlessEqual(flac.metadata_blocks[5].code, 99)
        self.failUnlessEqual(flac.metadata_blocks[5].data, "test block data")

    def test_two_vorbis_blocks(self):
        self.flac.metadata_blocks.append(self.flac.metadata_blocks[1])
        self.flac.save()
        self.failUnlessRaises(IOError, FLAC, self.NEW)

    def test_missing_streaminfo(self):
        self.flac.metadata_blocks.pop(0)
        self.flac.save()
        self.failUnlessRaises(IOError, FLAC, self.NEW)

    def test_load_invalid_flac(self):
        self.failUnlessRaises(
            IOError, FLAC, os.path.join("tests", "data", "xing.mp3"))

    def test_save_invalid_flac(self):
        self.failUnlessRaises(
            IOError, self.flac.save, os.path.join("tests", "data", "xing.mp3"))

    def test_pprint(self):
        self.failUnless(self.flac.pprint())

    def test_double_load(self):
        blocks = list(self.flac.metadata_blocks)
        self.flac.load(self.flac.filename)
        self.failUnlessEqual(blocks, self.flac.metadata_blocks)

    def test_seektable(self):
        self.failUnless(self.flac.seektable)

    def test_cuesheet(self):
        self.failUnless(self.flac.cuesheet)

    def test_pictures(self):
        self.failUnless(self.flac.pictures)

    def test_add_picture(self):
        f = FLAC(self.NEW)
        c = len(f.pictures)
        f.add_picture(Picture())
        f.save()
        f = FLAC(self.NEW)
        self.failUnlessEqual(len(f.pictures), c + 1)

    def test_clear_pictures(self):
        f = FLAC(self.NEW)
        c1 = len(f.pictures)
        c2 = len(f.metadata_blocks)
        f.clear_pictures()
        f.save()
        f = FLAC(self.NEW)
        self.failUnlessEqual(len(f.metadata_blocks), c2 - c1)

    def test_ignore_id3(self):
        id3 = ID3()
        id3.add(TIT2(encoding=0, text='id3 title'))
        id3.save(self.NEW)
        f = FLAC(self.NEW)
        f['title'] = 'vc title'
        f.save()
        id3 = ID3(self.NEW)
        self.failUnlessEqual(id3['TIT2'].text, ['id3 title'])
        f = FLAC(self.NEW)
        self.failUnlessEqual(f['title'], ['vc title'])

    def test_delete_id3(self):
        id3 = ID3()
        id3.add(TIT2(encoding=0, text='id3 title'))
        id3.save(self.NEW, v1=2)
        f = FLAC(self.NEW)
        f['title'] = 'vc title'
        f.save(deleteid3=True)
        self.failUnlessRaises(ID3NoHeaderError, ID3, self.NEW)
        f = FLAC(self.NEW)
        self.failUnlessEqual(f['title'], ['vc title'])

    def test_mime(self):
        self.failUnless("audio/x-flac" in self.flac.mime)

    def test_variable_block_size(self):
        FLAC(os.path.join("tests", "data", "variable-block.flac"))

    def test_load_flac_with_application_block(self):
        FLAC(os.path.join("tests", "data", "flac_application.flac"))

    def tearDown(self):
        os.unlink(self.NEW)
Exemplo n.º 27
0
class FlacTrack(Track):

	"""Expose canonical metadata from a single FLAC file"""

	def __init__(self, path ):
		super(FlacTrack, self).__init__(path)

		""" Load metadata from path """
		self._flac = FLAC( self.PathName )

	@property
	def Album(self):
		return self._flac["album"][0]

	@property
	def AlbumArtist(self):
		if "album artist" in self._flac.keys():
			return self._flac["album artist"][0]

		#print "No AlbumArtist"
		return self.Artist

	@property
	def Artist(self):
		return self._flac["artist"][0]

	@property
	def Title(self):
#		print type( self._flac["title"][0].text ), self._flac["title"][0].text
		return self._flac["title"][0]	

	@property
	def TrackNumber(self):
		return self._flac["tracknumber"][0]

	@property
	def AudioMD5(self):
		md5 =  unicode( hex(self._flac.info.md5_signature) )
                #print md5
                return md5

	@property
	def Wife(self):
		return "custom1" in self._flac and self._flac["custom1"][0] == u'Wife'

	@property
	def IsPartOfCompilation(self):
		artist = self.Artist.lower()
		albumArtist = self.AlbumArtist.lower()

		return ( artist == 'various' or 
			artist == 'various artists' or 
			albumArtist == 'various' or 
			albumArtist == 'various artists' or 
			not artist == albumArtist )

	@property
	def AlbumArtwork(self):
		# should be a jpeg
		#print "pictures", self._flac.pictures
		if len( self._flac.pictures ) > 0:
			cover = self._flac.pictures[0]

			if cover.mime == "image/jpeg":
				#print cover.data
				return AlbumArtwork( io.BytesIO( cover.data ) )
	#		else:
	#			print "no jpeg cover"
	#	else:
	#		print "no cover"

		#print type (self.Path), self.Path
		#print type (self.Album), self.Album
		
		path = None
		if isinstance(self.Path, unicode):
			path = self.Path.encode('utf-8')
		else:
			path = self.Path
		
		artPath = os.path.join( path, self.Album.encode('utf-8') ) + ".jpg"
		if os.path.isfile(artPath):
			return AlbumArtwork( io.BytesIO( open(artPath).read() ) )

		return None