#include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <wiringPi.h> #include <mpd/client.h> #include <unistd.h> #include <stdbool.h> #include <signal.h> pthread_mutex_t isr_mtx = PTHREAD_MUTEX_INITIALIZER; volatile sig_atomic_t pin_pressed= 0; unsigned int last_pressed_time = 0; #define FASTFORWARD_PIN 5 #define PLAYPAUSE_PIN 6 #define REWIND_PIN 13 #define VOLUMEDOWN_PIN 26 #define ONOFF_PIN 12 #define VOLUMEUP_PIN 16 void serviceInterrupt(int pin) { pthread_mutex_lock(&isr_mtx); unsigned int now = millis(); if ((last_pressed_time + 100) < now) { pin_pressed = pin; last_pressed_time = now; } else { pin_pressed = 0; } pthread_mutex_unlock(&isr_mtx); } void fastForwardInterrupt() { serviceInterrupt(FASTFORWARD_PIN); } void playPauseInterrupt() { serviceInterrupt(PLAYPAUSE_PIN); } void rewindInterrupt() { serviceInterrupt(REWIND_PIN); } void volumeDownInterrupt() { serviceInterrupt(VOLUMEDOWN_PIN); } void onOffInterrupt() { serviceInterrupt(ONOFF_PIN); } void volumeUpInterrupt() { serviceInterrupt(VOLUMEUP_PIN); } int main() { struct mpd_connection *conn; unsigned int tries = 0; signal(SIGPIPE, SIG_IGN); // don't die on connection issues conn = mpd_connection_new("/run/mpd.socket", 0, 0); while ((mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) && (tries < 60)) { mpd_connection_free(conn); conn = mpd_connection_new("/run/mpd.socket", 0, 0); tries++; sleep(1); } if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) { mpd_connection_free(conn); return EXIT_FAILURE; } mpd_connection_set_keepalive(conn, true); wiringPiSetupGpio(); pullUpDnControl(FASTFORWARD_PIN, PUD_UP); pullUpDnControl(PLAYPAUSE_PIN, PUD_UP); pullUpDnControl(REWIND_PIN, PUD_UP); pullUpDnControl(VOLUMEDOWN_PIN, PUD_UP); pullUpDnControl(ONOFF_PIN, PUD_UP); pullUpDnControl(VOLUMEUP_PIN, PUD_UP); wiringPiISR(FASTFORWARD_PIN, INT_EDGE_FALLING, &fastForwardInterrupt); wiringPiISR(PLAYPAUSE_PIN, INT_EDGE_FALLING, &playPauseInterrupt); wiringPiISR(REWIND_PIN, INT_EDGE_FALLING, &rewindInterrupt); wiringPiISR(VOLUMEDOWN_PIN, INT_EDGE_FALLING, &volumeDownInterrupt); wiringPiISR(ONOFF_PIN, INT_EDGE_FALLING, &onOffInterrupt); wiringPiISR(VOLUMEUP_PIN, INT_EDGE_FALLING, &volumeUpInterrupt); bool playing = true; for(;;) { bool success = false; while(!success) { switch(pin_pressed) { case PLAYPAUSE_PIN: success = mpd_run_toggle_pause(conn); printf("play/pause %d\n", success); break; case ONOFF_PIN: if (playing) { success = mpd_run_stop(conn); printf("stop %d\n", success); } else { success = mpd_run_play(conn); printf("start %d\n", success); } if (success) { playing = !playing; } break; case FASTFORWARD_PIN: success = mpd_run_next(conn); printf("ff %d\n", success); break; case REWIND_PIN: success = mpd_run_previous(conn); printf("rw %d\n", success); break; case VOLUMEDOWN_PIN: success = mpd_run_change_volume(conn, -10); printf("vol- %d\n", success); break; case VOLUMEUP_PIN: success = mpd_run_change_volume(conn, 10); printf("vol+ %d\n", success); break; default: success = true; break; } if (pin_pressed != 0) { pthread_mutex_lock(&isr_mtx); pin_pressed = 0; pthread_mutex_unlock(&isr_mtx); } if (!success) { switch(mpd_connection_get_error(conn)) { case MPD_ERROR_SERVER: case MPD_ERROR_ARGUMENT: case MPD_ERROR_STATE: case MPD_ERROR_MALFORMED: mpd_connection_clear_error(conn); printf("Clear error, don't try again.\n"); success = true; break; default: printf("Error code %d\n", mpd_connection_get_error(conn)); mpd_connection_free(conn); conn = mpd_connection_new("/run/mpd.socket", 0, 0); if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) { mpd_connection_free(conn); return EXIT_FAILURE; } printf("Reconnected, try again.\n"); break; } } } } mpd_connection_free(conn); return 0; }