Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 25 additions & 65 deletions audio_pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,98 +28,58 @@
#include <unistd.h>
#include <fcntl.h>
#include <memory.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include "common.h"
#include "audio.h"

static int fd = -1;
static char *pipename = NULL;
static int Fs;
static long long starttime, samples_played;

static void stop(void) {
close(fd);
fd = -1;
}

static void start(int sample_rate) {
if (fd >= 0)
stop();

fd = open(pipename, O_WRONLY | O_NONBLOCK);
if ((fd < 0) && (errno != ENXIO)) {
int readfd;

Fs = sample_rate;

readfd = open(pipename, O_RDONLY | O_NONBLOCK);
if (readfd < 0) {
perror("open");
die("could not open specified pipe for reading");
}
fd = open(pipename, O_WRONLY);
if (fd < 0) {
perror("open");
die("could not open specified pipe for writing");
}

// The other end is ready, reopen with blocking
if (fd >= 0) {
close(fd);
fd = open(pipename, O_WRONLY);
}

Fs = sample_rate;
starttime = 0;
samples_played = 0;
}

// Wait procedure taken from audio_dummy.c
static void wait_samples(int samples) {
struct timeval tv;

// this is all a bit expensive but it's long-term stable.
gettimeofday(&tv, NULL);

long long nowtime = tv.tv_usec + 1e6*tv.tv_sec;

if (!starttime)
starttime = nowtime;

samples_played += samples;

long long finishtime = starttime + samples_played * 1e6 / Fs;

usleep(finishtime - nowtime);
close(readfd);
}

static void play(short buf[], int samples) {
if (fd < 0) {
wait_samples(samples);

// check if the other end is ready every 5 seconds
if (samples_played > 5 * Fs)
start(Fs);

return;
}
int rc;

rc = write(fd, buf, samples*4);
if (rc <=0) usleep(1e6 * samples / Fs);
}

if (write(fd, buf, samples*4) < 0)
stop();
static void stop(void) {
close(fd);
}

static int init(int argc, char **argv) {
struct stat sb;

if (argc != 1)
die("bad argument(s) to pipe");

pipename = strdup(argv[0]);

if (stat(pipename, &sb) < 0)
die("could not stat() pipe");

if (!S_ISFIFO(sb.st_mode))
die("not a pipe");

// test open pipe so we error on startup if it's going to fail
start(44100);
stop();

return 0;
}

static void deinit(void) {
if (fd >= 0)
stop();
if (fd > 0)
close(fd);
if (pipename)
free(pipename);
}
Expand Down