Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
snippets/jellybean_trigger/jellybean_trigger.c
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
110 lines (88 sloc)
2.31 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* jellybean_trigger.c | |
Author: Rogach, William Woodruff | |
------------------------ | |
Uses libesd (ALSA) to monitor a jellybean button, executing a command | |
when the button is pushed. | |
Modified from https://github.com/Rogach/piano-pedal-driver | |
------------------------ | |
The original does not appear to be under any license, so this one will | |
remain in the public domain. | |
*/ | |
/* | |
NOTES: | |
npeaks = 125 works well for the inline button on my headphones (cheap panasonics) | |
npeaks = 64 works well for the jellybean buttons i've used | |
*/ | |
#include <unistd.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <esd.h> | |
#include <fcntl.h> | |
#define MIN_THRESH 120 | |
#define MAX_THRESH 127 | |
#define IN_THRESH(n) ((n <= MAX_THRESH) && (n >= MIN_THRESH)) | |
int jellybean(unsigned int npeaks, char **cmd); | |
int main(int argc, char **argv) | |
{ | |
int rc; | |
unsigned int npeaks = 0; | |
if (argc < 3) { | |
printf("Usage: %s <npeaks> <command [arg ...]>\n", argv[0]); | |
return 1; | |
} | |
sscanf(argv[1], "%u", &npeaks); | |
if (!npeaks) { | |
fprintf(stderr, "Fatal: Invalid `npeaks` given (positive integer expected).\n"); | |
return 2; | |
} | |
rc = jellybean(npeaks, argv + 2); | |
return rc; | |
} | |
int jellybean(unsigned int npeaks, char **cmd) | |
{ | |
int esd_socket = 0; | |
esd_format_t format = ESD_BITS16 | ESD_STEREO | ESD_STREAM | ESD_MONITOR; | |
while (esd_socket == 0) { | |
esd_socket = esd_record_stream_fallback(format, 1000, NULL, "ppd"); | |
if (esd_socket < 0) { | |
fprintf(stderr, "Fatal: Failed to open ESD socket.\n"); | |
return 1; | |
} | |
if (esd_socket == 0) { | |
fprintf(stderr, "Error: ESD not ready: got socket #0.\n"); | |
close(esd_socket); | |
sleep(3); | |
} | |
} | |
if (fcntl(esd_socket, F_SETFL, O_NONBLOCK) == -1) { | |
fprintf(stderr, "Fatal: Failed to set socket to non-blocking mode.\n"); | |
return 1; | |
} | |
while (1) { | |
unsigned char buffer[1024*64]; | |
int nbytes, peaks, i; | |
pid_t pid; | |
usleep(10000); | |
nbytes = read(esd_socket, buffer, sizeof(buffer)); | |
for (i = 1; i < nbytes; i += 2) { | |
if (IN_THRESH(buffer[i])) { | |
peaks++; | |
} | |
} | |
if (peaks > npeaks) { | |
switch (pid = fork()) { | |
case 0: | |
if (execvp(cmd[0], cmd) < 0) { | |
fprintf(stderr, "Error: Could not exec %s.\n", cmd[0]); | |
} | |
break; | |
case -1: | |
fprintf(stderr, "Fatal: Could not fork().\n"); | |
return 1; | |
} | |
} | |
peaks = 0; | |
} | |
close(esd_socket); | |
return 0; | |
} |