mirror of
https://github.com/beetbox/beets.git
synced 2025-12-30 04:22:40 +01:00
translate plugin documentation
This commit is contained in:
parent
3def27a96f
commit
2f8370669e
8 changed files with 512 additions and 3 deletions
|
|
@ -1,5 +1,5 @@
|
|||
Introduction
|
||||
============
|
||||
Guides
|
||||
======
|
||||
|
||||
Tutorial stuff
|
||||
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ also implicitly joined by ANDs: a track must match *all* criteria in order to
|
|||
match the query.) To narrow a search term to a particular metadata field, just
|
||||
put the field before the term, separated by a : character. So ``album:bird``
|
||||
only looks for ``bird`` in the "album" field of your songs. (Need to know more?
|
||||
:doc:`/ref/queries/` will answer all your questions.)
|
||||
:doc:`/reference/query/` will answer all your questions.)
|
||||
|
||||
The ``beet list`` command has another useful option worth mentioning, ``-a``,
|
||||
which searches for albums instead of songs::
|
||||
|
|
|
|||
|
|
@ -11,3 +11,4 @@ Contents
|
|||
|
||||
guides/index
|
||||
reference/index
|
||||
plugins/index
|
||||
|
|
|
|||
125
docs/plugins/bpd.rst
Normal file
125
docs/plugins/bpd.rst
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
BPD Plugin
|
||||
==========
|
||||
|
||||
BPD is a music player using music from a beets library. It runs as a daemon and
|
||||
implements the MPD protocol, so it's compatible with all the great MPD clients
|
||||
out there. I'm using `Theremin`_, `gmpc`_, `Sonata`_, and `Ario`_ successfully.
|
||||
|
||||
.. _Theremin: https://theremin.sigterm.eu/
|
||||
.. _gmpc: http://gmpc.wikia.com/wiki/Gnome_Music_Player_Client
|
||||
.. _Sonata: http://sonata.berlios.de/
|
||||
.. _Ario: http://ario-player.sourceforge.net/
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
Before you can use BPD, you'll need the media library called GStreamer (along
|
||||
with its Python bindings) on your system.
|
||||
|
||||
* On Mac OS X, you should use `MacPorts`_ and run ``port install
|
||||
py26-gst-python``. (Note that you'll almost certainly need the Mac OS X
|
||||
Developer Tools.)
|
||||
|
||||
* On Linux, it's likely that you already have gst-python. (If not, your
|
||||
distribution almost certainly has a package for it.)
|
||||
|
||||
* On Windows, you may want to try `GStreamer WinBuilds`_ (cavet emptor: I
|
||||
haven't tried this).
|
||||
|
||||
.. _MacPorts: http://www.macports.org/
|
||||
.. _GStreamer WinBuilds: http://www.gstreamer-winbuild.ylatuya.es/
|
||||
|
||||
Using and Configuring
|
||||
---------------------
|
||||
|
||||
BPD is a plugin for beets. It comes with beets, but it's disabled by default. To
|
||||
enable it, you'll need to edit your ``.beetsconfig`` file and add the line
|
||||
``plugins: bpd``. Like so::
|
||||
|
||||
[beets]
|
||||
plugins: bpd
|
||||
|
||||
Then, you can run BPD by invoking::
|
||||
|
||||
$ beet bpd
|
||||
|
||||
Fire up your favorite MPD client to start playing music. The MPD site has `a
|
||||
long list of available clients`_. Here are my favorites:
|
||||
|
||||
.. _a long list of available clients: http://mpd.wikia.com/wiki/Clients
|
||||
|
||||
* Linux: `gmpc`_, `Sonata`_
|
||||
|
||||
* Mac: `Theremin`_
|
||||
|
||||
* Windows: I don't know. Get in touch if you have a recommendation.
|
||||
|
||||
* iPhone/iPod touch: `MPoD`_
|
||||
|
||||
.. _MPoD: http://www.katoemba.net/makesnosenseatall/mpod/
|
||||
|
||||
One nice thing about MPD's (and thus BPD's) client-server architecture is that
|
||||
the client can just as easily on a different computer from the server as it can
|
||||
be run locally. Control your music from your laptop (or phone!) while it plays
|
||||
on your headless server box. Rad!
|
||||
|
||||
To configure the BPD server, add a ``[bpd]`` section to your ``.beetsconfig``
|
||||
file. The configuration values, which are pretty self-explanatory, are ``host``,
|
||||
``port``, and ``password``. Here's an example::
|
||||
|
||||
[bpd]
|
||||
host: 127.0.0.1
|
||||
port: 6600
|
||||
password: seekrit
|
||||
|
||||
Implementation Notes
|
||||
--------------------
|
||||
|
||||
In the real MPD, the user can browse a music directory as it appears on disk. In
|
||||
beets, we like to abstract away from the directory structure. Therefore, BPD
|
||||
creates a "virtual" directory structure (artist/album/track) to present to
|
||||
clients. This is static for now and cannot be reconfigured like the real on-disk
|
||||
directory structure can. (Note that an obvious solution to this is just string
|
||||
matching on items' destination, but this requires examining the entire library
|
||||
Python-side for every query.)
|
||||
|
||||
We don't currently support versioned playlists. Many clients, however, use
|
||||
plchanges instead of playlistinfo to get the current playlist, so plchanges
|
||||
contains a dummy implementation that just calls playlistinfo.
|
||||
|
||||
The ``stats`` command always send zero for ``playtime``, which is supposed to
|
||||
indicate the amount of time the server has spent playing music. BPD doesn't
|
||||
currently keep track of this. Also, because database updates aren't yet
|
||||
supported, ``db_update`` is just the time the server was started.
|
||||
|
||||
Unimplemented Commands
|
||||
----------------------
|
||||
|
||||
These are the commands from `the MPD protocol`_ that have not yet been
|
||||
implemented in BPD.
|
||||
|
||||
.. _the MPD protocol: http://mpd.wikia.com/wiki/MusicPlayerDaemonCommands
|
||||
|
||||
Database:
|
||||
|
||||
* update
|
||||
|
||||
Saved playlists:
|
||||
|
||||
* playlistclear
|
||||
* playlistdelete
|
||||
* playlistmove
|
||||
* playlistadd
|
||||
* playlistsearch
|
||||
* listplaylist
|
||||
* listplaylistinfo
|
||||
* playlistfind
|
||||
* rm
|
||||
* save
|
||||
* load
|
||||
* rename
|
||||
|
||||
Deprecated:
|
||||
|
||||
* playlist
|
||||
* volume
|
||||
46
docs/plugins/embedart.rst
Normal file
46
docs/plugins/embedart.rst
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
EmbedArt Plugin
|
||||
===============
|
||||
|
||||
Typically, beets stores album art in a "file on the side": along with each
|
||||
album, there is a file (named "cover.jpg" by default) that stores the album art.
|
||||
You might want to embed the album art directly into each file's metadata. While
|
||||
this will take more space than the external-file approach, it is necessary for
|
||||
displaying album art in some media players (iPods, for example).
|
||||
|
||||
This plugin was added in beets 1.0b8.
|
||||
|
||||
Embedding Art Automatically
|
||||
---------------------------
|
||||
|
||||
To automatically embed discovered album art into imported files, just
|
||||
:doc:`enable the plugin </plugins/index>`. Art will be embedded after each album
|
||||
is added to the library.
|
||||
|
||||
This behavior can be disabled with the ``autoembed`` config option (see below).
|
||||
|
||||
Manually Embedding and Extracting Art
|
||||
-------------------------------------
|
||||
|
||||
The ``embedart`` plugin provides a couple of commands for manually managing
|
||||
embedded album art:
|
||||
|
||||
* ``beet embedart IMAGE QUERY``: given an image file and a query matching an
|
||||
album, embed the image into the metadata of every track on the album.
|
||||
|
||||
* ``beet extractart [-o FILE] QUERY``: extracts the image from an item matching
|
||||
the query and stores it in a file. You can specify the destination file using
|
||||
the ``-o`` option, but leave off the extension: it will be chosen
|
||||
automatically. The destination filename defaults to ``cover`` if it's not
|
||||
specified.
|
||||
|
||||
* ``beet clearart QUERY``: removes all embedded images from all items matching
|
||||
the query. (Use with caution!)
|
||||
|
||||
Configuring
|
||||
-----------
|
||||
|
||||
The plugin has one configuration option, ``autoembed``, which lets you disable
|
||||
automatic album art embedding. To do so, add this to your ``~/.beetsconfig``::
|
||||
|
||||
[embedart]
|
||||
autoembed: no
|
||||
248
docs/plugins/index.rst
Normal file
248
docs/plugins/index.rst
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
Plugins
|
||||
=======
|
||||
|
||||
As of the 1.0b3 release, beets started supporting plugins to modularize its
|
||||
functionality and allow other developers to add new functionality. Plugins can
|
||||
add new commands to the command-line interface, respond to events in beets, and
|
||||
augment the autotagger.
|
||||
|
||||
Using Plugins
|
||||
-------------
|
||||
|
||||
To use a plugin, you have two options:
|
||||
|
||||
* Make sure it's in the Python path (known as `sys.path` to developers). This
|
||||
just means the plugin has to be installed on your system (e.g., with a
|
||||
`setup.py` script or a command like `pip` or `easy_install`).
|
||||
|
||||
* Set the `pythonpath` config variable to point to the directory containing the
|
||||
plugin. (See :doc:`/reference/cli`.)
|
||||
|
||||
Then, set the `plugins` option in your `~/.beetsconfig` file, like so::
|
||||
|
||||
[beets]
|
||||
plugins = mygreatplugin someotherplugin
|
||||
|
||||
The value for `plugins` should be a space-separated list of plugin module names.
|
||||
|
||||
.. _included-plugins:
|
||||
|
||||
Plugins Included With Beets
|
||||
---------------------------
|
||||
|
||||
There are a few plugins that are included with the beets distribution. They're
|
||||
disabled by default, but you can turn them on as described above:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
lastid
|
||||
bpd
|
||||
mpdupdate
|
||||
embedart
|
||||
|
||||
.. _other-plugins:
|
||||
|
||||
Other Plugins
|
||||
-------------
|
||||
|
||||
Here are a few of the plugins written by the beets community:
|
||||
|
||||
* `beets-replaygain`_ can analyze and store !ReplayGain normalization
|
||||
information.
|
||||
|
||||
* `beets-lyrics`_ searches Web repositories for song lyrics and adds them to your files.
|
||||
|
||||
* `beetFs`_ is a FUSE filesystem for browsing the music in your beets library.
|
||||
(Might be out of date.)
|
||||
|
||||
* `Beet-MusicBrainz-Collection`_ lets you add albums from your library to your
|
||||
!MusicBrainz `"music collection"`_.
|
||||
|
||||
* `A cmus plugin`_ integrates with the `cmus`_ console music player.
|
||||
|
||||
.. _beets-replaygain: https://github.com/Lugoues/beets-replaygain/
|
||||
.. _beets-lyrics: https://github.com/Lugoues/beets-lyrics/
|
||||
.. _beetFs: http://code.google.com/p/beetfs/
|
||||
.. _Beet-MusicBrainz-Collection:
|
||||
https://github.com/jeffayle/Beet-MusicBrainz-Collection/
|
||||
.. _"music collection": http://musicbrainz.org/show/collection/
|
||||
.. _A cmus plugin:
|
||||
https://github.com/coolkehon/beets/blob/master/beetsplug/cmus.py
|
||||
.. _cmus: http://cmus.sourceforge.net/
|
||||
|
||||
Writing Plugins
|
||||
---------------
|
||||
|
||||
A beets plugin is just a Python module inside the ``beetsplug`` namespace
|
||||
package. (Check out this `Stack Overflow question about namespace packages`_ if
|
||||
you haven't heard of them.) So, to make one, create a directory called
|
||||
``beetsplug`` and put two files in it: one called ``__init__.py`` and one called
|
||||
``myawesomeplugin.py`` (but don't actually call it that). Your directory
|
||||
structure should look like this::
|
||||
|
||||
beetsplug/
|
||||
__init__.py
|
||||
myawesomeplugin.py
|
||||
|
||||
.. _Stack Overflow question about namespace packages:
|
||||
http://stackoverflow.com/questions/1675734/how-do-i-create-a-namespace-package-in-python/1676069#1676069
|
||||
|
||||
Then, you'll need to put this stuff in ``__init__.py`` to make ``beetsplug`` a
|
||||
namespace package::
|
||||
|
||||
from pkgutil import extend_path
|
||||
__path__ = extend_path(__path__, __name__)
|
||||
|
||||
That's all for ``__init__.py``; you can can leave it alone. The meat of your
|
||||
plugin goes in ``myawesomeplugin.py``. There, you'll have to import the
|
||||
``beets.plugins`` module and define a subclass of the ``BeetsPlugin`` class
|
||||
found therein. Here's a skeleton of a plugin file::
|
||||
|
||||
from beets.plugins import BeetsPlugin
|
||||
|
||||
class MyPlugin(BeetsPlugin):
|
||||
pass
|
||||
|
||||
Once you have your ``BeetsPlugin`` subclass, there's a variety of things your
|
||||
plugin can do. (Read on!)
|
||||
|
||||
To use your new plugin, make sure your ``beetsplug`` directory is in the Python
|
||||
path (using ``PYTHONPATH`` or by installing in a `virtualenv`_, for example).
|
||||
Then, as described above, edit your ``.beetsconfig`` to include
|
||||
``plugins=myawesomeplugin`` (substituting the name of the Python module
|
||||
containing your plugin).
|
||||
|
||||
.. _virtualenv: http://pypi.python.org/pypi/virtualenv
|
||||
|
||||
Add Commands to the CLI
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Plugins can add new subcommands to the ``beet`` command-line interface. Define
|
||||
the plugin class' ``commands()`` method to return a list of ``Subcommand``
|
||||
objects. (The ``Subcommand`` class is defined in the ``beets.ui`` module.)
|
||||
Here's an example plugin that adds a simple command::
|
||||
|
||||
from beets.plugins import BeetsPlugin
|
||||
from beets.ui import Subcommand
|
||||
|
||||
my_super_command = Subcommand('super', help='do something super')
|
||||
def say_hi(lib, config, opts, args):
|
||||
print "Hello everybody! I'm a plugin!"
|
||||
my_super_command.func = say_hi
|
||||
|
||||
class SuperPlug(BeetsPlugin):
|
||||
def commands(self):
|
||||
return [my_super_command]
|
||||
|
||||
To make a subcommand, invoke the constructor like so: ``Subcommand(name, parser,
|
||||
help, aliases)``. The ``name`` parameter is the only required one and should
|
||||
just be the name of your command. ``parser`` can be an `OptionParser instance`_,
|
||||
but it defaults to an empty parser (you can extend it later). ``help`` is a
|
||||
description of your command, and ``aliases`` is a list of shorthand versions of
|
||||
your command name.
|
||||
|
||||
.. _OptionParser instance: http://docs.python.org/library/optparse.html
|
||||
|
||||
You'll need to add a function to your command by saying ``mycommand.func =
|
||||
myfunction``. This function should take the following parameters: ``lib`` (a
|
||||
beets ``Library`` object), ``config`` (a `ConfigParser object`_ containing the
|
||||
configuration values), and ``opts`` and ``args`` (command-line options and
|
||||
arguments as returned by `OptionParser.parse_args`_).
|
||||
|
||||
.. _ConfigParser object: http://docs.python.org/library/configparser.html
|
||||
.. _OptionParser.parse_args:
|
||||
http://docs.python.org/library/optparse.html#parsing-arguments
|
||||
|
||||
The function should use any of the utility functions defined in ``beets.ui``.
|
||||
Try running ``pydoc beets.ui`` to see what's available.
|
||||
|
||||
You can add command-line options to your new command using the ``parser`` member
|
||||
of the ``Subcommand`` class, which is an ``OptionParser`` instance. Just use it
|
||||
like you would a normal ``OptionParser`` in an independent script.
|
||||
|
||||
Listen for Events
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
As of beets 1.0b5, plugins can also define event handlers. Event handlers allow
|
||||
you to run code whenever something happens in beets' operation. For instance, a
|
||||
plugin could write a log message every time an album is successfully autotagged
|
||||
or update MPD's index whenever the database is changed.
|
||||
|
||||
You can "listen" for events using the ``BeetsPlugin.listen`` decorator. Here's
|
||||
an example::
|
||||
|
||||
from beets.plugins import BeetsPlugin
|
||||
|
||||
class SomePlugin(BeetsPlugin):
|
||||
pass
|
||||
|
||||
@SomePlugin.listen('pluginload')
|
||||
def loaded():
|
||||
print 'Plugin loaded!'
|
||||
|
||||
Pass the name of the event in question to the ``listen`` decorator. The events
|
||||
currently available are:
|
||||
|
||||
* *pluginload*: called after all the plugins have been loaded after the ``beet``
|
||||
command starts
|
||||
|
||||
* *save*: called whenever the library is changed and written to disk (the
|
||||
``lib`` keyword argument is the Library object that was written)
|
||||
|
||||
* *import*: called after a ``beet import`` command fishes (the ``lib`` keyword
|
||||
argument is a Library object; ``paths`` is a list of paths (strings) that were
|
||||
imported)
|
||||
|
||||
* *album_imported*: called with an ``Album`` object every time the ``import``
|
||||
command finishes adding an album to the library
|
||||
|
||||
The included ``mpdupdate`` plugin provides an example use case for event listeners.
|
||||
|
||||
Extend the Autotagger
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Plugins in 1.0b5 can also enhance the functionality of the autotagger. For a
|
||||
comprehensive example, try looking at the ``lastid`` plugin, which is included
|
||||
with beets.
|
||||
|
||||
A plugin can extend three parts of the autotagger's process: the track distance
|
||||
function, the album distance function, and the initial MusicBrainz search. The
|
||||
distance functions determine how "good" a match is at the track and album
|
||||
levels; the initial search controls which candidates are presented to the
|
||||
matching algorithm. Plugins implement these extensions by implementing three
|
||||
methods on the plugin class:
|
||||
|
||||
* ``track_distance(self, item, info)``: adds a component to the distance
|
||||
function (i.e., the similarity metric) for individual tracks. ``item`` is the
|
||||
track to be matched (and Item object) and ``info`` is the !MusicBrainz track
|
||||
entry that is proposed as a match. Should return a ``(dist, dist_max)`` pair
|
||||
of floats indicating the distance.
|
||||
|
||||
* ``album_distance(self, items, info)``: like the above, but compares a list of
|
||||
items (representing an album) to an album-level !MusicBrainz entry. Should
|
||||
only consider album-level metadata (e.g., the artist name and album title) and
|
||||
should not duplicate the factors considered by ``track_distance``.
|
||||
|
||||
* ``candidates(self, items)``: given a list of items comprised by an album to be
|
||||
matched, return a list of !MusicBrainz entries for candidate albums to be
|
||||
compared and matched.
|
||||
|
||||
When implementing these functions, it will probably be very necessary to use the
|
||||
functions from the ``beets.autotag`` and ``beets.autotag.mb`` modules, both of
|
||||
which have somewhat helpful docstrings.
|
||||
|
||||
Read Configuration Options
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Plugins can configure themselves using the ``.beetsconfig`` file. Define a
|
||||
``configure`` method on your plugin that takes an ``OptionParser`` object as an
|
||||
argument. Then use the ``beets.ui.config_val`` convenience function to access
|
||||
values from the config file. Like so::
|
||||
|
||||
class MyPlugin(BeetsPlugin):
|
||||
def configure(self, config):
|
||||
number_of_goats = beets.ui.config_val(config, 'myplug', 'goats', '42')
|
||||
|
||||
Try looking at the ``mpdupdate`` plugin (included with beets) for an example of
|
||||
real-world use of this API.
|
||||
65
docs/plugins/lastid.rst
Normal file
65
docs/plugins/lastid.rst
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
LastID Plugin
|
||||
=============
|
||||
|
||||
Acoustic fingerprinting is a technique for identifying songs from the way they
|
||||
"sound" rather from their existing metadata. That means that beets' autotagger
|
||||
can theoretically use fingerprinting to tag files that don't have any ID3
|
||||
information at all (or have completely incorrect data). The MusicBrainz project
|
||||
currently uses a fingerprinting technology called PUIDs, but beets uses a
|
||||
different fingerprinting algorithm provided by `Last.fm`_.
|
||||
|
||||
.. _Last.fm: http://last.fm/
|
||||
|
||||
Turning on fingerprinting can increase the accuracy of the
|
||||
autotagger---especially on files with very poor metadata---but it comes at a
|
||||
cost. First, it can be trickier to set up than beets itself (you need to compile
|
||||
the fingerprinting code, whereas all of the beets core is written in Python).
|
||||
Also, fingerprinting takes significantly more CPU and memory than ordinary
|
||||
tagging---which means that imports will go substantially slower.
|
||||
|
||||
If you're willing to pay the performance cost for fingerprinting, read on!
|
||||
|
||||
Installing Dependencies
|
||||
-----------------------
|
||||
|
||||
To use lastid, you'll need to install the `pylastfp`_ fingerprinting library,
|
||||
which has a few dependencies: `fftw`_, `libsamplerate`_, and `Gstreamer for
|
||||
Python`_. How you install these will depend on your operating system. Here's a
|
||||
few examples:
|
||||
|
||||
.. _pylastfp: http://github.com/sampsyo/pylastfp
|
||||
.. _fftw: http://www.fftw.org/
|
||||
.. _libsamplerate: http://www.mega-nerd.com/SRC/
|
||||
.. _Gstreamer for Python:
|
||||
http://gstreamer.freedesktop.org/modules/gst-python.html
|
||||
|
||||
* On Ubuntu, just run ``apt-get install libfftw3-dev libsamplerate0-dev
|
||||
python-gst0.10-dev``.
|
||||
|
||||
* On Arch Linux, you want
|
||||
``pacman -S fftw libsamplerate gstreamer0.10-python``.
|
||||
|
||||
Let me know if you have a good source for installing the packages on Windows.
|
||||
|
||||
To decode audio formats (MP3, FLAC, etc.), you'll need the standard set of
|
||||
Gstreamer plugins. For example, on Ubuntu, install the packages
|
||||
``gstreamer0.10-plugins-good``, ``gstreamer0.10-plugins-bad``, and
|
||||
``gstreamer0.10-plugins-ugly``.
|
||||
|
||||
Then, install pylastfp itself. You can do this using `pip`_, like so::
|
||||
|
||||
$ pip install pylastfp
|
||||
|
||||
.. _pip: http://pip.openplans.org/
|
||||
|
||||
Using
|
||||
-----
|
||||
|
||||
Once you have all the dependencies sorted out, you can enable fingerprinting by
|
||||
editing your :doc:`/reference/config`. Put ``lastid`` on your ``plugins:``
|
||||
line. Your config file should contain something like this::
|
||||
|
||||
[beets]
|
||||
plugins: lastid
|
||||
|
||||
With that, beets will use fingerprinting the next time you run ``beet import``.
|
||||
24
docs/plugins/mpdupdate.rst
Normal file
24
docs/plugins/mpdupdate.rst
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
MPDUpdate Plugin
|
||||
================
|
||||
|
||||
``mpdupdate`` is a very simple plugin for beets that lets you automatically
|
||||
update `MPD`_'s index whenever you change your beets library. The plugin is
|
||||
included with beets as of version 1.0b5.
|
||||
|
||||
.. _MPD: http://mpd.wikia.com/wiki/Music_Player_Daemon_Wiki
|
||||
|
||||
To use it, enable it in your ``.beetsconfig`` by putting ``mpdupdate`` on your ``plugins`` line. Your ``.beetsconfig`` should look like this::
|
||||
|
||||
[beets]
|
||||
plugins: mpdupdate
|
||||
|
||||
Then, you'll probably want to configure the specifics of your MPD server. You
|
||||
can do that using an ``[mpdupdate]`` section in your ``.beetsconfig``, which
|
||||
looks like this::
|
||||
|
||||
[mpdupdate]
|
||||
host = localhost
|
||||
port = 6600
|
||||
password = seekrit
|
||||
|
||||
With that all in place, you'll see beets send the "update" command to your MPD server every time you change your beets library.
|
||||
Loading…
Reference in a new issue