Annexe A: API des plugins

Métadonnées du plugin

Chaque plugin doit fournir des métadonnées sous forme de variables. Ces variables doivent être placées en haut du fichier.

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"

Explication des variables :

  • PLUGIN_NAME doit être un nom court mais descriptif du plugin.

  • PLUGIN_DESCRIPTION doit être aussi simple que possible, tout en décrivant la fonction principale. Si votre plugin est destiné à Picard 2.7 ou plus, vous pouvez utiliser la syntaxe Markdown pour formater le texte. Si votre plugin cible des versions antérieures, vous pouvez à la place utiliser un simple formatage HTML. Veuillez limiter l’utilisation du HTML au formatage de base du texte (par exemple, <strong>, <em>), aux liens (<a>) et aux listes (<ul>, <ol>).

  • PLUGIN_VERSION doit être rempli avec la version de le Plug-in. Les versions de plug-in doivent être au format x.y.z (par exemple: « 1.0 » ou « 2.12.4 »). Il est recommandé d’utiliser Semantic Versioning.

  • PLUGIN_API_VERSIONS doit être défini sur les versions de Picard avec lesquelles s’exécuter ce plugin. Les nouvelles versions de Picard prendront généralement en charge les anciennes versions de l’API de plug-in, mais en cas de modification, la prise en charge des anciennes versions de plug-in peut être abandonnée. Les versions disponibles pour Picard 2 sont « 2.0 », « 2.1 » et « 2.2 ».

  • PLUGIN_LICENSE doit être défini avec le nom de licence du plugin. Si possible, utilisez l’un des noms de licence de la Liste des licences SPDX, mais vous êtes invités à utiliser une autre licence si celle que vous avez choisie n’est pas disponible dans la liste.

  • PLUGIN_LICENSE_URL doit être défini sur une URL pointant vers le texte complet de la licence.

  • PLUGIN_USER_GUIDE_URL doit être définie comme une URL pointant vers la documentation du plugin. Cette variable est facultative et peut être omise. Si une URL est fournie, elle sera affichée comme un lien cliquable dans la description affichée pour le plugin dans l’écran de configuration des options de plugins.

Processeurs de métadonnées

Les métadonnées MusicBrainz peuvent être post-traitées à deux niveaux, album et piste. Les types d’arguments passés aux fonctions de processeur dans les exemples suivants sont les suivants :

  • album : picard.album.Album

  • metadata : picard.metadata.Metadata

  • release : dict avec les données de version du service Web MusicBrainz JSON

  • track : dict avec les données de piste du service Web MusicBrainz JSON

Exemple de métadonnées d’album :

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)

Exemple de Suivre les métadonnées :

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)

Crochets d’événement

Les plugins peuvent s’enregistrer pour écouter différents événements. Actuellement, les hooks d’événement suivants sont disponibles :

file_post_load_processor(file)

Ce hook est appelé après le chargement d’un fichier dans Picard. Cela pourrait par exemple être utilisé pour charger des données supplémentaires pour un fichier. Usage :

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)

Ce hook est appelé après l’enregistrement d’un fichier. Cela peut par exemple être utilisé pour exécuter un post-traitement supplémentaire sur le fichier ou écrire des données supplémentaires. Notez que les métadonnées du fichier sont déjà les métadonnées nouvellement enregistrées. Usage :

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)

Ce hook est appelé après qu’un fichier a été ajouté à une piste (dans le volet de droite de Picard).

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)

Ce hook est appelé après qu’un fichier a été supprimé d’une piste (dans le volet droit de Picard).

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)

Ce hook est appelé après qu’un album a été supprimé de Picard.

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)

Note

Les hooks d’événement sont disponibles depuis la version 2.2 de l’API.

Formats de fichiers

Les plugins peuvent étendre Picard avec la prise en charge de formats de fichiers supplémentaires. Voir les implémentations de format de fichier existantes pour plus de détails sur la façon d’implémenter les méthodes _load et _save. Exemple :

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)

Fonctions de script de tagger

Pour définir de nouvelles fonctions de script de tagger, utilisez register_script_function (function, name = None) du module picard.script. parser est une instance de picard.script.ScriptParser, et le reste des arguments qui lui sont passés sont les arguments de l’appel de fonction dans le script du tagger. Exemple :

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 prend en charge deux arguments optionnels :

  • eval_args : Si c’est False, les arguments ne seront pas évalués avant d’être passés à function.

  • check_argcount : Si c’est False, le nombre d’arguments passés à la fonction ne sera pas vérifié.

La valeur par défaut des deux arguments est True.

Actions du menu contextuel

Les actions du menu contextuel du clic droit peuvent être ajoutées aux albums, pistes et fichiers dans « Fichiers sans correspondance », « Clusters » et « ClusterList » (dossier parent des clusters). Exemple :

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())

Utilisez register_x_action où “x” est « album », « track », « file », « cluster » ou « clusterlist ».