Tutorials¶
Install¶
For now the code is in early development stage. No releases are made.
# Use a virtualenv
python -m venv .../path/to/my/venv
. .../path/to/my/venv/bin/activate
pip install git+https://codeberg.org/MusicPlayerDaemon/python-musicpdaio.git@main
Getting started¶
Connect, clear the queue, add tracks
import mpdaio
client = mpdaio.MPDClient()
await client.ping() # Plain connection test
print(client.version) # Prints MPD's protocol version
print(await client.clear()) # Clears the current queue
# Add all tracks from artist "Amon Tobin"
print(await client.searchadd('(Artist == "Amon Tobin")'))
await client.play()
await client.setvol(60)
print(await client.currentsong())
await client.close() # Finally close connection
musicpdaio tries to come with sane defaults, then running
mpdaio.MPDClient with no explicit argument will try default values
to connect to MPD. Cf. Reference for more about
defaults.
Using a specific host, port and a password.
The password is sent when a connection is made, no need to explicitly use the password command. In the following code a client is constructed with a password argument, then when the ping method is called:
the client fetch a connection from the pool
then a password command is sent with the password
finally the ping command is sent.
client = mpdaio.MPDClient(host='example.org', port='6601', password='53(237')
await client.ping()
Wrapping some commands in a python script
# mpd-client.py
import asyncio
import logging
from mpdaio import MPDClient
# Configure loggers
logging.basicConfig(level=logging.INFO, format='%(levelname)-8s %(message)s')
logging.getLogger("asyncio").setLevel(logging.WARNING)
# debug level level will show where defaults settings come from
log = logging.getLogger('mpdaio.client')
log.setLevel(logging.DEBUG)
async def run():
# Explicit host declaration
#client = MPDClient(host='example.org', port='6601')
# Use defaults
client = MPDClient()
# MPDClient use MPD_HOST/MPD_PORT env var if set
# else test ${XDG_RUNTIME_DIR}/mpd/socket for existence
# finnally fallback to localhost:6600
# Make an initial connection to MPD server
# The connection is kept open an reused for later commands
await client.ping()
# Get player status
status = await client.status()
if status.get('state') == 'play':
current_song_id = status.get('songid')
current_song = await client.playlistid(current_song_id)
log.info(f'Playing : {current_song[0].get("file")}')
next_song_id = status.get('nextsongid', None)
if next_song_id:
next_song = await client.playlistid(next_song_id)
log.info(f'Next song : {next_song[0].get("file")}')
else:
log.info('Not playing')
# Add all songs form artist "The Doors"
await client.searchadd('(Artist == "The Doors")')
# Start playing
if (await client.status()).get('state') != 'play':
await client.play()
# Closes any remaining connections to MPD server
await client.close()
if __name__ == '__main__':
asyncio.run(run())
Fetch album art for the given track
The logic is similar with readpicture command.
client = mpdaio.MPDClient()
# Looking for cover art in 'Tool/2001-Lateralus/'
track = 'Tool/2001-Lateralus/09-Tool - Lateralus.flac'
aart = await cli.albumart(track, 0)
received = int(aart.get('binary'))
size = int(aart.get('size'))
with open('/tmp/cover', 'wb') as cover:
# aart = {'size': 42, 'binary': 2051, data: bytes(...)}
cover.write(aart.get('data'))
while received < size:
aart = await cli.albumart(track, received)
cover.write(aart.get('data'))
received += int(aart.get('binary'))
if received != size:
print('something went wrong')
await cli.close()
Cf. MPD protocol documentation for more binary responses.
Concurrency¶
import asyncio
import logging
from mpdaio import MPDClient
# Configure loggers
logging.basicConfig(level=logging.INFO, format='%(levelname)-8s %(message)s')
logging.getLogger("asyncio").setLevel(logging.WARNING)
# debug level level will show where defaults settings come from
log = logging.getLogger('mpdaio.client')
log.setLevel(logging.DEBUG)
async def search(fltr):
# Look for and add
await client.searchadd(fltr)
async def run():
# Make an initial connection to MPD server
# The connection is kept open an reused for later commands
await client.ping()
await client.clear()
filters = [
'(Artist == "Neurosis")',
'(Artist == "Isis")',
'(Artist == "Cult of Luna")',
]
# Each task gathered here will run with it's own connection
await asyncio.gather(*map(search, filters))
# Closes all connections to MPD server
await client.close()
if __name__ == '__main__':
# Use defaults to access MPD server
client = MPDClient()
asyncio.run(run())