Mopidy-MPD-mpc
Contingut
Introducció
nota: ja havia treballat amb mpd i mpc ara fa dos anys en el projecte de les estacions de ràdio de JAZZ:
Mopidy (https://www.mopidy.com/, https://docs.mopidy.com/en/latest/) is an extensible music server written in Python.
Mopidy plays music from local disk, Spotify, SoundCloud, Google Play Music, and more. You edit the playlist from any phone, tablet, or computer using a range of MPD and web clients.
És a dir, mopidy és el servidor (té una base de dades textual, gestiona les cançons, els tracklist, sap aturar i arrencar una canço, etc.). Per programar aplicacions que treballin contra el servidor puc plantejar-me clients normals (que utilitzaran MPD), o clients WEB.
Mopidy-MPD (https://docs.mopidy.com/en/latest/ext/mpd/) is an extension that provides a full MPD server implementation to make Mopidy available to MPD clients. It is bundled with Mopidy and enabled by default.
Finalment necessito clients. El client més senzilla treballa amb la consola i està escrit en C: mpc (http://www.musicpd.org/clients/mpc/). A solid, lightweight, simple mpd client, written in C (línia de comanda). mpc: A minimalist command line interface to MPD.
Finalment, si tinc un client que funciona en línia de comanda, ha de ser fàcil integrar-ho amb altres aplicacions fent crides de sistema: system().
Per fer el projecte del moble rockola (jukebox), necessito un servidor media player (que sàpiga gestionar una base de dades i tracklist), i un front-end. Com a servidor tinc mopidy, però necessito una interfície per poder programar aplicacions: mpd. Per tant, si soluciono el tema del servidor, només m'hauré de preocupar de fer el front-end.
En aquesta entrada documentaré mopidy-mpd-mpc a Ubuntu. En el projecte real interessa implementar això en la RPi. Un altre tema que consideraré més endavant és que modpidy ja té una base de dades pròpia, i per tant no sé si quan implementi el meu front-end serà realment necessari una base de dades duplicada. (però aquest és un altre tema).
Instal.lació
Instal.lació a Ubuntu:
wget -q -O - https://apt.mopidy.com/mopidy.gpg | sudo apt-key add - Add the following to /etc/apt/sources.list, or if you have the directory /etc/apt/sources.list.d/, add it to a file called mopidy.list in that directory: # Mopidy APT archive deb http://apt.mopidy.com/ stable main contrib non-free deb-src http://apt.mopidy.com/ stable main contrib non-free For the lazy, you can simply run the following command to create /etc/apt/sources.list.d/mopidy.list: sudo wget -q -O /etc/apt/sources.list.d/mopidy.list https://apt.mopidy.com/mopidy.list Install Mopidy and all dependencies: sudo apt-get update sudo apt-get install mopidy
Configuració
De moment no existeix el fitxer de configuració. El pot crear un mateix a ~/.config/mopidy/mopidy.conf, o executant la comanda mopidy es crearà.
$ mopidy INFO Starting Mopidy 0.19.4 INFO Creating dir /home/joan/.local/share/mopidy INFO Creating dir /home/joan/.config/mopidy INFO Loading config from: builtin defaults, command line options ...
Ara ja puc editar manualment el fitxer de configuració.
Altra informació que es veu:
... INFO Starting Mopidy core INFO Starting Mopidy frontends: HttpFrontend, MpdFrontend INFO HTTP server running at [::ffff:127.0.0.1]:6680 INFO MPD server running at [::ffff:127.0.0.1]:6600
El servidor ja està esperant col.leccions, ja siguin clients web o de clients MPD.
... INFO No local library metadata cache found at /home/joan/.local/share/mopidy/local/library.json.gz. Please run `mopidy local scan` to index your local music library. If you do not have a local music collection, you can disable the local backend to hide this message. INFO Loaded 0 local tracks using json ...
Mirant el fitxer de configuració:
#media_dir = $XDG_MUSIC_DIR #data_dir = $XDG_DATA_DIR/mopidy/local #playlists_dir = $XDG_DATA_DIR/mopidy/local/playlists
queda clar que $XDG_DATA_DIR per defecte és: /home/joan/.local/share/, que és on es guardarà per defecte la base de dades. Però primer hem d'escanejar la nostra col.lecció, i dir quin és el directori on tenim la col.lecció:
media_dir = /home/joan/musica_rockola
$ mopidy local scan ... INFO Found 15 tracks which need to be updated. INFO Scanning... WARNING Failed local:track:TXARANGO%20-%20Som%20Riu/CLOWNIA.pdf: La vostra instal·lació del GStreamer manca un connector. ... INFO Done scanning.
No fer cas a l'últim missatge, és perquè hi ha un pdf que s'ha d'esborrar.
Ara ja tinc la base de dades, i el directori on aniran les playlists:
$ ls /home/joan/.local/share/mopidy/local/ library.json.gz playlists
I ja puc fer funcionar el servidor:
$ mopidy & ... INFO HTTP server running at [::ffff:127.0.0.1]:6680 INFO MPD server running at [::ffff:127.0.0.1]:6600
Ara he d'instal.lar algun client per poder escoltar els fitxers.
La base de dades
Com hem comentat, la base de dades es troba, segons diu el fitxer de configuració, a $XDG_DATA_DIR/mopidy/local que és /home/joan/.local/share/mopidy/local. Aquí dins es troba l'arxiu library.json.gz, i també es troba la carpeta playlists on aniran a parar les playlists que gravem com a fitxer. Mirar el fitxer json veiem quina és l'estructura. Per a la primera cançó tenim:
{ "tracks": [ { "composers": [ { "__model__": "Artist", "name": "Txarango" } ], "album": { "__model__": "Album", "name": "Som Riu", "artists": [ { "__model__": "Artist", "name": "Txarango" } ] }, "__model__": "Track", "name": "Coraz\u00f3n viajero", "uri": "local:track:TXARANGO%20-%20Som%20Riu/10%20Coraz%C2%A2n%20viajero.mp3", "length": 230384, "last_modified": 1394097908, "track_no": 10, "artists": [ { "__model__": "Artist", "name": "Txarango" } ], "date": "2014-01-01", "bitrate": 320000 }, ...
Veiem que el root és tracks. Per tant en definitiva és un array de tracks, cada track és un objecte, i s'opta per una definició del track el més general possible. Veiem que per cada track tenim un array de compositors, informació de l'album a que pertany (i l'album conté un array d'artistes), propietats del track, i un array d'artistes que conté el track. Per tant, és una definició molt completa.
mpc: Music Player Client
És un client MPD, de consola, escrit en llenguatge C.
$ sudo apt-get install mpc $ man mpc NAME mpc - Program for controlling Music Player Daemon (MPD) SYNOPSIS mpc [options] <command> [<arguments>] DESCRIPTION mpc is a client for MPD, the Music Player Daemon. mpc connects to a MPD and controls it according to commands and arguments passed to it. If no command is given, the current status is printed (same as 'mpc status'). ...
Primeres proves:
$ mpc status volume:100% repeat: off random: off single: off consume: off
El primer de tot és afegir cançons a la playlist:
add <file> Adds a song from the music database to the playlist. Can also read input from pipes. Use "mpc ls | mpc add" to add all files to the playlist.
$ mpc listall
no es veu res, cosa curiosa. I és que hi ha una mica de confusió. El fitxer de configuració de MPD està a /etc/mpd.conf, i aquí és el lloc correcte per ficar la ruta de les cançons:
$ joe /etc/mpd.conf ... music_directory "/home/joan/musica_rockola" ...
Reinicio mopidy, i ara sí:
$ mpc listall local:track:TXARANGO%20-%20Som%20Riu/01%20Esperan%C2%87a.mp3 local:track:TXARANGO%20-%20Som%20Riu/02%20M%C2%A3sic%20de%20carrer.mp3 local:track:TXARANGO%20-%20Som%20Riu/03%20La%20vuelta%20al%20mundo.mp3 local:track:TXARANGO%20-%20Som%20Riu/04%20Compta%20amb%20mi.mp3 local:track:TXARANGO%20-%20Som%20Riu/05%20El%20meu%20poble.mp3 local:track:TXARANGO%20-%20Som%20Riu/06%20Alegre%20i%20encantada.mp3 local:track:TXARANGO%20-%20Som%20Riu/07%20Som%20un%20riu.mp3 local:track:TXARANGO%20-%20Som%20Riu/08%20Governant.mp3 local:track:TXARANGO%20-%20Som%20Riu/09%20Batega.mp3 local:track:TXARANGO%20-%20Som%20Riu/10%20Coraz%C2%A2n%20viajero.mp3 local:track:TXARANGO%20-%20Som%20Riu/11%20Camp%20de%20batalla.mp3 local:track:TXARANGO%20-%20Som%20Riu/12%20Com%20dues%20gotes%20d%27aigua.mp3 local:track:TXARANGO%20-%20Som%20Riu/13%20Tant%20de%20bo.mp3 local:track:TXARANGO%20-%20Som%20Riu/14%20No%20t%27adormis.mp3
Afegeixo una cançó i la faig sonar:
$ mpc add local:track:TXARANGO%20-%20Som%20Riu/01%20Esperan%C2%87a.mp3 $ mpc ls Local media $ mpc playlist Txarango - Esperança $ mpc play Txarango - Esperança [playing] #1/1 0:00/3:38 (0%) volume:100% repeat: off random: off single: off consume: off
Afegim totes les cançons a la playlist:
$ mpc ls | mpc add $ mpc playlist Txarango - Esperança Txarango - Esperança Txarango - Músic de carrer Txarango - La vuelta al mundo Txarango - Compta amb mi Txarango - El meu poble Txarango - Alegre i encantada Txarango - Som un riu ... <pre> i esborrem la playlist: <pre> $ mpc clear
Per mostrar la cançó que està sonant en aquests moments:
$ mpc current Txarango - Esperança
Tinc una playlist amb dues cançons.
$ mpc playlist Txarango - Esperança Txarango - Tant de bo
Si vull eliminar una cançó de la playlist, he de fer del:
del <songpos> Removes a playlist number from the playlist. Can also read input from pipes (0 deletes the current playing song). $ mpc del 1 $ mpc playlist Txarango - Tant de bo
També hi ha eines per cercar per tag (find, search, findadd, list)
$ mpc list album Som Riu
mpc: cas pràctic per a la rockola
Es tracta de simular el funcionament de la rockola. Quan poses una moneda, tens dos crèdits i pots escollir dues cançons. Quan esculls la cançó, va a la cua de la playlist (només hi ha una playlist). Ha d'haver-hi un mètode de saber quan una canço s'ha acabat, i retirar-la de la playlist.
Pot ser que una persona posi una moneda mentre està sonant la música. No hi ha problema: les cançons que selecciones s'afegeixen a la playlist.
Per saber quan una cançó acaba, s'ha d'explorar la comanda
$ mpc idle
que espera que hi hagi un event, com ara acabar una cançó (TBD).
Amb tota aquesta informació, es pot fer un joc de proves que simuli la rockola, simulant una moneda amb un scanf.
single mode i consume mode:
The 'single' mode plays song only once, or repeat it if the 'repeat' mode is enabled.
I also implemented the 'consume' mode, which deletes each played song. Patches on mpd, libmpdclient and ncmpc aren't pushed on master repository yet.
Efectivament, el mode consume on funciona. Quan acaba de reproduir-se una cançó, la cançó s'esborra de la playlist. Si tenia 4 cançons, ja només en queden tres.
Simulació rockola
Es tracta de simular el comportament de la rockola. S'engega la màquina i la playlist està a 0. Es fica una moneda=2 crèdits, i puc escollir dues cançons que s'afegeixen a la playlist, i comença a sonar. Ve una altra persona i afegeix dues cançons més, que s'afegeixen a la cua de la playlist. Quan una cançó acaba, desapareix de la playlist (mode consume on). No hi ha cap problema en què es repeteixi una canço. Qualsevol cançó que faig add s'afegeix a la cua.
Amb mpc idle i sobretot mpc idleloop tinc la possibiltiat de capturar els events de quan una cançó canvia. Ara bé, a mi m'interessa captar l'event en un programa C, exactament igual que:
i per sort l'exemple en llenguatge C funciona perfectament:
simulacio_rocola_v1.c:
// https://bbs.archlinux.org/viewtopic.php?id=75518 // gcc prova_v1.c -o prova_v1 -lmpd -I/usr/include/libmpd-1.0/libmpd/ // $ sudo apt-get install libmpd-dev #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <libmpd.h> #include <debug_printf.h> #define RED "\x1b[31;01m" #define DARKRED "\x1b[31;06m" #define RESET "\x1b[0m" #define GREEN "\x1b[32;06m" #define YELLOW "\x1b[33;06m" void status_changed(MpdObj *mi, ChangedStatusType what) { if(what&MPD_CST_SONGID) { mpd_Song *song = mpd_playlist_get_current_song(mi); if(song) { printf(GREEN"Song:"RESET" %s - %s\n", song->artist, song->title); } } } int main() { int run = 1, iport = 6600; char *hostname = getenv("MPD_HOST"); char *port = getenv("MPD_PORT"); char *password = getenv("MPD_PASSWORD"); MpdObj *obj = NULL; if(!hostname) { hostname = "localhost"; } if(port){ iport = atoi(port); } obj = mpd_new(hostname, iport,password); mpd_signal_connect_status_changed(obj,(StatusChangedCallback)status_changed, NULL); mpd_set_connection_timeout(obj, 10); if(!mpd_connect(obj)) { mpd_send_password(obj); do{ mpd_status_update(obj); }while(!usleep(100000) && run); } return 1; }
Per compilar:
$ gcc simulacio_rockola_v1.c -o simulacio_rockola_v1 -lmpd -I/usr/include/libmpd-1.0/libmpd/
comprovar que existeix la llibreria libmpd a /usr/include/libmpd-1.0/libmpd/
Si no hi és, s'ha d'instal.lar:
$ sudo apt-get install libmpd-dev $ ls /usr/include/libmpd-1.0/libmpd/ debug_printf.h libmpd.h libmpd-playlist.h libmpd-strfsong.h libmpdclient.h libmpd-internal.h libmpd-status.h libmpd-version.h libmpd-database.h libmpd-player.h libmpd-sticker.h
cada vegada que canvia una cançó rebo una notificació:
$ ./simulacio_rockola_v1 Song: Txarango - Camp de batalla Song: Txarango - Corazón viajero ...