#! /usr/bin/env python # This script is helper to systematicly test the behaviour of MPD's idle # command. It is simply provided as a quick hack, expect nothing more. import logging import pprint import socket host = '' port = 6601 url = "13 - a-ha - White Canvas.mp3" artist = "a-ha" data = {'id': None, 'id2': None, 'url': url, 'artist': artist} # Commands to run before test requests to coerce MPD into right state setup_requests = [ 'clear', 'add "%(url)s"', 'add "%(url)s"', 'add "%(url)s"', 'play', # 'pause', # Uncomment to test paused idle behaviour # 'stop', # Uncomment to test stopped idle behaviour ] # List of commands to test for idle behaviour. Ordering of list is important in # order to keep MPD state as intended. Commands that are obviously # informational only or "harmfull" have been excluded. test_requests = [ 'add "%(url)s"', 'addid "%(url)s" "1"', 'clear', # 'clearerror', # 'close', # 'commands', 'consume "1"', 'consume "0"', # 'count', 'crossfade "1"', 'crossfade "0"', # 'currentsong', # 'delete "1:2"', 'delete "0"', 'deleteid "%(id)s"', 'disableoutput "0"', 'enableoutput "0"', # 'find', # 'findadd "artist" "%(artist)s"', # 'idle', # 'kill', # 'list', # 'listall', # 'listallinfo', # 'listplaylist', # 'listplaylistinfo', # 'listplaylists', # 'lsinfo', 'move "0:1" "2"', 'move "0" "1"', 'moveid "%(id)s" "1"', 'next', # 'notcommands', # 'outputs', # 'password', 'pause', # 'ping', 'play', 'playid "%(id)s"', # 'playlist', 'playlistadd "foo" "%(url)s"', 'playlistclear "foo"', 'playlistadd "foo" "%(url)s"', 'playlistdelete "foo" "0"', # 'playlistfind', # 'playlistid', # 'playlistinfo', 'playlistadd "foo" "%(url)s"', 'playlistadd "foo" "%(url)s"', 'playlistmove "foo" "0" "1"', # 'playlistsearch', # 'plchanges', # 'plchangesposid', 'previous', 'random "1"', 'random "0"', 'rm "bar"', 'rename "foo" "bar"', 'repeat "0"', 'rm "bar"', 'save "bar"', 'load "bar"', # 'search', 'seek "1" "10"', 'seekid "%(id)s" "10"', # 'setvol "10"', 'shuffle', 'shuffle "0:1"', 'single "1"', 'single "0"', # 'stats', # 'status', 'stop', 'swap "1" "2"', 'swapid "%(id)s" "%(id2)s"', # 'tagtypes', # 'update', # 'urlhandlers', # 'volume', ] def create_socketfile(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((host, port)) sock.settimeout(0.5) fd = sock.makefile('rw', 1) # 1 = line buffered fd.readline() # Read banner return fd def wait(fd, prefix=None, collect=None): while True: line = fd.readline().rstrip() if prefix: logging.debug('%s: %s', prefix, repr(line)) if line.split()[0] in ('OK', 'ACK'): break def collect_ids(fd): fd.write('playlistinfo\n') ids = [] while True: line = fd.readline() if line.split()[0] == 'OK': break if line.split()[0] == 'Id:': ids.append(line.split()[1]) return ids def main(): subsystems = {} command = create_socketfile() for test in test_requests: # Remove any old ids del data['id'] del data['id2'] # Run setup code to force MPD into known state for setup in setup_requests: command.write(setup % data + '\n') wait(command) data['id'], data['id2'] = collect_ids(command)[:2] # This connection needs to be make after setup commands are done or # else they will cause idle events. idle = create_socketfile() # Wait for new idle events idle.write('idle\n') test = test % data logging.debug('idle: %s', repr('idle')) logging.debug('command: %s', repr(test)) command.write(test + '\n') wait(command, prefix='command') while True: try: line = idle.readline().rstrip() except socket.timeout: # Abort try if we time out. idle.write('noidle\n') break logging.debug('idle: %s', repr(line)) if line == 'OK': break request_type = test.split()[0] subsystem = line.split()[1] subsystems.setdefault(request_type, set()).add(subsystem) logging.debug('---') pprint.pprint(subsystems) if __name__ == '__main__': main()