Skip to content

Commit

Permalink
Handle active_remote_id as a string rather than an unsigned 32-bit n…
Browse files Browse the repository at this point in the history
…umber -- seems ROON uses a longer character sequence.

    Tidy up some error messages about which backend is selected.
    Tighten up memory allocatons in DACP.c.
    Add a default name for the pipe backend: /tmp/shairport-sync-audio
    Ensure the metadata pipe is created, if necessary, when the --with-metadata option is chosen without dbus or mpris
    Make the first output backend in the list of backends the default and make its name the default output_name. Clang-format everything
    Add the word 'jack' to the version string if Jack Audio support is compiled in.
    Fix a flaw in resyncing -- a flush is set up but not triggered.
    Open metadata and audio pipes with 666 permissions.
    Ensure metadata and cover art are enabled if metadata support is included at compilation.
    Reword some misleading error messages.
    Set convolution defaults even if no configuration file is found.
  • Loading branch information
mikebrady committed Sep 30, 2020
1 parent 49084a0 commit 54cb9de
Show file tree
Hide file tree
Showing 15 changed files with 1,122 additions and 1,003 deletions.
2 changes: 1 addition & 1 deletion audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ static audio_output *outputs[] = {
#endif
NULL};

audio_output *audio_get_output(char *name) {
audio_output *audio_get_output(const char *name) {
audio_output **out;

// default to the first
Expand Down
2 changes: 1 addition & 1 deletion audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ typedef struct {

} audio_output;

audio_output *audio_get_output(char *name);
audio_output *audio_get_output(const char *name);
void audio_ls_outputs(void);
void parse_general_audio_options(void);

Expand Down
48 changes: 26 additions & 22 deletions audio_pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
static int fd = -1;

char *pipename = NULL;
char *default_pipe_name = "/tmp/shairport-sync-audio";

static void start(__attribute__((unused)) int sample_rate,
__attribute__((unused)) int sample_format) {
Expand All @@ -51,41 +52,41 @@ static void start(__attribute__((unused)) int sample_rate,
// "ENXIO O_NONBLOCK | O_WRONLY is set, the named file is a FIFO, and no process has the FIFO
// open for reading."

fd = try_to_open_pipe_for_writing(pipename);
// we check that it's not a "real" error. From the "man 2 open" page:
// "ENXIO O_NONBLOCK | O_WRONLY is set, the named file is a FIFO, and no process has the FIFO
// open for reading." Which is okay.
if ((fd == -1) && (errno != ENXIO)) {
char errorstring[1024];
strerror_r(errno, (char *)errorstring, sizeof(errorstring));
debug(1, "audio_pipe start -- error %d (\"%s\") opening pipe: \"%s\".", errno,
(char *)errorstring, pipename);
warn("can not open audio pipe -- error %d (\"%s\") opening pipe: \"%s\".", errno,
(char *)errorstring, pipename);
}
fd = try_to_open_pipe_for_writing(pipename);
// we check that it's not a "real" error. From the "man 2 open" page:
// "ENXIO O_NONBLOCK | O_WRONLY is set, the named file is a FIFO, and no process has the FIFO
// open for reading." Which is okay.
if ((fd == -1) && (errno != ENXIO)) {
char errorstring[1024];
strerror_r(errno, (char *)errorstring, sizeof(errorstring));
debug(1, "audio_pipe start -- error %d (\"%s\") opening pipe: \"%s\".", errno,
(char *)errorstring, pipename);
warn("can not open audio pipe -- error %d (\"%s\") opening pipe: \"%s\".", errno,
(char *)errorstring, pipename);
}
}

static int play(void *buf, int samples) {
// if the file is not open, try to open it.
char errorstring[1024];
if (fd == -1) {
fd = try_to_open_pipe_for_writing(pipename);
fd = try_to_open_pipe_for_writing(pipename);
}
// if it's got a reader, write to it.
if (fd > 0) {
//int rc = non_blocking_write(fd, buf, samples * 4);
// int rc = non_blocking_write(fd, buf, samples * 4);
int rc = write(fd, buf, samples * 4);
if ((rc < 0) && (errno != EPIPE)) {
strerror_r(errno, (char *)errorstring, 1024);
debug(1, "audio_pip play: error %d writing to the pipe named \"%s\": \"%s\".", errno, pipename, errorstring);
debug(1, "audio_pip play: error %d writing to the pipe named \"%s\": \"%s\".", errno,
pipename, errorstring);
}
}
return 0;
}

static void stop(void) {
// Don't close the pipe just because a play session has stopped.

}

static int init(int argc, char **argv) {
Expand All @@ -108,16 +109,19 @@ static int init(int argc, char **argv) {
if (config_lookup_string(config.cfg, "pipe.name", &str)) {
pipename = (char *)str;
}

if ((pipename) && (strcasecmp(pipename, "STDOUT") == 0))
die("Can't use \"pipe\" backend for STDOUT. Use the \"stdout\" backend instead.");
}

if ((pipename == NULL) && (argc != 1))
die("bad or missing argument(s) to pipe");
if (argc > 1)
die("too many command-line arguments to pipe");

if (argc == 1)
pipename = strdup(argv[0]);
pipename = argv[0]; // command line argument has priority

if ((pipename) && (strcasecmp(pipename, "STDOUT") == 0))
die("Can't use \"pipe\" backend for STDOUT. Use the \"stdout\" backend instead.");

if (pipename == NULL)
pipename = default_pipe_name; // if none specified

// here, create the pipe
mode_t oldumask = umask(000);
Expand Down
186 changes: 97 additions & 89 deletions common.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#include "common.h"
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <memory.h>
#include <poll.h>
#include <popt.h>
Expand All @@ -40,8 +42,6 @@
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <libgen.h>

#ifdef COMPILE_FOR_OSX
#include <CoreServices/CoreServices.h>
Expand Down Expand Up @@ -141,64 +141,69 @@ void do_sps_log_to_stdout(__attribute__((unused)) int prio, const char *t, ...)
fprintf(stdout, "%s\n", s);
}

int create_log_file(const char* path) {
int fd = -1;
if (path != NULL) {
char *dirc = strdup(path);
if (dirc) {
char *dname = dirname(dirc);
// create the directory, if necessary
int result = 0;
if (dname) {
char *pdir = realpath(dname, NULL); // will return a NULL if the directory doesn't exist
if (pdir == NULL) {
mode_t oldumask = umask(000);
result = mkpath(dname, 0777);
umask(oldumask);
} else {
free(pdir);
}
if ((result == 0) || (result == -EEXIST)) {
// now open the file
fd = open(path, O_WRONLY | O_NONBLOCK | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if ((fd == -1) && (errno == EEXIST))
fd = open(path, O_WRONLY | O_APPEND | O_NONBLOCK);

if (fd >= 0) {
// now we switch to blocking mode
int flags = fcntl(fd, F_GETFL);
if (flags == -1) {
// strerror_r(errno, (char *)errorstring, sizeof(errorstring));
// debug(1, "create_log_file -- error %d (\"%s\") getting flags of pipe: \"%s\".", errno,
// (char *)errorstring, pathname);
} else {
flags = fcntl(fd, F_SETFL,flags & ~O_NONBLOCK);
// if (flags == -1) {
// strerror_r(errno, (char *)errorstring, sizeof(errorstring));
// debug(1, "create_log_file -- error %d (\"%s\") unsetting NONBLOCK of pipe: \"%s\".", errno,
// (char *)errorstring, pathname);
}
}
}
}
free(dirc);
}
}
return fd;
int create_log_file(const char *path) {
int fd = -1;
if (path != NULL) {
char *dirc = strdup(path);
if (dirc) {
char *dname = dirname(dirc);
// create the directory, if necessary
int result = 0;
if (dname) {
char *pdir = realpath(dname, NULL); // will return a NULL if the directory doesn't exist
if (pdir == NULL) {
mode_t oldumask = umask(000);
result = mkpath(dname, 0777);
umask(oldumask);
} else {
free(pdir);
}
if ((result == 0) || (result == -EEXIST)) {
// now open the file
fd = open(path, O_WRONLY | O_NONBLOCK | O_CREAT | O_EXCL,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if ((fd == -1) && (errno == EEXIST))
fd = open(path, O_WRONLY | O_APPEND | O_NONBLOCK);

if (fd >= 0) {
// now we switch to blocking mode
int flags = fcntl(fd, F_GETFL);
if (flags == -1) {
// strerror_r(errno, (char
//*)errorstring, sizeof(errorstring));
// debug(1, "create_log_file -- error %d (\"%s\") getting flags of pipe: \"%s\".",
// errno,
// (char *)errorstring, pathname);
} else {
flags = fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
// if (flags == -1) {
// strerror_r(errno,
//(char *)errorstring, sizeof(errorstring));
// debug(1, "create_log_file -- error %d
//(\"%s\") unsetting NONBLOCK of pipe: \"%s\".", errno,
//(char *)errorstring, pathname);
}
}
}
}
free(dirc);
}
}
return fd;
}

void do_sps_log_to_fd(__attribute__((unused)) int prio, const char *t, ...) {
char s[1024];
va_list args;
va_start(args, t);
vsnprintf(s, sizeof(s), t, args);
va_end(args);
if (config.log_fd == -1)
config.log_fd = create_log_file(config.log_file_path);
if (config.log_fd >= 0) {
dprintf(config.log_fd, "%s\n", s);
char s[1024];
va_list args;
va_start(args, t);
vsnprintf(s, sizeof(s), t, args);
va_end(args);
if (config.log_fd == -1)
config.log_fd = create_log_file(config.log_file_path);
if (config.log_fd >= 0) {
dprintf(config.log_fd, "%s\n", s);
} else if (errno != ENXIO) { // maybe there is a pipe there but not hooked up
fprintf(stderr, "%s\n", s);
fprintf(stderr, "%s\n", s);
}
}

Expand All @@ -207,9 +212,9 @@ void log_to_stdout() { sps_log = do_sps_log_to_stdout; }
void log_to_file() { sps_log = do_sps_log_to_fd; }
void log_to_syslog() {
#ifdef CONFIG_LIBDAEMON
sps_log = daemon_log;
sps_log = daemon_log;
#else
sps_log = syslog;
sps_log = syslog;
#endif
}

Expand Down Expand Up @@ -309,8 +314,8 @@ void _die(const char *filename, const int linenumber, const char *format, ...) {
1.0 * time_since_last_debug_message / 1000000000, filename,
linenumber, " *fatal error: ");
} else {
strncpy(b, "fatal error: ", sizeof(b));
s = b+strlen(b);
strncpy(b, "fatal error: ", sizeof(b));
s = b + strlen(b);
}
va_list args;
va_start(args, format);
Expand Down Expand Up @@ -339,8 +344,8 @@ void _warn(const char *filename, const int linenumber, const char *format, ...)
1.0 * time_since_last_debug_message / 1000000000, filename,
linenumber, " *warning: ");
} else {
strncpy(b, "warning: ", sizeof(b));
s = b+strlen(b);
strncpy(b, "warning: ", sizeof(b));
s = b + strlen(b);
}
va_list args;
va_start(args, format);
Expand Down Expand Up @@ -1134,37 +1139,37 @@ uint64_t get_absolute_time_in_ns() {
return time_now_ns;
}

int try_to_open_pipe_for_writing(const char* pathname) {
// tries to open the pipe in non-blocking mode first.
// if it succeeds, it sets it to blocking.
// if not, it returns -1.
int try_to_open_pipe_for_writing(const char *pathname) {
// tries to open the pipe in non-blocking mode first.
// if it succeeds, it sets it to blocking.
// if not, it returns -1.

int fdis = open(pathname, O_WRONLY | O_NONBLOCK); // open it in non blocking mode first
int fdis = open(pathname, O_WRONLY | O_NONBLOCK); // open it in non blocking mode first

// we check that it's not a "real" error. From the "man 2 open" page:
// "ENXIO O_NONBLOCK | O_WRONLY is set, the named file is a FIFO, and no process has the FIFO
// open for reading." Which is okay.
// This is checked by the caller.

if (fdis >= 0) {
// now we switch to blocking mode
int flags = fcntl(fdis, F_GETFL);
if (flags == -1) {
char errorstring[1024];
strerror_r(errno, (char *)errorstring, sizeof(errorstring));
debug(1, "try_to_open_pipe -- error %d (\"%s\") getting flags of pipe: \"%s\".", errno,
(char *)errorstring, pathname);
} else {
flags = fcntl(fdis, F_SETFL,flags & ~O_NONBLOCK);
if (flags == -1) {
char errorstring[1024];
strerror_r(errno, (char *)errorstring, sizeof(errorstring));
debug(1, "try_to_open_pipe -- error %d (\"%s\") unsetting NONBLOCK of pipe: \"%s\".", errno,
(char *)errorstring, pathname);
}
}
// now we switch to blocking mode
int flags = fcntl(fdis, F_GETFL);
if (flags == -1) {
char errorstring[1024];
strerror_r(errno, (char *)errorstring, sizeof(errorstring));
debug(1, "try_to_open_pipe -- error %d (\"%s\") getting flags of pipe: \"%s\".", errno,
(char *)errorstring, pathname);
} else {
flags = fcntl(fdis, F_SETFL, flags & ~O_NONBLOCK);
if (flags == -1) {
char errorstring[1024];
strerror_r(errno, (char *)errorstring, sizeof(errorstring));
debug(1, "try_to_open_pipe -- error %d (\"%s\") unsetting NONBLOCK of pipe: \"%s\".", errno,
(char *)errorstring, pathname);
}
}
}
return fdis;
return fdis;
}

/* from
Expand Down Expand Up @@ -1460,6 +1465,9 @@ char *get_version_string() {
#ifdef CONFIG_SNDIO
strcat(version_string, "-sndio");
#endif
#ifdef CONFIG_JACK
strcat(version_string, "-jack");
#endif
#ifdef CONFIG_AO
strcat(version_string, "-ao");
#endif
Expand Down Expand Up @@ -1707,11 +1715,11 @@ int string_update_with_size(char **str, int *flag, char *s, size_t len) {
}

// from https://stackoverflow.com/questions/13663617/memdup-function-in-c, with thanks
void* memdup(const void* mem, size_t size) {
void* out = malloc(size);
void *memdup(const void *mem, size_t size) {
void *out = malloc(size);

if(out != NULL)
memcpy(out, mem, size);
if (out != NULL)
memcpy(out, mem, size);

return out;
return out;
}
Loading

0 comments on commit 54cb9de

Please sign in to comment.