1 (edited by Zwergner 2008-06-19 18:10:39)

Topic: m3u generating plugin (Picard)

Hello there,

Just started using Picard a week or two ago, and I love it.  I checked out the plugins and while Lukáš Lalinský's CUE generator is great, it put way too much info in there for my needs.  I wanted a playlist and I wanted relative paths.

So I hacked up his plugin.  Basically just removing lines and editing a few.  It now generates a m3u playlist, which if you don't know is just a plaintext list of files.  I make a few assumptions in the implementation (because python is a stranger to me), but it works for me.

First off, it assumes all the files of the album are in the same directory, if they aren't, it will not work properly.  I didn't want full static paths because I'd like to be able to move the music around, so I opted for same directory paths (just the filename).

It has the same version compatibilities as the CUE generating plugin, because it's almost exactly the same.

I made a few "enhancements" as well.  Rather than whatever default directory the CUE file generator was sending me to before, I made it so that the save dialog pops up already in the same folder as the first track on the album, and the playlist is already named as "Artist - Album.m3u".

I kept Lukáš Lalinský's name on there because this plugin is still 99% his work, the only reason I put my name in there is so you don't blame him if it doesn't work properly ;p if you feel like making any improvements (I'm sure I left a ton of now unnecessary code in there) feel free to, I appreciate it.

Hope someone finds this useful and hope Lukáš doesn't mind me taking a machete to his plugin ;p

EDIT:  Now it's more of an addon than a modification as per suggestion by voiceinsideyou.  Can do both CUE and M3U.

# -*- coding: utf-8 -*-

PLUGIN_NAME = u"Generate cue/m3u"
PLUGIN_AUTHOR = u"Lukáš Lalinský (modified by Zwergner)"
PLUGIN_DESCRIPTION = "Generate cuesheet (.cue file) or m3u playlist (.m3u file) from an album."
PLUGIN_VERSION = "0.1"
PLUGIN_API_VERSIONS = ["0.9.0", "0.10"]

import os.path
import re
from PyQt4 import QtCore, QtGui
from picard.util import find_existing_path, encode_filename
from picard.ui.itemviews import BaseAction, register_album_action

_whitespace_re = re.compile('\s', re.UNICODE)
_split_re = re.compile('\s*("[^"]*"|[^ ]+)\s*', re.UNICODE)

def msfToMs(msf):
    msf = msf.split(":")
    return ((int(msf[0]) * 60 + int(msf[1])) * 75 + int(msf[2])) * 1000 / 75   

class CuesheetTrack(list):

    def __init__(self, cuesheet, index):
        list.__init__(self)
        self.cuesheet = cuesheet
        self.index = index

    def set(self, *args):
        self.append(args)

    def find(self, prefix):
        return [i for i in self if tuple(i[:len(prefix)]) == tuple(prefix)]

    def getTrackNumber(self):
        return self.index

    def getLength(self):
        try:
            nextTrack = self.cuesheet.tracks[self.index+1]
            index0 = self.find((u"INDEX",u"01"))
            index1 = nextTrack.find((u"INDEX",u"01"))
            return msfToMs(index1[0][2]) - msfToMs(index0[0][2]) 
        except IndexError:
            return 0

    def getField(self, prefix):
        try:
            return self.find(prefix)[0][len(prefix)]
        except IndexError:
            return u""

    def getArtist(self):
        return self.getField((u"PERFORMER",))

    def getTitle(self):
        return self.getField((u"TITLE",))

    def setArtist(self, artist):
        found = False
        for item in self:
            if item[0] == u"PERFORMER":
                if not found:
                    item[1] = artist
                    found = True
                else:
                    del item
        if not found:
            self.append((u"PERFORMER", artist))

    artist = property(getArtist, setArtist)


class Cuesheet(object):

    def __init__(self, filename):
        self.filename = filename
        self.tracks = []

    def read(self):
        f = open(encode_filename(self.filename))
        self.parse(f.readlines())
        f.close()

    def unquote(self, string):
        if string.startswith('"'):
            if string.endswith('"'):
                return string[1:-1]
            else:
                return string[1:]
        return string

    def quote(self, string):
        if _whitespace_re.search(string):
            return '"' + string.replace('"', '\'') + '"'
        return string

    def parse(self, lines):
        track = CuesheetTrack(self, 0)
        self.tracks = [track]
        isUnicode = False
        for line in lines:
            # remove BOM
            if line.startswith('\xfe\xff'):
                isUnicode = True
                line = line[1:]
            # decode to unicode string
            line = line.strip()
            if isUnicode:
                line = line.decode('UTF-8', 'replace')
            else:
                line = line.decode('ISO-8859-1', 'replace')
            # parse the line
            split = [self.unquote(s) for s in _split_re.findall(line)]
            keyword = split[0].upper()
            if keyword == 'TRACK':
                trackNum = int(split[1])
                track = CuesheetTrack(self, trackNum)
                self.tracks.append(track)
            track.append(split)

    def write(self):
        lines = []
        for track in self.tracks:
            num = track.index
            for line in track:
                indent = 0
                if num > 0:
                    if line[0] == "TRACK":
                        indent = 2
                    elif line[0] != "FILE":
                        indent = 4
                line2 = u" ".join([self.quote(s) for s in line])
                lines.append(" " * indent + line2.encode("UTF-8") + "\n")
        f = open(encode_filename(self.filename), "wt")
        f.writelines(lines)
        f.close()
        
class Playlist(object):

    def __init__(self, filename):
        self.filename = filename
        self.tracks = []

    def read(self):
        f = open(encode_filename(self.filename))
        self.parse(f.readlines())
        f.close()

    def unquote(self, string):
        if string.startswith('"'):
            if string.endswith('"'):
                return string[1:-1]
            else:
                return string[1:]
        return string

    def parse(self, lines):
        track = CuesheetTrack(self, 0)
        self.tracks = [track]
        isUnicode = False
        for line in lines:
            # remove BOM
            if line.startswith('\xfe\xff'):
                isUnicode = True
                line = line[1:]
            # decode to unicode string
            line = line.strip()
            if isUnicode:
                line = line.decode('UTF-8', 'replace')
            else:
                line = line.decode('ISO-8859-1', 'replace')
            # parse the line
            split = [self.unquote(s) for s in _split_re.findall(line)]
            keyword = split[0].upper()
            if keyword == 'TRACK':
                trackNum = int(split[1])
                track = CuesheetTrack(self, trackNum)
                self.tracks.append(track)
            track.append(split)

    def write(self):
        lines = []
        for track in self.tracks:
            num = track.index
            for line in track:
                indent = 0
                if num > 0:
                    if line[0] == "TRACK":
                        indent = 2
                    elif line[0] != "FILE":
                        indent = 4
                line2 = u" ".join(line)
                lines.append(line2.encode("UTF-8") + "\n")
        f = open(encode_filename(self.filename), "wt")
        f.writelines(lines)
        f.close()

class GenerateM3u(BaseAction):
    NAME = "Generate &m3u Playlist..."

    def callback(self, objs):
        album = objs[0]
        trackpath = album.tracks[0].linked_files[0]
        current_directory = album.tracks[0].linked_files[0].filename or self.config.persist["current_directory"] or QtCore.QDir.homePath()
        current_directory = find_existing_path(unicode(current_directory))
        current_directory += "\\" + album.metadata["albumartist"] + " - " + album.metadata["album"]
        selected_format = QtCore.QString()
        filename = QtGui.QFileDialog.getSaveFileName(None, "", current_directory, "M3U Playlist (*.m3u)", selected_format)
        if filename:
            filename = unicode(filename)
            playlist = Playlist(filename)

            while len(playlist.tracks) <= len(album.tracks):
                track = CuesheetTrack(playlist, len(playlist.tracks))
                playlist.tracks.append(track)

            t = playlist.tracks[0]

            index = 0.0
            for i, track in enumerate(album.tracks):
                t = playlist.tracks[i + 1]
                for file in track.linked_files:
                    audio_filename = file.filename
                    audio_filename = os.path.basename(audio_filename)
                    audio_filename = audio_filename
                    t.set(audio_filename)

            playlist.write()

class GenerateCuesheet(BaseAction):
    NAME = "Generate &Cuesheet..."

    def callback(self, objs):
        album = objs[0]
        current_directory = album.tracks[0].linked_files[0].filename or self.config.persist["current_directory"] or QtCore.QDir.homePath()
        current_directory = find_existing_path(unicode(current_directory))
        current_directory += "\\" + album.metadata["albumartist"] + " - " + album.metadata["album"]
        selected_format = QtCore.QString()
        filename = QtGui.QFileDialog.getSaveFileName(None, "", current_directory, "Cuesheet (*.cue)", selected_format)
        if filename:
            filename = unicode(filename)
            cuesheet = Cuesheet(filename)
            #try: cuesheet.read()
            #except IOError: pass
            while len(cuesheet.tracks) <= len(album.tracks):
                track = CuesheetTrack(cuesheet, len(cuesheet.tracks))
                cuesheet.tracks.append(track)
            #if len(cuesheet.tracks) > len(album.tracks) - 1:
            #    cuesheet.tracks = cuesheet.tracks[0:len(album.tracks)+1]

            t = cuesheet.tracks[0]
            t.set("PERFORMER", album.metadata["albumartist"])
            t.set("TITLE", album.metadata["album"])
            t.set("REM", "MUSICBRAINZ_ALBUM_ID", album.metadata["musicbrainz_albumid"])
            t.set("REM", "MUSICBRAINZ_ALBUM_ARTIST_ID", album.metadata["musicbrainz_albumartistid"])
            if "date" in album.metadata:
                t.set("REM", "DATE", album.metadata["date"])
            index = 0.0
            for i, track in enumerate(album.tracks):
                mm = index / 60.0
                ss = (mm - int(mm)) * 60.0
                ff = (ss - int(ss)) * 75.0
                index += track.metadata.length / 1000.0
                t = cuesheet.tracks[i + 1]
                t.set("TRACK", "%02d" % (i + 1), "AUDIO")
                t.set("PERFORMER", track.metadata["artist"])
                t.set("TITLE", track.metadata["title"])
                t.set("REM", "MUSICBRAINZ_TRACK_ID", track.metadata["musicbrainz_trackid"])
                t.set("REM", "MUSICBRAINZ_ARTIST_ID", track.metadata["musicbrainz_artistid"])
                t.set("INDEX", "01", "%02d:%02d:%02d" % (mm, ss, ff))
                for file in track.linked_files:
                    audio_filename = file.filename
                    if os.path.dirname(filename) == os.path.dirname(audio_filename):
                        audio_filename = os.path.basename(audio_filename)
                    cuesheet.tracks[i].set("FILE", audio_filename, "MP3")

            cuesheet.write()



register_album_action(GenerateCuesheet())
register_album_action(GenerateM3u())

just make a text file named cuem3u.py and pop it into your plugin directory.

Re: m3u generating plugin (Picard)

I don't mind at all :)

Re: m3u generating plugin (Picard)

Looks like great work. If you were able to make it have an option/setting entry to work like it did before (with the excessive info) that'd be great; we could just put it over the top of the existing one on the plugins page and avoid the code fork?

4 (edited by Zwergner 2008-06-19 17:48:23)

Re: m3u generating plugin (Picard)

voiceinsideyou wrote:

Looks like great work. If you were able to make it have an option/setting entry to work like it did before (with the excessive info) that'd be great; we could just put it over the top of the existing one on the plugins page and avoid the code fork?

Sounds like a good idea.  I'll do that and some cleanup.  Would you like the cue to have the same default save name/location as I made for the m3u (the directory of the first track of the album, named "artist - album")?

EDIT:  Fixed the code in the first post to do both, assumed "yes" to the question above :D

Re: m3u generating plugin (Picard)

Hi everyone. Thanks for sharing your work with us, Zwergner. That's very kind.

I have luks' original cuesheet plugin installed and it works. But I have troubles with your modified version. First of all, Picard doesn't create a .pyo file from the .py file. But if I remove the special characters from Lukáš Lalinský and write Lukas Lalinsky for PLUGIN_AUTHOR, the .pyo file is created it works and the 2 new plugin menu entries show up. But if I choose either one, nothing happens.

Here is the error entry from the log file:

 Traceback (most recent call last):
  File "picard\ui\itemviews.pyo", line 41, in __callback
  File "D:\appz\MusicBrainz Picard\plugins\cue.py", line 204, in callback
    trackpath = album.tracks[0].linked_files[0]
AttributeError: linked_files

Any ideas? Tell me if I can do more testing for you.

Re: m3u generating plugin (Picard)

Hi!
You have to convert the py-file into UTF-8 encoding. Then Picard will compile it.
If nothing is happening, klicking on the Menu-entry, try a Album without colon in the Album-name. This seems to be a little bug. Maybe someone coult change this in the python-script?

Re: m3u generating plugin (Picard)

The plugin is loaded, but no m3u nor cue file is created when pressing the save button. Am I doing something wrong? I'm running Picard 0.11.

(I'm new too Picard and must say that it rocks! This is what I was looking for for a very long time!)

Re: m3u generating plugin (Picard)

It doesn't happen automatically when you press save, you need to right click on the releases manually in the right hand pane and click Plugins >> "Generate..." etc.

Re: m3u generating plugin (Picard)

Thats the problem. If I click right on the files and choose plugins, nothing pops out. There is nothing to choose from, altough the plugin is loaded (checkbox is on). I tried this for the modified and the original plugin.. Any ideas?
Running Ubuntu Intrepid.

Re: m3u generating plugin (Picard)

Are you definitely clicking on the right hand side pane, on the album entry itself (not the tracks)? If you're sure you're doing it correctly, you can try starting Picard with "-d" and then pasting the log from Help -> View Log.

Re: m3u generating plugin (Picard)

Hello Alpha-CentaUrI and all with the same problem,

with Ubuntu and other *nix you have to change the line

current_directory += "\\" + album.metadata["albumartist"] + " - " + album.metadata["album"]

to

current_directory += "/" + album.metadata["albumartist"] + " - " + album.metadata["album"] + ".m3u"

Re: m3u generating plugin (Picard)

How can I modify the plugin to generate the m3u automatically when saving an album?

When I understand the plugin correctly the "register_album_action" has to be replaced by something ( in the picard-code where "ExtensionPoint()" is called ).

Also to avoid a popup dialog, I have to change this:

        current_directory += "/" + album.metadata["albumartist"] + " - " + album.metadata["album"] + ".m3u"
        filename = current_directory

A bit off-topic: Is there a list of functions like "register_album_action" where a plugin can interact with picard?

Re: m3u generating plugin (Picard)

There is currently no hook for plugins to perform some action when an album gets saved. The "register_album_action" is called whenever an album gets loaded.

But a better plugin documentation would be great. I'm afraid there is currently no list. But you can look at the existing plugins how they are implemented.

Re: m3u generating plugin (Picard)

First I thought:

A solution would be to create the m3u-file with "register_album_action" and then to move the m3u automatically with the music files.

But if the tracks are renamed this way does not work.

Would  a tagger-script do the trick?

Re: m3u generating plugin (Picard)

Brand new kid here!  I'm loving the promise of this program.  I have a giant collection of .wav and .flac files, have been burning them with .cue files for years.  It's been long enough that I have a giant pile of files with no actual tag data, just 'track 1', etc.  I found the .cue plugin, which appears to operate correctly but doesn't create a line directing the cue to any filename.  Consequently, none of the cue-reading programs I use (Foobar, mp3 splitter, EAC) recognizes the cue.

I'm pretty much a computer idiot but the cue generator appears to be doing everything correctly except create a 'pointer' line.

Thanks in advance,

Mike

Re: m3u generating plugin (Picard)

I know this is pretty old, but I revived the m3u-generation for use with Picard 1.0. I changed the filename to be derived by script from album-metadata. You can change the line "script = ...".

# -*- coding: utf-8 -*-

PLUGIN_NAME = u"Generate Cuesheet"
PLUGIN_AUTHOR = u"Lukáš Lalinský (m3u-support by Zwergner, enhanced by floeti"
PLUGIN_DESCRIPTION = "Generate cuesheet (.cue file) from an album."
PLUGIN_VERSION = "0.11"
PLUGIN_API_VERSIONS = ["0.10", "0.15"]


import os.path
import re
from PyQt4 import QtCore, QtGui
from picard.util import find_existing_path, encode_filename
from picard.ui.itemviews import BaseAction, register_album_action
import picard.script


_whitespace_re = re.compile('\s', re.UNICODE)
_split_re = re.compile('\s*("[^"]*"|[^ ]+)\s*', re.UNICODE)


def msfToMs(msf):
    msf = msf.split(":")
    return ((int(msf[0]) * 60 + int(msf[1])) * 75 + int(msf[2])) * 1000 / 75   


class CuesheetTrack(list):

    def __init__(self, cuesheet, index):
        list.__init__(self)
        self.cuesheet = cuesheet
        self.index = index

    def set(self, *args):
        self.append(args)

    def find(self, prefix):
        return [i for i in self if tuple(i[:len(prefix)]) == tuple(prefix)]

    def getTrackNumber(self):
        return self.index

    def getLength(self):
        try:
            nextTrack = self.cuesheet.tracks[self.index+1]
            index0 = self.find((u"INDEX",u"01"))
            index1 = nextTrack.find((u"INDEX",u"01"))
            return msfToMs(index1[0][2]) - msfToMs(index0[0][2]) 
        except IndexError:
            return 0

    def getField(self, prefix):
        try:
            return self.find(prefix)[0][len(prefix)]
        except IndexError:
            return u""

    def getArtist(self):
        return self.getField((u"PERFORMER",))

    def getTitle(self):
        return self.getField((u"TITLE",))

    def setArtist(self, artist):
        found = False
        for item in self:
            if item[0] == u"PERFORMER":
                if not found:
                    item[1] = artist
                    found = True
                else:
                    del item
        if not found:
            self.append((u"PERFORMER", artist))

    artist = property(getArtist, setArtist)


class Cuesheet(object):

    def __init__(self, filename):
        self.filename = filename
        self.tracks = []

    def read(self):
        f = open(encode_filename(self.filename))
        self.parse(f.readlines())
        f.close()

    def unquote(self, string):
        if string.startswith('"'):
            if string.endswith('"'):
                return string[1:-1]
            else:
                return string[1:]
        return string

    def quote(self, string):
        if _whitespace_re.search(string):
            return '"' + string.replace('"', '\'') + '"'
        return string

    def parse(self, lines):
        track = CuesheetTrack(self, 0)
        self.tracks = [track]
        isUnicode = False
        for line in lines:
            # remove BOM
            if line.startswith('\xfe\xff'):
                isUnicode = True
                line = line[1:]
            # decode to unicode string
            line = line.strip()
            if isUnicode:
                line = line.decode('UTF-8', 'replace')
            else:
                line = line.decode('ISO-8859-1', 'replace')
            # parse the line
            split = [self.unquote(s) for s in _split_re.findall(line)]
            keyword = split[0].upper()
            if keyword == 'TRACK':
                trackNum = int(split[1])
                track = CuesheetTrack(self, trackNum)
                self.tracks.append(track)
            track.append(split)

    def write(self):
        lines = []
        for track in self.tracks:
            num = track.index
            for line in track:
                indent = 0
                if num > 0:
                    if line[0] == "TRACK":
                        indent = 2
                    elif line[0] != "FILE":
                        indent = 4
                line2 = u" ".join([self.quote(s) for s in line])
                lines.append(" " * indent + line2.encode("UTF-8") + "\n")
        f = open(encode_filename(self.filename), "wt")
        f.writelines(lines)
        f.close()

class Playlist(object):

    def __init__(self, filename):
        self.filename = filename
        self.tracks = []

    def read(self):
        f = open(encode_filename(self.filename))
        self.parse(f.readlines())
        f.close()

    def unquote(self, string):
        if string.startswith('"'):
            if string.endswith('"'):
                return string[1:-1]
            else:
                return string[1:]
        return string

    def parse(self, lines):
        track = CuesheetTrack(self, 0)
        self.tracks = [track]
        isUnicode = False
        for line in lines:
            # remove BOM
            if line.startswith('\xfe\xff'):
                isUnicode = True
                line = line[1:]
            # decode to unicode string
            line = line.strip()
            if isUnicode:
                line = line.decode('UTF-8', 'replace')
            else:
                line = line.decode('ISO-8859-1', 'replace')
            # parse the line
            split = [self.unquote(s) for s in _split_re.findall(line)]
            keyword = split[0].upper()
            if keyword == 'TRACK':
                trackNum = int(split[1])
                track = CuesheetTrack(self, trackNum)
                self.tracks.append(track)
            track.append(split)

    def write(self):
        lines = []
        for track in self.tracks:
            num = track.index
            for line in track:
                indent = 0
                if num > 0:
                    if line[0] == "TRACK":
                        indent = 2
                    elif line[0] != "FILE":
                        indent = 4
                line2 = u" ".join(line)
                lines.append(line2.encode("UTF-8") + "\n")
        f = open(encode_filename(self.filename), "wt")
        f.writelines(lines)
        f.close()

class GenerateM3u(BaseAction):
    NAME = "Generate &m3u Playlist..."

    def callback(self, objs):
        album = objs[0]
        current_directory = album.tracks[0].linked_files[0].filename or self.config.persist["current_directory"] or QtCore.QDir.homePath()
        current_directory = find_existing_path(unicode(current_directory))
        script = "$if2(%albumartist%,%artist%) ($left($if2(%originaldate%,%date%),4)) - $replace($replace(%album%,:, -),?,)"
        p = picard.script.ScriptParser()
        newName = p.eval(script, album.metadata)
        #newName = p.eval("$replace($replace(%album%,:, -),?,) ($left($if2(%originaldate%,%date%),4))", album.metadata)
        #newName = album.metadata["albumartist"] + " (%s) - "%album.metadata["originaldate"][:4] # + album.metadata["album"]
        current_directory = current_directory + "\\" + newName + ".m3u8"
        selected_format = QtCore.QString()

        filename = QtGui.QFileDialog.getSaveFileName(None, "", current_directory, "M3U Playlist (*.m3u)", selected_format)
        if filename:
            filename = unicode(filename)
            playlist = Playlist(filename)

            while len(playlist.tracks) <= len(album.tracks):
                track = CuesheetTrack(playlist, len(playlist.tracks))
                playlist.tracks.append(track)

            t = playlist.tracks[0]

            index = 0.0
            for i, track in enumerate(album.tracks):
                t = playlist.tracks[i + 1]
                for file in track.linked_files:
                    audio_filename = file.filename
                    audio_filename = os.path.basename(audio_filename)
                    audio_filename = audio_filename
                    t.set(audio_filename)

            playlist.write()

class GenerateCuesheet(BaseAction):
    NAME = "Generate &Cuesheet..."

    def callback(self, objs):
        album = objs[0]
        current_directory = self.config.persist["current_directory"] or QtCore.QDir.homePath()
        current_directory = find_existing_path(unicode(current_directory))
        selected_format = QtCore.QString()
        filename = QtGui.QFileDialog.getSaveFileName(None, "", current_directory, "Cuesheet (*.cue)", selected_format)
        if filename:
            filename = unicode(filename)
            cuesheet = Cuesheet(filename)
            #try: cuesheet.read()
            #except IOError: pass
            while len(cuesheet.tracks) <= len(album.tracks):
                track = CuesheetTrack(cuesheet, len(cuesheet.tracks))
                cuesheet.tracks.append(track)
            #if len(cuesheet.tracks) > len(album.tracks) - 1:
            #    cuesheet.tracks = cuesheet.tracks[0:len(album.tracks)+1]

            t = cuesheet.tracks[0]
            t.set("PERFORMER", album.metadata["albumartist"])
            t.set("TITLE", album.metadata["album"])
            t.set("REM", "MUSICBRAINZ_ALBUM_ID", album.metadata["musicbrainz_albumid"])
            t.set("REM", "MUSICBRAINZ_ALBUM_ARTIST_ID", album.metadata["musicbrainz_albumartistid"])
            if "date" in album.metadata:
                t.set("REM", "DATE", album.metadata["date"])
            index = 0.0
            for i, track in enumerate(album.tracks):
                mm = index / 60.0
                ss = (mm - int(mm)) * 60.0
                ff = (ss - int(ss)) * 75.0
                index += track.metadata.length / 1000.0
                t = cuesheet.tracks[i + 1]
                t.set("TRACK", "%02d" % (i + 1), "AUDIO")
                t.set("PERFORMER", track.metadata["artist"])
                t.set("TITLE", track.metadata["title"])
                t.set("REM", "MUSICBRAINZ_TRACK_ID", track.metadata["musicbrainz_trackid"])
                t.set("REM", "MUSICBRAINZ_ARTIST_ID", track.metadata["musicbrainz_artistid"])
                t.set("INDEX", "01", "%02d:%02d:%02d" % (mm, ss, ff))
                for file in track.linked_files:
                    audio_filename = file.filename
                    if os.path.dirname(filename) == os.path.dirname(audio_filename):
                        audio_filename = os.path.basename(audio_filename)
                    cuesheet.tracks[i].set("FILE", audio_filename, "MP3")

            cuesheet.write()


action = GenerateCuesheet()
register_album_action(action)

actionm = GenerateM3u()
register_album_action(actionm)