Pass on rtpmap to raop_buffer in order to add AAC support later
[deb_shairplay.git] / src / lib / raop_rtp.c
index 1896e160b562c50e1b67081cb65c1950c86165fe..e80da78d0d1ee3bc86c2712c377e5e66420a23d7 100644 (file)
@@ -45,6 +45,7 @@ struct raop_rtp_s {
        int joined;
 
        float volume;
+       int volume_changed;
        unsigned char *metadata;
        int metadata_len;
        unsigned char *coverart;
@@ -120,13 +121,15 @@ raop_rtp_parse_remote(raop_rtp_t *raop_rtp, const char *remote)
 
 raop_rtp_t *
 raop_rtp_init(logger_t *logger, raop_callbacks_t *callbacks, const char *remote,
-              const char *fmtp, const unsigned char *aeskey, const unsigned char *aesiv)
+              const char *rtpmap, const char *fmtp,
+              const unsigned char *aeskey, const unsigned char *aesiv)
 {
        raop_rtp_t *raop_rtp;
 
        assert(logger);
        assert(callbacks);
        assert(remote);
+       assert(rtpmap);
        assert(fmtp);
 
        raop_rtp = calloc(1, sizeof(raop_rtp_t));
@@ -135,7 +138,7 @@ raop_rtp_init(logger_t *logger, raop_callbacks_t *callbacks, const char *remote,
        }
        raop_rtp->logger = logger;
        memcpy(&raop_rtp->callbacks, callbacks, sizeof(raop_callbacks_t));
-       raop_rtp->buffer = raop_buffer_init(fmtp, aeskey, aesiv);
+       raop_rtp->buffer = raop_buffer_init(rtpmap, fmtp, aeskey, aesiv);
        if (!raop_rtp->buffer) {
                free(raop_rtp);
                return NULL;
@@ -245,6 +248,78 @@ 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)
+{
+       int flush;
+       float volume;
+       int volume_changed;
+       unsigned char *metadata;
+       int metadata_len;
+       unsigned char *coverart;
+       int coverart_len;
+
+       assert(raop_rtp);
+
+       MUTEX_LOCK(raop_rtp->run_mutex);
+       if (!raop_rtp->running) {
+               MUTEX_UNLOCK(raop_rtp->run_mutex);
+               return 1;
+       }
+
+       /* Read the volume level */
+       volume = raop_rtp->volume;
+       volume_changed = raop_rtp->volume_changed;
+       raop_rtp->volume_changed = 0;
+
+       /* 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,7 +328,6 @@ raop_rtp_thread_udp(void *arg)
        unsigned int packetlen;
        struct sockaddr_storage saddr;
        socklen_t saddrlen;
-       float volume = 0.0;
 
        const ALACSpecificConfig *config;
        void *cb_data = NULL;
@@ -267,35 +341,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)) {
                        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,7 +435,6 @@ raop_rtp_thread_tcp(void *arg)
        int stream_fd = -1;
        unsigned char packet[RAOP_PACKET_LEN];
        unsigned int packetlen = 0;
-       float volume = 0.0;
 
        const ALACSpecificConfig *config;
        void *cb_data = NULL;
@@ -396,25 +448,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)) {
                        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;
@@ -567,6 +608,7 @@ raop_rtp_set_volume(raop_rtp_t *raop_rtp, float volume)
        /* Set volume in thread instead */
        MUTEX_LOCK(raop_rtp->run_mutex);
        raop_rtp->volume = volume;
+       raop_rtp->volume_changed = 1;
        MUTEX_UNLOCK(raop_rtp->run_mutex);
 }