From b4cc5b07433c16215f903a67ae9ca59e7114dc90 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Juho=20V=C3=A4h=C3=A4-Herttua?= Date: Sun, 13 May 2012 16:45:41 +0300 Subject: [PATCH] Add full metadata and coverart support to the library --- src/include/raop.h | 2 + src/lib/raop.c | 4 +- src/lib/raop_rtp.c | 111 ++++++++++++++++++++++++++++++--------------- src/test/example.c | 26 +++++++++++ 4 files changed, 105 insertions(+), 38 deletions(-) diff --git a/src/include/raop.h b/src/include/raop.h index e5158cb..aa1a47f 100644 --- a/src/include/raop.h +++ b/src/include/raop.h @@ -17,6 +17,8 @@ struct raop_callbacks_s { void* cls; void* (*audio_init)(void *cls, int bits, int channels, int samplerate); void (*audio_set_volume)(void *cls, void *session, float volume); + void (*audio_set_metadata)(void *cls, void *session, const void *buffer, int buflen); + void (*audio_set_coverart)(void *cls, void *session, const void *buffer, int buflen); void (*audio_process)(void *cls, void *session, const void *buffer, int buflen); void (*audio_flush)(void *cls, void *session); void (*audio_destroy)(void *cls, void *session); diff --git a/src/lib/raop.c b/src/lib/raop.c index a0289b7..0d2b11f 100644 --- a/src/lib/raop.c +++ b/src/lib/raop.c @@ -365,8 +365,8 @@ raop_init(raop_callbacks_t *callbacks, const char *pemkey) } /* Validate the callbacks structure */ - if (!callbacks->audio_init || !callbacks->audio_set_volume || - !callbacks->audio_process || !callbacks->audio_flush || + if (!callbacks->audio_init || + !callbacks->audio_process || !callbacks->audio_destroy) { return NULL; } diff --git a/src/lib/raop_rtp.c b/src/lib/raop_rtp.c index 1896e16..77814ba 100644 --- a/src/lib/raop_rtp.c +++ b/src/lib/raop_rtp.c @@ -245,6 +245,77 @@ raop_rtp_resend_callback(void *opaque, unsigned short seqnum, unsigned short cou return 0; } +static int +raop_rtp_process_events(raop_rtp_t *raop_rtp, void *cb_data, float *volume) +{ + int flush; + int volume_changed; + unsigned char *metadata; + int metadata_len; + unsigned char *coverart; + int coverart_len; + + assert(raop_rtp); + assert(volume); + + MUTEX_LOCK(raop_rtp->run_mutex); + if (!raop_rtp->running) { + MUTEX_UNLOCK(raop_rtp->run_mutex); + return 1; + } + + /* Read the volume level */ + volume_changed = (*volume != raop_rtp->volume); + *volume = raop_rtp->volume; + + /* Read the flush value */ + flush = raop_rtp->flush; + raop_rtp->flush = NO_FLUSH; + + /* Read the metadata */ + metadata = raop_rtp->metadata; + metadata_len = raop_rtp->metadata_len; + raop_rtp->metadata = NULL; + raop_rtp->metadata_len = 0; + + /* Read the coverart */ + coverart = raop_rtp->coverart; + coverart_len = raop_rtp->coverart_len; + raop_rtp->coverart = NULL; + raop_rtp->coverart_len = 0; + MUTEX_UNLOCK(raop_rtp->run_mutex); + + /* Call set_volume callback if changed */ + if (volume_changed) { + if (raop_rtp->callbacks.audio_set_volume) { + raop_rtp->callbacks.audio_set_volume(raop_rtp->callbacks.cls, cb_data, *volume); + } + } + + /* Handle flush if requested */ + if (flush != NO_FLUSH) { + raop_buffer_flush(raop_rtp->buffer, flush); + if (raop_rtp->callbacks.audio_flush) { + raop_rtp->callbacks.audio_flush(raop_rtp->callbacks.cls, cb_data); + } + } + if (metadata != NULL) { + if (raop_rtp->callbacks.audio_set_metadata) { + raop_rtp->callbacks.audio_set_metadata(raop_rtp->callbacks.cls, cb_data, metadata, metadata_len); + } + free(metadata); + metadata = NULL; + } + if (coverart != NULL) { + if (raop_rtp->callbacks.audio_set_coverart) { + raop_rtp->callbacks.audio_set_coverart(raop_rtp->callbacks.cls, cb_data, coverart, coverart_len); + } + free(coverart); + coverart = NULL; + } + return 0; +} + static THREAD_RETVAL raop_rtp_thread_udp(void *arg) { @@ -267,35 +338,14 @@ raop_rtp_thread_udp(void *arg) config->sampleRate); while(1) { - int volume_changed; - int flush; - fd_set rfds; struct timeval tv; int nfds, ret; - MUTEX_LOCK(raop_rtp->run_mutex); - if (!raop_rtp->running) { - MUTEX_UNLOCK(raop_rtp->run_mutex); + /* Check if we are still running and process callbacks */ + if (raop_rtp_process_events(raop_rtp, cb_data, &volume)) { break; } - /* Read the volume level */ - volume_changed = (volume != raop_rtp->volume); - volume = raop_rtp->volume; - - /* Read the flush value */ - flush = raop_rtp->flush; - raop_rtp->flush = NO_FLUSH; - MUTEX_UNLOCK(raop_rtp->run_mutex); - - /* Call set_volume callback if changed */ - if (volume_changed) { - raop_rtp->callbacks.audio_set_volume(raop_rtp->callbacks.cls, cb_data, volume); - } - if (flush != NO_FLUSH) { - raop_buffer_flush(raop_rtp->buffer, flush); - raop_rtp->callbacks.audio_flush(raop_rtp->callbacks.cls, cb_data); - } /* Set timeout value to 5ms */ tv.tv_sec = 0; @@ -396,25 +446,14 @@ raop_rtp_thread_tcp(void *arg) config->sampleRate); while (1) { - int volume_changed; - fd_set rfds; struct timeval tv; int nfds, ret; - MUTEX_LOCK(raop_rtp->run_mutex); - if (!raop_rtp->running) { - MUTEX_UNLOCK(raop_rtp->run_mutex); + /* Check if we are still running and process callbacks */ + if (raop_rtp_process_events(raop_rtp, cb_data, &volume)) { break; } - volume_changed = (volume != raop_rtp->volume); - volume = raop_rtp->volume; - MUTEX_UNLOCK(raop_rtp->run_mutex); - - /* Call set_volume callback if changed */ - if (volume_changed) { - raop_rtp->callbacks.audio_set_volume(raop_rtp->callbacks.cls, cb_data, volume); - } /* Set timeout value to 5ms */ tv.tv_sec = 0; diff --git a/src/test/example.c b/src/test/example.c index 960e125..c1ae7f0 100644 --- a/src/test/example.c +++ b/src/test/example.c @@ -21,6 +21,30 @@ audio_set_volume(void *cls, void *session, float volume) printf("Setting volume to %f\n", volume); } +static void +audio_set_metadata(void *cls, void *session, const void *buffer, int buflen) +{ + int orig = buflen; + FILE *file = fopen("metadata.bin", "wb"); + while (buflen > 0) { + buflen -= fwrite(buffer+orig-buflen, 1, buflen, file); + } + fclose(file); + printf("Metadata of length %d saved as metadata.bin\n", orig); +} + +static void +audio_set_coverart(void *cls, void *session, const void *buffer, int buflen) +{ + int orig = buflen; + FILE *file = fopen("coverart.jpg", "wb"); + while (buflen > 0) { + buflen -= fwrite(buffer+orig-buflen, 1, buflen, file); + } + fclose(file); + printf("Coverart of length %d saved as coverart.jpg\n", orig); +} + static void audio_process(void *cls, void *session, const void *buffer, int buflen) { @@ -56,6 +80,8 @@ main(int argc, char *argv[]) raop_cbs.cls = NULL; raop_cbs.audio_init = audio_init; raop_cbs.audio_set_volume = audio_set_volume; + raop_cbs.audio_set_metadata = audio_set_metadata; + raop_cbs.audio_set_coverart = audio_set_coverart; raop_cbs.audio_process = audio_process; raop_cbs.audio_flush = audio_flush; raop_cbs.audio_destroy = audio_destroy; -- 2.34.1