Skip to content

Commit

Permalink
4.1.1 almost...
Browse files Browse the repository at this point in the history
  • Loading branch information
mikebrady committed Dec 5, 2022
2 parents 029baf2 + 02c0a15 commit acdae45
Show file tree
Hide file tree
Showing 28 changed files with 648 additions and 235 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/check_ap2_systemd_basic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
jobs:
build:

runs-on: ubuntu-latest
runs-on: ubuntu-22.04

steps:
- uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/check_ap2_systemd_full.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
jobs:
build:

runs-on: ubuntu-latest
runs-on: ubuntu-22.04

steps:
- uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/check_ap2_systemd_full_build_folder.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
jobs:
build:

runs-on: ubuntu-latest
runs-on: ubuntu-22.04

steps:
- uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/check_ap2_systemv_full.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
jobs:
build:

runs-on: ubuntu-latest
runs-on: ubuntu-22.04

steps:
- uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/check_classic_systemd_basic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
jobs:
build:

runs-on: ubuntu-latest
runs-on: ubuntu-22.04

steps:
- uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/check_classic_systemd_full.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
jobs:
build:

runs-on: ubuntu-latest
runs-on: ubuntu-22.04

steps:
- uses: actions/checkout@v3
Expand Down
3 changes: 2 additions & 1 deletion BUILD.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ Do this until no more copies of `shairport-sync` are found.
You should also remove any of the following service files that may be present:
* `/etc/systemd/system/shairport-sync.service`
* `/etc/systemd/user/shairport-sync.service`
* `/lib/systemd/system/shairport-sync.service`
* `/lib/systemd/user/shairport-sync.service`
* `/etc/init.d/shairport-sync`
* `/etc/init.d/shairport-sync`

New service files will be installed if necessary at the `# make install` stage.
#### Reboot after Cleaning Up
Expand Down
6 changes: 4 additions & 2 deletions activity_monitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ pthread_mutex_t activity_monitor_mutex;
pthread_cond_t activity_monitor_cv;

void going_active(int block) {
// debug(1, "activity_monitor: state transitioning to \"active\" with%s blocking", block ? "" : "out");
// debug(1, "activity_monitor: state transitioning to \"active\" with%s blocking", block ? "" :
// "out");
if (config.cmd_active_start)
command_execute(config.cmd_active_start, "", block);
#ifdef CONFIG_METADATA
Expand All @@ -75,7 +76,8 @@ void going_active(int block) {
}

void going_inactive(int block) {
// debug(1, "activity_monitor: state transitioning to \"inactive\" with%s blocking", block ? "" : "out");
// debug(1, "activity_monitor: state transitioning to \"inactive\" with%s blocking", block ? "" :
// "out");
if (config.cmd_active_stop)
command_execute(config.cmd_active_stop, "", block);
#ifdef CONFIG_METADATA
Expand Down
4 changes: 3 additions & 1 deletion audio_alsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,9 @@ static int precision_delay_available() {
// this is very crude -- if the device is a hardware device, then it's assumed the delay is
// precise
const char *output_device_name = snd_pcm_name(alsa_handle);
int is_a_real_hardware_device = (strstr(output_device_name, "hw:") == output_device_name);
int is_a_real_hardware_device = 0;
if (output_device_name != NULL)
is_a_real_hardware_device = (strstr(output_device_name, "hw:") == output_device_name);

// The criteria as to whether precision delay is available
// is whether the device driver returns non-zero update timestamps
Expand Down
165 changes: 102 additions & 63 deletions audio_pa.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,12 +155,11 @@ static int init(__attribute__((unused)) int argc, __attribute__((unused)) char *
static void deinit(void) {
pa_threaded_mainloop_stop(mainloop);
pa_threaded_mainloop_free(mainloop);
// debug(1, "pa deinit done");
debug(1, "pa deinit done");
}

static void start(__attribute__((unused)) int sample_rate,
__attribute__((unused)) int sample_format) {

static void do_start() {
// debug(1, "pa_start");
uint32_t buffer_size_in_bytes = (uint32_t)2 * 2 * RATE * 0.1; // hard wired in here
// debug(1, "pa_buffer size is %u bytes.", buffer_size_in_bytes);

Expand Down Expand Up @@ -223,88 +222,128 @@ static void start(__attribute__((unused)) int sample_rate,
pa_threaded_mainloop_unlock(mainloop);
}

static void start(__attribute__((unused)) int sample_rate,
__attribute__((unused)) int sample_format) {
do_start();
}

static int stream_is_open() {
int response = 0; // default to no
pa_usec_t latency;
int negative;
pa_threaded_mainloop_lock(mainloop);
int gl = pa_stream_get_latency(stream, &latency, &negative);
pa_threaded_mainloop_unlock(mainloop);
if (gl >= 0)
response = 1;
return response;
}

static int play(void *buf, int samples, __attribute__((unused)) int sample_type,
__attribute__((unused)) uint32_t timestamp,
__attribute__((unused)) uint64_t playtime) {
// debug(1,"pa_play of %d samples.",samples);
// copy the samples into the queue
size_t bytes_to_transfer = samples * 2 * 2;
size_t space_to_end_of_buffer = audio_umb - audio_eoq;
if (space_to_end_of_buffer >= bytes_to_transfer) {
memcpy(audio_eoq, buf, bytes_to_transfer);
audio_occupancy += bytes_to_transfer;
pthread_mutex_lock(&buffer_mutex);
audio_eoq += bytes_to_transfer;
pthread_mutex_unlock(&buffer_mutex);
} else {
memcpy(audio_eoq, buf, space_to_end_of_buffer);
buf += space_to_end_of_buffer;
memcpy(audio_lmb, buf, bytes_to_transfer - space_to_end_of_buffer);
pthread_mutex_lock(&buffer_mutex);
audio_occupancy += bytes_to_transfer;
pthread_mutex_unlock(&buffer_mutex);
audio_eoq = audio_lmb + bytes_to_transfer - space_to_end_of_buffer;
if (stream_is_open() == 0) {
// debug(1,"pa open stream before play.");
do_start();
}
if ((audio_occupancy >= 11025 * 2 * 2) && (pa_stream_is_corked(stream))) {
// debug(1,"Uncorked");
pa_threaded_mainloop_lock(mainloop);
pa_stream_cork(stream, 0, stream_success_cb, mainloop);
pa_threaded_mainloop_unlock(mainloop);
if (stream_is_open() != 0) {
// copy the samples into the queue
size_t bytes_to_transfer = samples * 2 * 2;
size_t space_to_end_of_buffer = audio_umb - audio_eoq;
if (space_to_end_of_buffer >= bytes_to_transfer) {
memcpy(audio_eoq, buf, bytes_to_transfer);
audio_occupancy += bytes_to_transfer;
pthread_mutex_lock(&buffer_mutex);
audio_eoq += bytes_to_transfer;
pthread_mutex_unlock(&buffer_mutex);
} else {
memcpy(audio_eoq, buf, space_to_end_of_buffer);
buf += space_to_end_of_buffer;
memcpy(audio_lmb, buf, bytes_to_transfer - space_to_end_of_buffer);
pthread_mutex_lock(&buffer_mutex);
audio_occupancy += bytes_to_transfer;
pthread_mutex_unlock(&buffer_mutex);
audio_eoq = audio_lmb + bytes_to_transfer - space_to_end_of_buffer;
}
if ((audio_occupancy >= 11025 * 2 * 2) && (pa_stream_is_corked(stream))) {
// debug(1,"Uncorked");
pa_threaded_mainloop_lock(mainloop);
pa_stream_cork(stream, 0, stream_success_cb, mainloop);
pa_threaded_mainloop_unlock(mainloop);
}
} else {
// debug(2, "could not open pa stream for play");
}
return 0;
}

int pa_delay(long *the_delay) {
long result = 0;
// debug(1,"pa_delay");
int reply = -ENODEV;
pa_usec_t latency;
int negative;
pa_threaded_mainloop_lock(mainloop);
int gl = pa_stream_get_latency(stream, &latency, &negative);
pa_threaded_mainloop_unlock(mainloop);
if (gl == PA_ERR_NODATA) {
// debug(1, "No latency data yet.");
reply = -ENODEV;
} else if (gl != 0) {
// debug(1,"Error %d getting latency.",gl);
reply = -EIO;
long result = 0;
if (stream_is_open() == 0) {
// debug(1,"pa open stream before delay.");
do_start();
}
if (stream_is_open() != 0) {
pa_usec_t latency;
int negative;
pa_threaded_mainloop_lock(mainloop);
int gl = pa_stream_get_latency(stream, &latency, &negative);
pa_threaded_mainloop_unlock(mainloop);
if (gl == PA_ERR_NODATA) {
// debug(1, "No latency data yet.");
reply = -ENODEV;
} else if (gl != 0) {
// debug(1,"Error %d getting latency.",gl);
reply = -EIO;
} else {
result = (audio_occupancy / (2 * 2)) + (latency * 44100) / 1000000;
reply = 0;
}
} else {
result = (audio_occupancy / (2 * 2)) + (latency * 44100) / 1000000;
reply = 0;
// debug(2, "could not open pa stream for delay");
}
*the_delay = result;
return reply;
}

void flush(void) {
// Cork the stream so it will stop playing
pa_threaded_mainloop_lock(mainloop);
if (pa_stream_is_corked(stream) == 0) {
// debug(1,"Flush and cork for flush.");
pa_stream_flush(stream, stream_success_cb, NULL);
pa_stream_cork(stream, 1, stream_success_cb, mainloop);
// debug(1,"Flush.");
if (stream_is_open() != 0) {
// Cork the stream so it will stop playing
pa_threaded_mainloop_lock(mainloop);
if (pa_stream_is_corked(stream) == 0) {
// debug(1,"Flush and cork for flush.");
pa_stream_flush(stream, stream_success_cb, NULL);
pa_stream_cork(stream, 1, stream_success_cb, mainloop);
}
pa_threaded_mainloop_unlock(mainloop);
audio_toq = audio_eoq = audio_lmb;
audio_umb = audio_lmb + audio_size;
audio_occupancy = 0;
}
pa_threaded_mainloop_unlock(mainloop);
audio_toq = audio_eoq = audio_lmb;
audio_umb = audio_lmb + audio_size;
audio_occupancy = 0;
}

static void stop(void) {
// Cork the stream so it will stop playing
pa_threaded_mainloop_lock(mainloop);
if (pa_stream_is_corked(stream) == 0) {
// debug(1,"Flush and cork for stop.");
pa_stream_flush(stream, stream_success_cb, NULL);
pa_stream_cork(stream, 1, stream_success_cb, mainloop);
}
pa_threaded_mainloop_unlock(mainloop);
audio_toq = audio_eoq = audio_lmb;
audio_umb = audio_lmb + audio_size;
audio_occupancy = 0;
// debug(1,"Stop.");
if (stream_is_open() != 0) {
// Cork the stream so it will stop playing
pa_threaded_mainloop_lock(mainloop);
if (pa_stream_is_corked(stream) == 0) {
// debug(1,"Flush and cork for stop.");
pa_stream_flush(stream, stream_success_cb, NULL);
pa_stream_cork(stream, 1, stream_success_cb, mainloop);
}
pa_threaded_mainloop_unlock(mainloop);
audio_toq = audio_eoq = audio_lmb;
audio_umb = audio_lmb + audio_size;
audio_occupancy = 0;

// debug(1,"pa stop");
pa_stream_disconnect(stream);
// debug(1,"pa stop");
pa_stream_disconnect(stream);
}
}

audio_output audio_pa = {.name = "pa",
Expand Down
4 changes: 3 additions & 1 deletion audio_pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,9 @@ static void deinit(void) {
close(fd);
}

static void help(void) { printf(" Provide the pipe's pathname. The default is \"%s\".\n", default_pipe_name); }
static void help(void) {
printf(" Provide the pipe's pathname. The default is \"%s\".\n", default_pipe_name);
}

audio_output audio_pipe = {.name = "pipe",
.help = &help,
Expand Down
2 changes: 2 additions & 0 deletions common.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ typedef struct {
int metadata_sockport;
size_t metadata_sockmsglength;
int get_coverart;
double metadata_progress_interval; // 0 means no progress reports
#endif
#ifdef CONFIG_MQTT
int mqtt_enabled;
Expand All @@ -159,6 +160,7 @@ typedef struct {
int mqtt_enable_remote;
char *mqtt_empty_payload_substitute;
#endif
uint8_t ap1_prefix[6];
uint8_t hw_addr[8]; // only needs 6 but 8 is handy when converting this to a number
int port;
int udp_port_base;
Expand Down
7 changes: 6 additions & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,8 @@ AM_CONDITIONAL([USE_METADATA], [test "x$with_metadata" = "xyes"])
AC_ARG_WITH(airplay-2, [AS_HELP_STRING([--with-airplay-2],[Build for AirPlay 2])])
if test "x$with_airplay_2" = "xyes" ; then
AC_DEFINE([CONFIG_AIRPLAY_2], 1, [Build for AirPlay 2])
AC_CHECK_PROG(XXD_CHECK,xxd,yes)
AS_IF([test x"$XXD_CHECK" != x"yes"], [AC_MSG_ERROR([xxd can not be found. Please install xxd for building for AirPlay 2.])])
PKG_CHECK_MODULES([libplist], [libplist >= 2.0.0],[CFLAGS="${libplist_CFLAGS} ${CFLAGS}" LIBS="${libplist_LIBS} ${LIBS}"],[
PKG_CHECK_MODULES([libplist], [libplist-2.0 >= 2.0.0],[CFLAGS="${libplist_CFLAGS} ${CFLAGS}" LIBS="${libplist_LIBS} ${LIBS}"],[
AC_MSG_ERROR(AirPlay 2 support requires libplist 2.0.0 or later -- search for pkg libplist-dev on Debian or libplist-2.2.0 or later on FreeBSD!)
Expand All @@ -420,7 +422,10 @@ if test "x$with_airplay_2" = "xyes" ; then
PKG_CHECK_MODULES([libavutil], [libavutil],[CFLAGS="${libavutil_CFLAGS} ${CFLAGS}" LIBS="${libavutil_LIBS} ${LIBS}"],[
AC_MSG_ERROR(AirPlay 2 support requires libavutil -- libavutil-dev suggested)])
PKG_CHECK_MODULES([libavcodec], [libavcodec],[CFLAGS="${libavcodec_CFLAGS} ${CFLAGS}" LIBS="${libavcodec_LIBS} ${LIBS}"],[
AC_MSG_ERROR(AirPlay 2 support requires libavcodec -- libavcodec-dev suggested)])
AC_CHECK_LIB([avcodec], [avcodec_find_decoder], [], [
AC_MSG_ERROR(AirPlay 2 support requires libavcodec -- libavcodec-dev suggested)
])
])
AC_CHECK_LIB([avformat],[avformat_new_stream], [], [AC_MSG_ERROR([AirPlay 2 support requires libavformat -- libavformat-dev suggested])])
AC_CHECK_LIB([swresample],[swr_convert], [], [AC_MSG_ERROR([AirPlay 2 support requires libswresample -- libswresample-dev suggested])])
AC_CHECK_LIB([uuid],[uuid_generate], [], [AC_MSG_ERROR([AirPlay 2 support requires the uuid library -- uuid-dev suggested])])
Expand Down
15 changes: 9 additions & 6 deletions dacp.c
Original file line number Diff line number Diff line change
Expand Up @@ -803,8 +803,9 @@ void *dacp_monitor_thread_code(__attribute__((unused)) void *na) {
case 'canp': // nowplaying 4 ids: dbid, plid, playlistItem, itemid (from mellowware
// see reference above)
debug(2, "DACP Composite ID seen");
if (memcmp(metadata_store.item_composite_id, sp - item_size,
sizeof(metadata_store.item_composite_id)) != 0) {
if ((metadata_store.item_composite_id_is_valid == 0) ||
(memcmp(metadata_store.item_composite_id, sp - item_size,
sizeof(metadata_store.item_composite_id)) != 0)) {
memcpy(metadata_store.item_composite_id, sp - item_size,
sizeof(metadata_store.item_composite_id));
char st[33];
Expand All @@ -817,6 +818,7 @@ void *dacp_monitor_thread_code(__attribute__((unused)) void *na) {
*pt = 0;
debug(2, "Item composite ID changed to 0x%s.", st);
metadata_store.item_composite_id_changed = 1;
metadata_store.item_composite_id_is_valid = 1;
}
break;
case 'astm':
Expand All @@ -826,6 +828,7 @@ void *dacp_monitor_thread_code(__attribute__((unused)) void *na) {
if (ui != metadata_store.songtime_in_milliseconds) {
metadata_store.songtime_in_milliseconds = ui;
metadata_store.songtime_in_milliseconds_changed = 1;
metadata_store.songtime_in_milliseconds_is_valid = 1;
debug(2, "DACP Song Time set to: \"%u\"",
metadata_store.songtime_in_milliseconds);
}
Expand Down Expand Up @@ -1219,8 +1222,8 @@ int dacp_get_volume(int32_t *the_actual_volume) {
http_response = dacp_get_speaker_list((dacp_spkr_stuff *)&speaker_info, 50, &speaker_count);
if (http_response == 200) {
// get our machine number
uint16_t *hn = (uint16_t *)config.hw_addr;
uint32_t *ln = (uint32_t *)(config.hw_addr + 2);
uint16_t *hn = (uint16_t *)config.ap1_prefix;
uint32_t *ln = (uint32_t *)(config.ap1_prefix + 2);
uint64_t t1 = ntohs(*hn);
uint64_t t2 = ntohl(*ln);
int64_t machine_number = (t1 << 32) + t2; // this form is useful
Expand Down Expand Up @@ -1273,8 +1276,8 @@ int dacp_set_volume(int32_t vo) {
http_response = dacp_get_speaker_list((dacp_spkr_stuff *)&speaker_info, 50, &speaker_count);
if (http_response == 200) {
// get our machine number
uint16_t *hn = (uint16_t *)config.hw_addr;
uint32_t *ln = (uint32_t *)(config.hw_addr + 2);
uint16_t *hn = (uint16_t *)config.ap1_prefix;
uint32_t *ln = (uint32_t *)(config.ap1_prefix + 2);
uint64_t t1 = ntohs(*hn);
uint64_t t2 = ntohl(*ln);
int64_t machine_number = (t1 << 32) + t2; // this form is useful
Expand Down
Loading

0 comments on commit acdae45

Please sign in to comment.