#!/bin/env python # This is adapted from mpdlisten.c : https://gist.github.com/sahib/6718139 # 2024 abelliqueux # # MPD client import musicpd from math import floor from os import environ import sys from time import sleep # Relay import RPi.GPIO as GPIO # OLED SSD1306 from luma.core.interface.serial import i2c from luma.core.render import canvas from luma.oled.device import ssd1306 # MPD config off_delay = 3 mpd_host='localhost' mpd_port=6600 mpd_passwd = None mpd_states = ['play', 'pause', 'stop', 'unknown'] # Relay GPIO setup GPIO.setmode(GPIO.BCM) RELAIS_1_GPIO = 17 GPIO.setup(RELAIS_1_GPIO, GPIO.OUT) # GPIO Assign mode # SSD1306 setup serial = i2c(port=1, address=0x3C) device = ssd1306(serial) # TODO: get ctrlc state ctrlc_pressed = False mpd_client_status = {'volume': 'N/A', 'repeat': 'N/A', 'random': 'N/A', 'single': 'N/A', 'consume': 'N/A', 'partition': 'N/A', 'playlist': 'N/A', 'playlistlength': 'N/A', 'mixrampdb': 'N/A', 'state': 'N/A', 'song': 'N/A', 'songid': 'N/A', 'time': '0', 'elapsed': '0', 'bitrate': 'N/A', 'duration': '0', 'audio': 'N/A', 'nextsong': 'N/A', 'nextsongid': 'N/A' } mpd_client_currentsong = {'file': 'N/A', 'last-modified': 'N/A', 'format': 'N/A', 'artist': 'N/A', 'albumartist': 'N/A', 'title': 'N/A', 'album': 'N/A', 'track': 'N/A', 'date': 'N/A', 'genre': 'N/A', 'time': 'N/A', 'duration': 'N/A', 'pos': 'N/A', 'id': 'N/A'} # Source host, port from env variables if 'MPD_HOST' in environ: mpd_host = environ['MPD_HOST'] # Extract password if provided if len(mpd_host.split('@')) > 1: mpd_passwd = mpd_host.split('@')[0] mpd_host = mpd_host.split('@')[1] if 'MPD_PORT' in environ: mpd_port = environ['MPD_PORT'] def sectomin(sec:str): minute = 0 minute = floor(float(sec)/60) second = round(float(sec)-minute*60) return "{}:{}".format(str(minute), str(second)) def update_display(device, currentsong, status): # ~ print(currentsong['artist']) # ~ print(currentsong['title']) # ~ print(status['time']) # ~ print("{}/{}".format(status['time'], sectomin(status['duration']))) with canvas(device) as draw: draw.rectangle(device.bounding_box, outline="white", fill="black") draw.text((10, 5), currentsong['artist'], fill="white") draw.text((10, 18), currentsong['title'], fill="white") draw.text((10, 31), currentsong['album'], fill="white") draw.text((10, 44), "{}/{}".format(status['time'], sectomin(status['duration'])), fill="white") draw.regular_polygon(bounding_circle=(14, 55, 8), n_sides=3, rotate=90, fill="white") def main(args): previous_sond_id = None previous_state = None paused_since_seconds = 0 # MPDclient setup client = musicpd.MPDClient() if mpd_passwd is not None: client.pwd = mpd_passwd client.host = mpd_host client.port = mpd_port client.mpd_timeout = 5 try: client.connect() except musicpd.ConnectionError as errorMessage: print(repr(errorMessage)) print("Check host and port are correct.") # ~ print(client.status()) # duration, elapsed, volume, repeat, random, single # ~ print(client.currentsong()) # artist, title, album while ctrlc_pressed is False: mpd_status = client.status() if len(mpd_status): mpd_client_status = mpd_status mpd_client_currentsong = client.currentsong() play_state = client.status()['state'] current_song_id = client.status()['songid'] if play_state in mpd_states: if play_state == 'play': paused_since_seconds = 0 if (current_song_id != previous_sond_id) and (previous_state != play_state): print("Play") # Relay on GPIO.output(RELAIS_1_GPIO, GPIO.HIGH) if play_state == 'pause': if paused_since_seconds < off_delay: paused_since_seconds += 1 print("Paused for {}".format(str(paused_since_seconds))) if (paused_since_seconds >= off_delay) and GPIO.input(RELAIS_1_GPIO): print("Off") # Relay off GPIO.output(RELAIS_1_GPIO, GPIO.LOW) if play_state == 'stop' or play_state == 'unknown': previous_sond_id = None paused_since_seconds = 0 if previous_state != play_state: print("Stopped") # Relay off GPIO.output(RELAIS_1_GPIO, GPIO.LOW) previous_state = play_state sleep(1) update_display(device, mpd_client_currentsong, mpd_client_status) client.disconnect() return 0 if __name__ == '__main__': sys.exit(main(sys.argv[1:]))