#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;
}