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;
MUTEX_DESTROY(raop_rtp->run_mutex);
raop_buffer_destroy(raop_rtp->buffer);
+ free(raop_rtp->metadata);
+ free(raop_rtp->coverart);
free(raop_rtp);
}
}
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)
{
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;
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;
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)
{