Bijlage A: Plug-in-API

Plug-inmetadata

Elke plug-in moet bepaalde metadata als variabele opgeven. Deze variabelen moeten bovenaan het bestand staan.

PLUGIN_NAME = "Example plugin"
PLUGIN_AUTHOR = "This authors name"
PLUGIN_DESCRIPTION = """
This plugin is an example

Since *Picard 2.7* the description can be formatted using
[Markdown](https://daringfireball.net/projects/markdown/) syntax.
If you use Markdown formatting make sure the minimum version in
'PLUGIN_API_VERSIONS' is set to 2.7.
"""
PLUGIN_VERSION = '0.1'
PLUGIN_API_VERSIONS = ['2.7', '2.8']
PLUGIN_LICENSE = "GPL-2.0-or-later"
PLUGIN_LICENSE_URL = "https://www.gnu.org/licenses/gpl-2.0.html"
PLUGIN_USER_GUIDE_URL = "https://my.program.site.org/example_plugin_documentation.html"

Uitleg van de variabelen:

  • PLUGIN_NAME moet een korte beschrijvende naam voor de plug-in zijn.

  • PLUGIN_DESCRIPTION moet zo eenvoudig mogelijk zijn, maar wel de hoofdfunctie uitleggen. Als je plug-in is bedoeld voor Picard 2.7 of nieuwer, kan je de opmaak van de tekst met Markdown verzorgen. Als je plug-in voor eerdere versies is bedoeld, kan je eenvoudige html-opmaak gebruiken. Beperk het gebruik van html tot eenvoudige tekstopmaak (bijb. <strong>, <em>), links (<a>) en lijsten (<ul>, <ol>).

  • PLUGIN_VERSION moet de versie van de plug-in bevatten. De versie moet de indeling x.y.z (bijv. ‘1.0’ of ‘2.12.4’) hebben. We raden aan om semantische versienummering te gebruiken.

  • PLUGIN_API_VERSIONS moet worden ingesteld op de versies van Picard waarmee deze plug-in werkt. Meestal ondersteunen nieuwe versies van Picard oudere API-versies, maar bij compatibiliteitsbrekende veranderingen kan de ondersteuning voor oudere plug-inversies worden losgelaten. Beschikbare versies voor Picard 2 zijn ‘2.0’, ‘2.1’ en ‘2.2’.

  • PLUGIN_LICENSE moet worden ingesteld op de licentie van de plug-in. Bij voorkeur een van de licenties uit de SPDX-licentielijst, maar je kan natuurlijk ook een andere licentie gebruiken als je favoriete licentie niet in die lijst staat.

  • PLUGIN_LICENSE_URL moet de URL naar de volledige tekst van de licentie zijn.

  • PLUGIN_USER_GUIDE_URL moet de URL naar de documentatie van de plug-in zijn. Deze variabele is optioneel en kan worden weggelaten. Als er een URL wordt opgegeven, is die te zien als klikbare link in de beschrijving op het instellingenvenster van de plug-in.

Metadataverwerkers

De metadata van MusicBrainz kan op twee niveaus worden verwerkt: uitgave en nummer. Aan de verwerker kunnen de volgende argumenten worden doorgegeven:

  • album: picard.album.Album

  • metadata: picard.metadata.Metadata

  • uitgave: dict met uitgave-informatie uit de JSON-webdienst van MusicBrainz

  • nummer: dict met nummerinformatie uit de JSON-webdienst van MusicBrainz

Voorbeeld van uitgavemetadata:

PLUGIN_NAME = "Disc Numbers"
PLUGIN_AUTHOR = "Lukas Lalinsky"
PLUGIN_DESCRIPTION = "Moves disc numbers from album titles to tags."

from picard.metadata import register_album_metadata_processor
import re

def remove_discnumbers(tagger, metadata, release):
    matches = re.search(r"\(disc (\d+)\)", metadata["album"])
    if matches:
        metadata["discnumber"] = matches.group(1)
        metadata["album"] = re.sub(r"\(disc \d+\)", "", metadata["album"])

register_album_metadata_processor(remove_discnumbers)

Voorbeeld van nummermetadata:

PLUGIN_NAME = "Feat. Artists"
PLUGIN_AUTHOR = "Lukas Lalinsky"
PLUGIN_DESCRIPTION = "Removes feat. artists from track titles."

from picard.metadata import register_track_metadata_processor
import re

def remove_featartists(tagger, metadata, track, release):
    metadata["title"] = re.sub(r"\(feat. [^)]*\)", "", metadata["title"])

register_track_metadata_processor(remove_featartists)

Eventhooks

Plug-ins kunnen worden geregistreerd om naar verschillende soorten gebeurtenissen te luisteren. Op dit moment zijn de volgende eventhooks beschikbaar:

file_post_load_processor(file)

Deze hook wordt opgeroepen nadat een bestand in Picard is geladen. Je kan hem bijvoorbeeld gebruiken om extra informatie voor een bestand te laden. Gebruik:

from picard.file import register_file_post_load_processor

def file_post_load_processor(file):
  pass

register_file_post_load_processor(file_post_load_processor)

file_post_save_processor(file)

Deze hook wordt opgeroepen nadat een bestand is opgeslagen. Je kan hem bijvoorbeeld gebruiken voor extra nabewerking op het bestand of het schrijven van extra informatie. Let op: op dit moment is de nieuwe metadata al naar het bestand geschreven. Gebruik:

from picard.file import register_file_post_save_processor

def file_post_save_processor(file):
  pass

register_file_post_save_processor(file_post_save_processor)

file_post_addition_to_track_processor(track, file)

Deze hook wordt opgeroepen nadat een bestand aan een nummer is gekoppeld (in het rechter deelvenster).

from picard.file import register_file_post_addition_to_track_processor

def file_post_addition_to_track_processor(track, file):
  pass

register_file_post_addition_to_track_processor(file_post_addition_to_track_processor)

file_post_removal_from_track_processor(track, file)

Deze hook wordt opgeroepen nadat een bestand van een nummer is verwijderd (in het rechter deelvenster).

from picard.file import register_file_post_removal_from_track_processor

def file_post_removal_from_track_processor(track, file):
  pass

register_file_post_removal_from_track_processor(file_post_removal_from_track_processor)

album_post_removal_processor(album)

Deze hook wordt opgeroepen nadat een bestand uit Picard is verwijderd.

from picard.album import register_album_post_removal_processor

def album_post_removal_processor(album):
  pass

register_album_post_removal_processor(album_post_removal_processor)

Notitie

Eventhooks zijn sinds API-versie 2.2 beschikbaar.

Bestandsindelingen

Met plug-ins kan je Picard ondersteuning voor meer bestandsindelingen geven. Op GitHub kun je zien hoe bestandsindelingen nu worden ondersteund en hoe je het _laden en _opslaan implementeert. Voorbeeld:

PLUGIN_NAME = "..."
PLUGIN_AUTHOR = "..."
PLUGIN_DESCRIPTION = "..."
PLUGIN_VERSION = '...'
PLUGIN_API_VERSIONS = ['...']
PLUGIN_LICENSE = "..."
PLUGIN_LICENSE_URL = "..."

from picard.file import File
from picard.formats import register_format
from picard.metadata import Metadata

class MyFile(File):
    EXTENSIONS = [".foo"]
    NAME = "Foo Audio"

    def _load(self, filename):
        metadata = Metadata()
        # Implement loading and parsing the file here.
        # This method is supposed to return a Metadata instance filled
        # with all the metadata read from the file.
        metadata['~format'] = self.NAME
        return metadata

    def _save(self, filename, metadata):
        # Implement saving the metadata to the file here.
        pass

register_format(MyFile)

Taggerscriptfuncties

Met register_script_function(function, name=None) uit de module picard.script kan je nieuwe tagscriptfuncties definiëren. parser is een exemplaar van picard.script.ScriptParser en de overige argumenten die eraan worden doorgegeven, zijn de argumenten van de functie-aanroep in het tagscript. Voorbeeld:

PLUGIN_NAME = "Initials"
PLUGIN_AUTHOR = "Lukas Lalinsky"
PLUGIN_DESCRIPTION = "Provides tagger script function $initials(text)."
PLUGIN_VERSION = '0.1'
PLUGIN_API_VERSIONS = ['2.0']
PLUGIN_LICENSE = "GPL-2.0"
PLUGIN_LICENSE_URL = "https://www.gnu.org/licenses/gpl-2.0.txt"

from picard.script import register_script_function

def initials(parser, text):
    return "".join(a[:1] for a in text.split(" ") if a[:1].isalpha())

register_script_function(initials)

register_script_function ondersteunt twee optionele argumenten:

  • eval_args: Als dit niet waar is, worden de argumenten niet geëvalueerd voordat ze aan de functie worden doorgegeven.

  • check_argcount: Als dit niet waar is, worden de argumenten die aan de functie worden doorgegeven niet geëvalueerd.

De standaardwaarde van beide argumenten is waar.

Bewerkingen via het contextmenu

Bewerkingen die via het contextmenu beschikbaar zijn, kunnen aan uitgaven, nummers en bestanden in ‘Niet-overeenkomende bestanden’, ‘Clusters’ en ‘ClusterList’ (de bovenliggende map van Clusters) worden toegevoegd. Voorbeeld:

PLUGIN_NAME = u'Remove Perfect Albums'
PLUGIN_AUTHOR = u'ichneumon, hrglgrmpf'
PLUGIN_DESCRIPTION = u'''Remove all perfectly matched albums from the selection.'''
PLUGIN_VERSION = '0.2'
PLUGIN_API_VERSIONS = ['0.15.1']
PLUGIN_LICENSE = "GPL-2.0"
PLUGIN_LICENSE_URL = "https://www.gnu.org/licenses/gpl-2.0.txt"

from picard.album import Album
from picard.ui.itemviews import BaseAction, register_album_action

class RemovePerfectAlbums(BaseAction):
    NAME = 'Remove perfect albums'

    def callback(self, objs):
        for album in objs:
            if isinstance(album, Album) and album.is_complete()\
               and album.get_num_unmatched_files() == 0\
               and album.get_num_matched_tracks() == len(list(album.iterfiles()))\
               and album.get_num_unsaved_files() == 0 and album.loaded == True:
                self.tagger.remove_album(album)

register_album_action(RemovePerfectAlbums())

Gebruik register_x_action, waarbij ‘x’ ‘album’, ‘track’, ‘file’, ‘cluster’ of ‘clusterlist’ is.