plugin API to extend MediaFile (#324)

This commit is contained in:
Adrian Sampson 2012-02-09 14:35:47 -08:00
parent 72659975a2
commit 08e93a5309
3 changed files with 61 additions and 0 deletions

View file

@ -19,6 +19,8 @@ import itertools
import traceback
from collections import defaultdict
from beets import mediafile
PLUGIN_NAMESPACE = 'beetsplug'
DEFAULT_PLUGINS = []
@ -36,6 +38,12 @@ class BeetsPlugin(object):
functionality by defining a subclass of BeetsPlugin and overriding
the abstract methods defined here.
"""
def __init__(self):
"""Perform one-time plugin setup. There is probably no reason to
override this method.
"""
_add_media_fields(self.item_fields())
def commands(self):
"""Should return a list of beets.ui.Subcommand objects for
commands that should be added to beets' CLI.
@ -72,6 +80,14 @@ class BeetsPlugin(object):
"""
pass
def item_fields(self):
"""Returns field descriptors to be added to the MediaFile class,
in the form of a dictionary whose keys are field names and whose
values are descriptor (e.g., MediaField) instances. The Library
database schema is not (currently) extended.
"""
return {}
listeners = None
@classmethod
@ -246,6 +262,13 @@ def template_values(item):
values[name] = unicode(func(item))
return values
def _add_media_fields(fields):
"""Adds a {name: descriptor} dictionary of fields to the MediaFile
class. Called during the plugin initialization.
"""
for key, value in fields.iteritems():
setattr(mediafile.MediaFile, key, value)
# Event dispatch.

View file

@ -22,6 +22,8 @@ Changelog
* Filename extensions are now always lower-cased when copying and moving files.
* The ``inline`` plugin now prints a more comprehensible error when exceptions
occur in Python snippets.
* New plugin API: plugins can now add fields to the MediaFile tag abstraction
layer. See :ref:`writing-plugins`.
* A reasonable error message is now shown when the import log file cannot be
opened.
* Fix a bug in the ``rewrite`` plugin that broke the use of multiple rules for

View file

@ -301,3 +301,39 @@ that adds a ``$disc_and_track`` field::
With this plugin enabled, templates can reference ``$disc_and_track`` as they
can any standard metadata field.
Extend MediaFile
^^^^^^^^^^^^^^^^
`MediaFile`_ is the file tag abstraction layer that beets uses to make
cross-format metadata manipulation simple. Plugins can add fields to MediaFile
to extend the kinds of metadata that they can easily manage.
The ``item_fields`` method on plugins should be overridden to return a
dictionary whose keys are field names and whose values are descriptor objects
that provide the field in question. The descriptors should probably be
``MediaField`` instances (defined in ``beets.mediafile``). Here's an example
plugin that provides a meaningless new field "foo"::
from beets import mediafile, plugins, ui
class FooPlugin(plugins.BeetsPlugin):
def item_fields(self):
return {
'foo': mediafile.MediaField(
mp3 = mediafile.StorageStyle(
'TXXX', id3_desc=u'Foo Field'),
mp4 = mediafile.StorageStyle(
'----:com.apple.iTunes:Foo Field'),
etc = mediafile.StorageStyle('FOO FIELD')
),
}
Later, the plugin can manipulate this new field by saying something like
``mf.foo = 'bar'`` where ``mf`` is a ``MediaFile`` instance.
Note that, currently, these additional fields are *only* applied to
``MediaFile`` itself. The beets library database schema and the ``Item`` class
are not extended, so the fields are second-class citizens. This may change
eventually.
.. _MediaFile: https://github.com/sampsyo/beets/wiki/MediaFile