From: Martin Blanchard <tinram@xxxxxx> --- src/modules/raop/base64.c | 28 ++++-- src/modules/raop/base64.h | 6 +- src/modules/raop/module-raop-discover.c | 169 ++++++++++++++++---------------- src/modules/raop/module-raop-sink.c | 56 +++++------ src/modules/raop/raop_client.c | 93 +++++++++--------- src/modules/raop/raop_client.h | 16 +-- 6 files changed, 190 insertions(+), 178 deletions(-) diff --git a/src/modules/raop/base64.c b/src/modules/raop/base64.c index 37e4762..91b76ae 100644 --- a/src/modules/raop/base64.c +++ b/src/modules/raop/base64.c @@ -19,10 +19,10 @@ USA. ***/ -/* +/*** This file was originally inspired by a file developed by - Kungliga Tekniska H?gskolan -*/ + Kungliga Tekniska H?gskolan. +***/ #ifdef HAVE_CONFIG_H #include <config.h> @@ -39,11 +39,17 @@ static const char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static int pos(char c) { - if (c >= 'A' && c <= 'Z') return c - 'A' + 0; - if (c >= 'a' && c <= 'z') return c - 'a' + 26; - if (c >= '0' && c <= '9') return c - '0' + 52; - if (c == '+') return 62; - if (c == '/') return 63; + if (c >= 'A' && c <= 'Z') + return c - 'A' + 0; + if (c >= 'a' && c <= 'z') + return c - 'a' + 26; + if (c >= '0' && c <= '9') + return c - '0' + 52; + if (c == '+') + return 62; + if (c == '/') + return 63; + return -1; } @@ -75,8 +81,10 @@ int pa_base64_encode(const void *data, int size, char **str) { p[2] = '='; p += 4; } + *p = 0; *str = s; + return strlen(s); } @@ -86,6 +94,7 @@ static unsigned int token_decode(const char *token) { int i; unsigned int val = 0; int marker = 0; + if (strlen(token) < 4) return DECODE_ERROR; for (i = 0; i < 4; i++) { @@ -101,8 +110,10 @@ static unsigned int token_decode(const char *token) { val += lpos; } } + if (marker > 2) return DECODE_ERROR; + return (marker << 24) | val; } @@ -122,5 +133,6 @@ int pa_base64_decode(const char *str, void *data) { if (marker < 1) *q++ = val & 0xff; } + return q - (unsigned char *) data; } diff --git a/src/modules/raop/base64.h b/src/modules/raop/base64.h index 7a973b6..05194a0 100644 --- a/src/modules/raop/base64.h +++ b/src/modules/raop/base64.h @@ -23,10 +23,10 @@ USA. ***/ -/* +/*** This file was originally inspired by a file developed by - Kungliga Tekniska H?gskolan -*/ + Kungliga Tekniska H?gskolan. +***/ int pa_base64_encode(const void *data, int size, char **str); int pa_base64_decode(const char *str, void *data); diff --git a/src/modules/raop/module-raop-discover.c b/src/modules/raop/module-raop-discover.c index c7efe9a..4137cf7 100644 --- a/src/modules/raop/module-raop-discover.c +++ b/src/modules/raop/module-raop-discover.c @@ -54,6 +54,17 @@ PA_MODULE_LOAD_ONCE(true); #define SERVICE_TYPE_SINK "_raop._tcp" +struct userdata { + pa_core *core; + pa_module *module; + + AvahiPoll *avahi_poll; + AvahiClient *client; + AvahiServiceBrowser *sink_browser; + + pa_hashmap *tunnels; +}; + static const char* const valid_modargs[] = { NULL }; @@ -65,16 +76,6 @@ struct tunnel { uint32_t module_index; }; -struct userdata { - pa_core *core; - pa_module *module; - AvahiPoll *avahi_poll; - AvahiClient *client; - AvahiServiceBrowser *sink_browser; - - pa_hashmap *tunnels; -}; - static unsigned tunnel_hash(const void *p) { const struct tunnel *t = p; @@ -104,11 +105,11 @@ static int tunnel_compare(const void *a, const void *b) { return 0; } -static struct tunnel *tunnel_new( +static struct tunnel* tunnel_new( AvahiIfIndex interface, AvahiProtocol protocol, const char *name, const char *type, const char *domain) { - struct tunnel *t; + t = pa_xnew(struct tunnel, 1); t->interface = interface; t->protocol = protocol; @@ -116,6 +117,7 @@ static struct tunnel *tunnel_new( t->type = pa_xstrdup(type); t->domain = pa_xstrdup(domain); t->module_index = PA_IDXSET_INVALID; + return t; } @@ -136,88 +138,87 @@ static void resolver_cb( AvahiStringList *txt, AvahiLookupResultFlags flags, void *userdata) { - struct userdata *u = userdata; struct tunnel *tnl; + char *device = NULL, *nicename, *dname, *vname, *args; + char at[AVAHI_ADDRESS_STR_MAX]; + AvahiStringList *l; + pa_module *m; pa_assert(u); tnl = tunnel_new(interface, protocol, name, type, domain); - if (event != AVAHI_RESOLVER_FOUND) + if (event != AVAHI_RESOLVER_FOUND) { pa_log("Resolving of '%s' failed: %s", name, avahi_strerror(avahi_client_errno(u->client))); - else { - char *device = NULL, *nicename, *dname, *vname, *args; - char at[AVAHI_ADDRESS_STR_MAX]; - AvahiStringList *l; - pa_module *m; - - if ((nicename = strstr(name, "@"))) { - ++nicename; - if (strlen(nicename) > 0) { - pa_log_debug("Found RAOP: %s", nicename); - nicename = pa_escape(nicename, "\"'"); - } else - nicename = NULL; - } + goto finish; + } - for (l = txt; l; l = l->next) { - char *key, *value; - pa_assert_se(avahi_string_list_get_pair(l, &key, &value, NULL) == 0); + if ((nicename = strstr(name, "@"))) { + ++nicename; + if (strlen(nicename) > 0) { + pa_log_debug("Found RAOP: %s", nicename); + nicename = pa_escape(nicename, "\"'"); + } else + nicename = NULL; + } - pa_log_debug("Found key: '%s' with value: '%s'", key, value); - if (pa_streq(key, "device")) { - pa_xfree(device); - device = value; - value = NULL; - } - avahi_free(key); - avahi_free(value); + for (l = txt; l; l = l->next) { + char *key, *value; + pa_assert_se(avahi_string_list_get_pair(l, &key, &value, NULL) == 0); + + pa_log_debug("Found key: '%s' with value: '%s'", key, value); + if (pa_streq(key, "device")) { + device = value; + value = NULL; } - if (device) - dname = pa_sprintf_malloc("raop.%s.%s", host_name, device); - else - dname = pa_sprintf_malloc("raop.%s", host_name); + avahi_free(key); + avahi_free(value); + } - if (!(vname = pa_namereg_make_valid_name(dname))) { - pa_log("Cannot construct valid device name from '%s'.", dname); - avahi_free(device); - pa_xfree(dname); - goto finish; - } + if (device) + dname = pa_sprintf_malloc("raop.%s.%s", host_name, device); + else + dname = pa_sprintf_malloc("raop.%s", host_name); + + if (!(vname = pa_namereg_make_valid_name(dname))) { + pa_log("Cannot construct valid device name from '%s'.", dname); + avahi_free(device); pa_xfree(dname); + goto finish; + } - if (nicename) { - args = pa_sprintf_malloc("server=[%s]:%u " - "sink_name=%s " - "sink_properties='device.description=\"%s\"'", - avahi_address_snprint(at, sizeof(at), a), port, - vname, - nicename); - pa_xfree(nicename); - } else { - args = pa_sprintf_malloc("server=[%s]:%u " - "sink_name=%s", - avahi_address_snprint(at, sizeof(at), a), port, - vname); - } + avahi_free(device); + pa_xfree(dname); + + if (nicename) { + args = pa_sprintf_malloc("server=[%s]:%u " + "sink_name=%s " + "sink_properties='device.description=\"%s\"'", + avahi_address_snprint(at, sizeof(at), a), port, + vname, + nicename); + pa_xfree(nicename); + } else { + args = pa_sprintf_malloc("server=[%s]:%u " + "sink_name=%s", + avahi_address_snprint(at, sizeof(at), a), port, + vname); + } - pa_log_debug("Loading module-raop-sink with arguments '%s'", args); + pa_log_debug("Loading module-raop-sink with arguments '%s'", args); - if ((m = pa_module_load(u->core, "module-raop-sink", args))) { - tnl->module_index = m->index; - pa_hashmap_put(u->tunnels, tnl, tnl); - tnl = NULL; - } - - pa_xfree(vname); - pa_xfree(args); - avahi_free(device); + if ((m = pa_module_load(u->core, "module-raop-sink", args))) { + tnl->module_index = m->index; + pa_hashmap_put(u->tunnels, tnl, tnl); + tnl = NULL; } -finish: + pa_xfree(vname); + pa_xfree(args); +finish: avahi_service_resolver_free(r); if (tnl) @@ -231,7 +232,6 @@ static void browser_cb( const char *name, const char *type, const char *domain, AvahiLookupResultFlags flags, void *userdata) { - struct userdata *u = userdata; struct tunnel *t; @@ -250,7 +250,7 @@ static void browser_cb( /* We ignore the returned resolver object here, since the we don't * need to attach any special data to it, and we can still destroy - * it from the callback */ + * it from the callback. */ } else if (event == AVAHI_BROWSER_REMOVE) { struct tunnel *t2; @@ -277,9 +277,7 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void *userda case AVAHI_CLIENT_S_REGISTERING: case AVAHI_CLIENT_S_RUNNING: case AVAHI_CLIENT_S_COLLISION: - if (!u->sink_browser) { - if (!(u->sink_browser = avahi_service_browser_new( c, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, @@ -301,16 +299,16 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void *userda pa_log_debug("Avahi daemon disconnected."); + /* Try to reconnect. */ if (!(u->client = avahi_client_new(u->avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, u, &error))) { pa_log("avahi_client_new() failed: %s", avahi_strerror(error)); pa_module_unload_request(u->module, true); } } - /* Fall through */ + /* Fall through. */ case AVAHI_CLIENT_CONNECTING: - if (u->sink_browser) { avahi_service_browser_free(u->sink_browser); u->sink_browser = NULL; @@ -318,12 +316,12 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void *userda break; - default: ; + default: + break; } } -int pa__init(pa_module*m) { - +int pa__init(pa_module *m) { struct userdata *u; pa_modargs *ma = NULL; int error; @@ -360,8 +358,9 @@ fail: return -1; } -void pa__done(pa_module*m) { - struct userdata*u; +void pa__done(pa_module *m) { + struct userdata *u; + pa_assert(m); if (!(u = m->userdata)) diff --git a/src/modules/raop/module-raop-sink.c b/src/modules/raop/module-raop-sink.c index 2d08645..96c6a82 100644 --- a/src/modules/raop/module-raop-sink.c +++ b/src/modules/raop/module-raop-sink.c @@ -126,10 +126,10 @@ enum { SINK_MESSAGE_RIP_SOCKET }; -/* Forward declaration */ +/* Forward declarations: */ static void sink_set_volume_cb(pa_sink *); -static void on_connection(int fd, void*userdata) { +static void on_connection(int fd, void *userdata) { int so_sndbuf = 0; socklen_t sl = sizeof(int); struct userdata *u = userdata; @@ -145,7 +145,7 @@ static void on_connection(int fd, void*userdata) { pa_sink_set_max_request(u->sink, PA_MAX((size_t) so_sndbuf, u->block_size)); } - /* Set the initial volume */ + /* Set the initial volume. */ sink_set_volume_cb(u->sink); pa_log_debug("Connection authenticated, handing fd to IO thread..."); @@ -176,7 +176,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse pa_smoother_pause(u->smoother, pa_rtclock_now()); - /* Issue a FLUSH if we are connected */ + /* Issue a FLUSH if we are connected. */ if (u->fd >= 0) { pa_raop_flush(u->raop); } @@ -189,7 +189,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse pa_smoother_resume(u->smoother, pa_rtclock_now(), true); /* The connection can be closed when idle, so check to - see if we need to reestablish it */ + * see if we need to reestablish it. */ if (u->fd < 0) pa_raop_connect(u->raop); else @@ -228,7 +228,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse /*pollfd->events = */pollfd->revents = 0; if (u->sink->thread_info.state == PA_SINK_SUSPENDED) { - /* Our stream has been suspended so we just flush it.... */ + /* Our stream has been suspended so we just flush it... */ pa_raop_flush(u->raop); } return 0; @@ -270,19 +270,19 @@ static void sink_set_volume_cb(pa_sink *s) { pa_assert(u); - /* If we're muted we don't need to do anything */ + /* If we're muted we don't need to do anything. */ if (s->muted) return; /* Calculate the max volume of all channels. - We'll use this as our (single) volume on the APEX device and emulate - any variation in channel volumes in software */ + * We'll use this as our (single) volume on the APEX device and emulate + * any variation in channel volumes in software. */ v = pa_cvolume_max(&s->real_volume); - /* Create a pa_cvolume version of our single value */ + /* Create a pa_cvolume version of our single value. */ pa_cvolume_set(&hw, s->sample_spec.channels, v); - /* Perform any software manipulation of the volume needed */ + /* Perform any software manipulation of the volume needed. */ pa_sw_cvolume_divide(&s->soft_volume, &s->real_volume, &hw); pa_log_debug("Requested volume: %s", pa_cvolume_snprint_verbose(t, sizeof(t), &s->real_volume, &s->channel_map, false)); @@ -291,7 +291,7 @@ static void sink_set_volume_cb(pa_sink *s) { pa_cvolume_snprint_verbose(t, sizeof(t), &s->soft_volume, &s->channel_map, true)); /* Any necessary software volume manipulation is done so set - our hw volume (or v as a single value) on the device */ + * our hw volume (or v as a single value) on the device. */ pa_raop_client_set_volume(u->raop, v); } @@ -335,7 +335,7 @@ static void thread_func(void *userdata) { struct pollfd *pollfd; pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); - /* Render some data and write it to the fifo */ + /* Render some data and write it to the fifo. */ if (/*PA_SINK_IS_OPENED(u->sink->thread_info.state) && */pollfd->revents) { pa_usec_t usec; int64_t n; @@ -366,29 +366,29 @@ static void thread_func(void *userdata) { if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) { size_t rl; - /* We render real data */ + /* We render real data. */ if (u->raw_memchunk.length <= 0) { if (u->raw_memchunk.memblock) pa_memblock_unref(u->raw_memchunk.memblock); pa_memchunk_reset(&u->raw_memchunk); - /* Grab unencoded data */ + /* Grab unencoded data. */ pa_sink_render(u->sink, u->block_size, &u->raw_memchunk); } pa_assert(u->raw_memchunk.length > 0); - /* Encode it */ + /* Encode it. */ rl = u->raw_memchunk.length; u->encoding_overhead += u->next_encoding_overhead; pa_raop_client_encode_sample(u->raop, &u->raw_memchunk, &u->encoded_memchunk); u->next_encoding_overhead = (u->encoded_memchunk.length - (rl - u->raw_memchunk.length)); u->encoding_ratio = u->encoded_memchunk.length / (rl - u->raw_memchunk.length); } else { - /* We render some silence into our memchunk */ + /* We render some silence into our memchunk. */ memcpy(&u->encoded_memchunk, &silence, sizeof(pa_memchunk)); pa_memblock_ref(silence.memblock); - /* Calculate/store some values to be used with the smoother */ + /* Calculate/store some values to be used with the smoother. */ u->next_encoding_overhead = silence_overhead; u->encoding_ratio = silence_ratio; } @@ -407,8 +407,7 @@ static void thread_func(void *userdata) { continue; else if (errno == EAGAIN) { - /* OK, we filled all socket buffers up - * now. */ + /* OK, we filled all socket buffers up now. */ goto filled_up; } else { @@ -425,22 +424,21 @@ static void thread_func(void *userdata) { pollfd->revents = 0; if (u->encoded_memchunk.length > 0) { - /* we've completely written the encoded data, so update our overhead */ + /* We've completely written the encoded data, so update our overhead. */ u->encoding_overhead += u->next_encoding_overhead; /* OK, we wrote less that we asked for, * hence we can assume that the socket - * buffers are full now */ + * buffers are full now. */ goto filled_up; } } } filled_up: - /* At this spot we know that the socket buffers are * fully filled up. This is the best time to estimate - * the playback position of the server */ + * the playback position of the server. */ n = u->offset - u->encoding_overhead; @@ -462,7 +460,7 @@ static void thread_func(void *userdata) { pa_smoother_put(u->smoother, pa_rtclock_now(), usec); } - /* Hmm, nothing to do. Let's sleep */ + /* Hmm, nothing to do. Let's sleep... */ pollfd->events = POLLOUT; /*PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0;*/ } @@ -484,7 +482,7 @@ static void thread_func(void *userdata) { } /* We expect this to happen on occasion if we are not sending data. - It's perfectly natural and normal and natural */ + * It's perfectly natural and normal and natural. */ if (u->rtpoll_item) pa_rtpoll_item_free(u->rtpoll_item); u->rtpoll_item = NULL; @@ -494,7 +492,7 @@ static void thread_func(void *userdata) { fail: /* If this was no regular exit from the loop we have to continue - * processing messages until we received PA_MESSAGE_SHUTDOWN */ + * processing messages until we received PA_MESSAGE_SHUTDOWN. */ pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core), PA_CORE_MESSAGE_UNLOAD_MODULE, u->module, 0, NULL, NULL); pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN); @@ -504,7 +502,7 @@ finish: pa_log_debug("Thread shutting down"); } -int pa__init(pa_module*m) { +int pa__init(pa_module *m) { struct userdata *u = NULL; pa_sample_spec ss; pa_modargs *ma = NULL; @@ -640,7 +638,7 @@ int pa__get_n_used(pa_module *m) { return pa_sink_linked_by(u->sink); } -void pa__done(pa_module*m) { +void pa__done(pa_module *m) { struct userdata *u; pa_assert(m); diff --git a/src/modules/raop/raop_client.c b/src/modules/raop/raop_client.c index 98a9822..45bdfd9 100644 --- a/src/modules/raop/raop_client.c +++ b/src/modules/raop/raop_client.c @@ -82,9 +82,9 @@ struct pa_raop_client { /* Encryption Related bits */ AES_KEY aes; - uint8_t aes_iv[AES_CHUNKSIZE]; /* initialization vector for aes-cbc */ - uint8_t aes_nv[AES_CHUNKSIZE]; /* next vector for aes-cbc */ - uint8_t aes_key[AES_CHUNKSIZE]; /* key for aes-cbc */ + uint8_t aes_iv[AES_CHUNKSIZE]; /* Initialization vector for aes-cbc */ + uint8_t aes_nv[AES_CHUNKSIZE]; /* Next vector for aes-cbc */ + uint8_t aes_key[AES_CHUNKSIZE]; /* Key for aes-cbc */ pa_socket_client *sc; int fd; @@ -93,9 +93,9 @@ struct pa_raop_client { uint32_t rtptime; pa_raop_client_cb_t callback; - void* userdata; + void *userdata; pa_raop_client_closed_cb_t closed_callback; - void* closed_userdata; + void *closed_userdata; }; /** @@ -117,32 +117,32 @@ static inline void bit_writer(uint8_t **buffer, uint8_t *bit_pos, int *size, uin if (!*bit_pos) *size += 1; - /* Calc the number of bits left in the current byte of buffer */ + /* Calc the number of bits left in the current byte of buffer. */ bits_left = 7 - *bit_pos + 1; /* Calc the overflow of bits in relation to how much space we have left... */ bit_overflow = bits_left - data_bit_len; if (bit_overflow >= 0) { - /* We can fit the new data in our current byte */ - /* As we write from MSB->LSB we need to left shift by the overflow amount */ + /* We can fit the new data in our current byte. + * As we write from MSB->LSB we need to left shift by the overflow amount. */ bit_data = data << bit_overflow; if (*bit_pos) **buffer |= bit_data; else **buffer = bit_data; - /* If our data fits exactly into the current byte, we need to increment our pointer */ + /* If our data fits exactly into the current byte, we need to increment our pointer. */ if (0 == bit_overflow) { - /* Do not increment size as it will be incremented on next call as bit_pos is zero */ + /* Do not increment size as it will be incremented on next call as bit_pos is zero. */ *buffer += 1; *bit_pos = 0; } else { *bit_pos += data_bit_len; } } else { - /* bit_overflow is negative, there for we will need a new byte from our buffer */ - /* Firstly fill up what's left in the current byte */ + /* bit_overflow is negative, there for we will need a new byte from our buffer + * Firstly fill up what's left in the current byte. */ bit_data = data >> -bit_overflow; **buffer |= bit_data; - /* Increment our buffer pointer and size counter*/ + /* Increment our buffer pointer and size counter. */ *buffer += 1; *size += 1; **buffer = data << (8 + bit_overflow); @@ -175,7 +175,7 @@ static int rsa_encrypt(uint8_t *text, int len, uint8_t *res) { return size; } -static int aes_encrypt(pa_raop_client* c, uint8_t *data, int size) { +static int aes_encrypt(pa_raop_client *c, uint8_t *data, int size) { uint8_t *buf; int i=0, j; @@ -230,8 +230,8 @@ static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata c->callback(c->fd, c->userdata); } -static void rtsp_cb(pa_rtsp_client *rtsp, pa_rtsp_state state, pa_headerlist* headers, void *userdata) { - pa_raop_client* c = userdata; +static void rtsp_cb(pa_rtsp_client *rtsp, pa_rtsp_state state, pa_headerlist *headers, void *userdata) { + pa_raop_client *c = userdata; pa_assert(c); pa_assert(rtsp); pa_assert(rtsp == c->rtsp); @@ -247,12 +247,12 @@ static void rtsp_cb(pa_rtsp_client *rtsp, pa_rtsp_state state, pa_headerlist* he pa_log_debug("RAOP: CONNECTED"); ip = pa_rtsp_localip(c->rtsp); - /* First of all set the url properly */ + /* First of all set the url properly. */ url = pa_sprintf_malloc("rtsp://%s/%s", ip, c->sid); pa_rtsp_set_url(c->rtsp, url); pa_xfree(url); - /* Now encrypt our aes_public key to send to the device */ + /* Now encrypt our aes_public key to send to the device. */ i = rsa_encrypt(c->aes_key, AES_CHUNKSIZE, rsakey); pa_base64_encode(rsakey, i, &key); rtrimchar(key, '='); @@ -351,7 +351,7 @@ static void rtsp_cb(pa_rtsp_client *rtsp, pa_rtsp_state state, pa_headerlist* he pa_rtsp_client_free(c->rtsp); c->rtsp = NULL; if (c->fd > 0) { - /* We do not close the fd, we leave it to the closed callback to do that */ + /* We do not close the fd, we leave it to the closed callback to do that. */ c->fd = -1; } if (c->sc) { @@ -365,9 +365,9 @@ static void rtsp_cb(pa_rtsp_client *rtsp, pa_rtsp_state state, pa_headerlist* he } } -pa_raop_client* pa_raop_client_new(pa_core *core, const char* host) { +pa_raop_client* pa_raop_client_new(pa_core *core, const char *host) { pa_parsed_address a; - pa_raop_client* c = pa_xnew0(pa_raop_client, 1); + pa_raop_client *c = pa_xnew0(pa_raop_client, 1); pa_assert(core); pa_assert(host); @@ -388,10 +388,11 @@ pa_raop_client* pa_raop_client_new(pa_core *core, const char* host) { pa_raop_client_free(c); return NULL; } + return c; } -void pa_raop_client_free(pa_raop_client* c) { +void pa_raop_client_free(pa_raop_client *c) { pa_assert(c); if (c->rtsp) @@ -402,7 +403,7 @@ void pa_raop_client_free(pa_raop_client* c) { pa_xfree(c); } -int pa_raop_connect(pa_raop_client* c) { +int pa_raop_connect(pa_raop_client *c) { char *sci; struct { uint32_t a; @@ -419,30 +420,31 @@ int pa_raop_connect(pa_raop_client* c) { c->rtsp = pa_rtsp_client_new(c->core->mainloop, c->host, c->port, "iTunes/4.6 (Macintosh; U; PPC Mac OS X 10.3)"); - /* Initialise the AES encryption system */ + /* Initialise the AES encryption system. */ pa_random(c->aes_iv, sizeof(c->aes_iv)); pa_random(c->aes_key, sizeof(c->aes_key)); memcpy(c->aes_nv, c->aes_iv, sizeof(c->aes_nv)); AES_set_encrypt_key(c->aes_key, 128, &c->aes); - /* Generate random instance id */ + /* Generate random instance id. */ pa_random(&rand_data, sizeof(rand_data)); c->sid = pa_sprintf_malloc("%u", rand_data.a); sci = pa_sprintf_malloc("%08x%08x",rand_data.b, rand_data.c); pa_rtsp_add_header(c->rtsp, "Client-Instance", sci); pa_xfree(sci); pa_rtsp_set_callback(c->rtsp, rtsp_cb, c); + return pa_rtsp_connect(c->rtsp); } -int pa_raop_flush(pa_raop_client* c) { +int pa_raop_flush(pa_raop_client *c) { pa_assert(c); pa_rtsp_flush(c->rtsp, c->seq, c->rtptime); return 0; } -int pa_raop_client_set_volume(pa_raop_client* c, pa_volume_t volume) { +int pa_raop_client_set_volume(pa_raop_client *c, pa_volume_t volume) { int rv; double db; char *param; @@ -457,13 +459,14 @@ int pa_raop_client_set_volume(pa_raop_client* c, pa_volume_t volume) { param = pa_sprintf_malloc("volume: %0.6f\r\n", db); - /* We just hit and hope, cannot wait for the callback */ + /* We just hit and hope, cannot wait for the callback. */ rv = pa_rtsp_setparameter(c->rtsp, param); pa_xfree(param); + return rv; } -int pa_raop_client_encode_sample(pa_raop_client* c, pa_memchunk* raw, pa_memchunk* encoded) { +int pa_raop_client_encode_sample(pa_raop_client *c, pa_memchunk *raw, pa_memchunk *encoded) { uint16_t len; size_t bufmax; uint8_t *bp, bpos; @@ -491,25 +494,25 @@ int pa_raop_client_encode_sample(pa_raop_client* c, pa_memchunk* raw, pa_memchun bsize = (int)(raw->length / 4); length = bsize * 4; - /* Leave 16 bytes extra to allow for the ALAC header which is about 55 bits */ + /* Leave 16 bytes extra to allow for the ALAC header which is about 55 bits. */ bufmax = length + header_size + 16; pa_memchunk_reset(encoded); encoded->memblock = pa_memblock_new(c->core->mempool, bufmax); b = pa_memblock_acquire(encoded->memblock); memcpy(b, header, header_size); - /* Now write the actual samples */ + /* Now write the actual samples. */ bp = b + header_size; size = bpos = 0; bit_writer(&bp,&bpos,&size,1,3); /* channel=1, stereo */ - bit_writer(&bp,&bpos,&size,0,4); /* unknown */ - bit_writer(&bp,&bpos,&size,0,8); /* unknown */ - bit_writer(&bp,&bpos,&size,0,4); /* unknown */ - bit_writer(&bp,&bpos,&size,1,1); /* hassize */ - bit_writer(&bp,&bpos,&size,0,2); /* unused */ - bit_writer(&bp,&bpos,&size,1,1); /* is-not-compressed */ - - /* size of data, integer, big endian */ + bit_writer(&bp,&bpos,&size,0,4); /* Unknown */ + bit_writer(&bp,&bpos,&size,0,8); /* Unknown */ + bit_writer(&bp,&bpos,&size,0,4); /* Unknown */ + bit_writer(&bp,&bpos,&size,1,1); /* Hassize */ + bit_writer(&bp,&bpos,&size,0,2); /* Unused */ + bit_writer(&bp,&bpos,&size,1,1); /* Is-not-compressed */ + + /* Size of data, integer, big endian. */ bit_writer(&bp,&bpos,&size,(bsize>>24)&0xff,8); bit_writer(&bp,&bpos,&size,(bsize>>16)&0xff,8); bit_writer(&bp,&bpos,&size,(bsize>>8)&0xff,8); @@ -518,7 +521,7 @@ int pa_raop_client_encode_sample(pa_raop_client* c, pa_memchunk* raw, pa_memchun ibp = p = pa_memblock_acquire(raw->memblock); maxibp = p + raw->length - 4; while (ibp <= maxibp) { - /* Byte swap stereo data */ + /* Byte swap stereo data. */ bit_writer(&bp,&bpos,&size,*(ibp+1),8); bit_writer(&bp,&bpos,&size,*(ibp+0),8); bit_writer(&bp,&bpos,&size,*(ibp+3),8); @@ -530,28 +533,28 @@ int pa_raop_client_encode_sample(pa_raop_client* c, pa_memchunk* raw, pa_memchun pa_memblock_release(raw->memblock); encoded->length = header_size + size; - /* store the length (endian swapped: make this better) */ + /* Store the length (endian swapped: make this better). */ len = size + header_size - 4; *(b + 2) = len >> 8; *(b + 3) = len & 0xff; - /* encrypt our data */ + /* Encrypt our data. */ aes_encrypt(c, (b + header_size), size); - /* We're done with the chunk */ + /* We're done with the chunk. */ pa_memblock_release(encoded->memblock); return 0; } -void pa_raop_client_set_callback(pa_raop_client* c, pa_raop_client_cb_t callback, void *userdata) { +void pa_raop_client_set_callback(pa_raop_client *c, pa_raop_client_cb_t callback, void *userdata) { pa_assert(c); c->callback = callback; c->userdata = userdata; } -void pa_raop_client_set_closed_callback(pa_raop_client* c, pa_raop_client_closed_cb_t callback, void *userdata) { +void pa_raop_client_set_closed_callback(pa_raop_client *c, pa_raop_client_closed_cb_t callback, void *userdata) { pa_assert(c); c->closed_callback = callback; diff --git a/src/modules/raop/raop_client.h b/src/modules/raop/raop_client.h index ce81f39..e44b1d7 100644 --- a/src/modules/raop/raop_client.h +++ b/src/modules/raop/raop_client.h @@ -26,19 +26,19 @@ typedef struct pa_raop_client pa_raop_client; -pa_raop_client* pa_raop_client_new(pa_core *core, const char* host); -void pa_raop_client_free(pa_raop_client* c); +pa_raop_client* pa_raop_client_new(pa_core *core, const char *host); +void pa_raop_client_free(pa_raop_client *c); -int pa_raop_connect(pa_raop_client* c); -int pa_raop_flush(pa_raop_client* c); +int pa_raop_connect(pa_raop_client *c); +int pa_raop_flush(pa_raop_client *c); -int pa_raop_client_set_volume(pa_raop_client* c, pa_volume_t volume); -int pa_raop_client_encode_sample(pa_raop_client* c, pa_memchunk* raw, pa_memchunk* encoded); +int pa_raop_client_set_volume(pa_raop_client *c, pa_volume_t volume); +int pa_raop_client_encode_sample(pa_raop_client *c, pa_memchunk *raw, pa_memchunk *encoded); typedef void (*pa_raop_client_cb_t)(int fd, void *userdata); -void pa_raop_client_set_callback(pa_raop_client* c, pa_raop_client_cb_t callback, void *userdata); +void pa_raop_client_set_callback(pa_raop_client *c, pa_raop_client_cb_t callback, void *userdata); typedef void (*pa_raop_client_closed_cb_t)(void *userdata); -void pa_raop_client_set_closed_callback(pa_raop_client* c, pa_raop_client_closed_cb_t callback, void *userdata); +void pa_raop_client_set_closed_callback(pa_raop_client *c, pa_raop_client_closed_cb_t callback, void *userdata); #endif -- 1.8.1.2