X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Flib%2Fraop_rtp.c;h=77814ba08680528e9a2d96b9ee9d42d40792d16a;hb=b4cc5b07433c16215f903a67ae9ca59e7114dc90;hp=3400c0c9169e65679b0ec573cb6899bf5573b2eb;hpb=46212791ac2f31ee382934c461c49495e0c66cc9;p=deb_shairplay.git diff --git a/src/lib/raop_rtp.c b/src/lib/raop_rtp.c index 3400c0c..77814ba 100644 --- a/src/lib/raop_rtp.c +++ b/src/lib/raop_rtp.c @@ -39,13 +39,21 @@ struct raop_rtp_s { struct sockaddr_storage remote_saddr; socklen_t remote_saddr_len; + /* MUTEX LOCKED VARIABLES START */ /* These variables only edited mutex locked */ int running; int joined; + float volume; + unsigned char *metadata; + int metadata_len; + unsigned char *coverart; + int coverart_len; + int flush; thread_handle_t thread; mutex_handle_t run_mutex; + /* MUTEX LOCKED VARIABLES END */ /* Remote control and timing ports */ unsigned short control_rport; @@ -94,6 +102,10 @@ raop_rtp_parse_remote(raop_rtp_t *raop_rtp, const char *remote) free(original); return -1; } + if (strstr(current, ":")) { + /* FIXME: iTunes sends IP4 even with an IPv6 address, does it mean something */ + family = AF_INET6; + } ret = netutils_parse_address(family, current, &raop_rtp->remote_saddr, sizeof(raop_rtp->remote_saddr)); @@ -149,6 +161,8 @@ raop_rtp_destroy(raop_rtp_t *raop_rtp) MUTEX_DESTROY(raop_rtp->run_mutex); raop_buffer_destroy(raop_rtp->buffer); + free(raop_rtp->metadata); + free(raop_rtp->coverart); free(raop_rtp); } } @@ -231,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) { @@ -253,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; @@ -382,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; @@ -556,6 +609,48 @@ raop_rtp_set_volume(raop_rtp_t *raop_rtp, float volume) MUTEX_UNLOCK(raop_rtp->run_mutex); } +void +raop_rtp_set_metadata(raop_rtp_t *raop_rtp, const char *data, int datalen) +{ + unsigned char *metadata; + + assert(raop_rtp); + + if (datalen <= 0) { + return; + } + metadata = malloc(datalen); + assert(metadata); + memcpy(metadata, data, datalen); + + /* Set metadata in thread instead */ + MUTEX_LOCK(raop_rtp->run_mutex); + raop_rtp->metadata = metadata; + raop_rtp->metadata_len = datalen; + MUTEX_UNLOCK(raop_rtp->run_mutex); +} + +void +raop_rtp_set_coverart(raop_rtp_t *raop_rtp, const char *data, int datalen) +{ + unsigned char *coverart; + + assert(raop_rtp); + + if (datalen <= 0) { + return; + } + coverart = malloc(datalen); + assert(coverart); + memcpy(coverart, data, datalen); + + /* Set coverart in thread instead */ + MUTEX_LOCK(raop_rtp->run_mutex); + raop_rtp->coverart = coverart; + raop_rtp->coverart_len = datalen; + MUTEX_UNLOCK(raop_rtp->run_mutex); +} + void raop_rtp_flush(raop_rtp_t *raop_rtp, int next_seq) {