raop: Cosmetic fixes / Match coding style

Reviewed-by: Anton Lundin <glance@acc.umu.se>
This commit is contained in:
Martin Blanchard 2016-01-31 22:16:00 -06:00 committed by Tanu Kaskinen
parent d623c689e6
commit 6665acac56
8 changed files with 252 additions and 222 deletions

View file

@ -17,10 +17,10 @@
along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
***/ ***/
/* /***
This file was originally inspired by a file developed by This file was originally inspired by a file developed by
Kungliga Tekniska högskolan Kungliga Tekniska högskolan
*/ ***/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include <config.h> #include <config.h>
@ -37,11 +37,17 @@ static const char base64_chars[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static int pos(char c) { static int pos(char c) {
if (c >= 'A' && c <= 'Z') return c - 'A' + 0; if (c >= 'A' && c <= 'Z')
if (c >= 'a' && c <= 'z') return c - 'a' + 26; return c - 'A' + 0;
if (c >= '0' && c <= '9') return c - '0' + 52; if (c >= 'a' && c <= 'z')
if (c == '+') return 62; return c - 'a' + 26;
if (c == '/') return 63; if (c >= '0' && c <= '9')
return c - '0' + 52;
if (c == '+')
return 62;
if (c == '/')
return 63;
return -1; return -1;
} }
@ -73,8 +79,10 @@ int pa_base64_encode(const void *data, int size, char **str) {
p[2] = '='; p[2] = '=';
p += 4; p += 4;
} }
*p = 0; *p = 0;
*str = s; *str = s;
return strlen(s); return strlen(s);
} }
@ -84,6 +92,7 @@ static unsigned int token_decode(const char *token) {
int i; int i;
unsigned int val = 0; unsigned int val = 0;
int marker = 0; int marker = 0;
if (strlen(token) < 4) if (strlen(token) < 4)
return DECODE_ERROR; return DECODE_ERROR;
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
@ -99,8 +108,10 @@ static unsigned int token_decode(const char *token) {
val += lpos; val += lpos;
} }
} }
if (marker > 2) if (marker > 2)
return DECODE_ERROR; return DECODE_ERROR;
return (marker << 24) | val; return (marker << 24) | val;
} }
@ -120,5 +131,6 @@ int pa_base64_decode(const char *str, void *data) {
if (marker < 1) if (marker < 1)
*q++ = val & 0xff; *q++ = val & 0xff;
} }
return q - (unsigned char *) data; return q - (unsigned char *) data;
} }

View file

@ -21,10 +21,10 @@
along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
***/ ***/
/* /***
This file was originally inspired by a file developed by 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_encode(const void *data, int size, char **str);
int pa_base64_decode(const char *str, void *data); int pa_base64_decode(const char *str, void *data);

View file

@ -52,6 +52,17 @@ PA_MODULE_LOAD_ONCE(true);
#define SERVICE_TYPE_SINK "_raop._tcp" #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[] = { static const char* const valid_modargs[] = {
NULL NULL
}; };
@ -63,16 +74,6 @@ struct tunnel {
uint32_t module_index; 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) { static unsigned tunnel_hash(const void *p) {
const struct tunnel *t = p; const struct tunnel *t = p;
@ -102,11 +103,11 @@ static int tunnel_compare(const void *a, const void *b) {
return 0; return 0;
} }
static struct tunnel *tunnel_new( static struct tunnel* tunnel_new(
AvahiIfIndex interface, AvahiProtocol protocol, AvahiIfIndex interface, AvahiProtocol protocol,
const char *name, const char *type, const char *domain) { const char *name, const char *type, const char *domain) {
struct tunnel *t; struct tunnel *t;
t = pa_xnew(struct tunnel, 1); t = pa_xnew(struct tunnel, 1);
t->interface = interface; t->interface = interface;
t->protocol = protocol; t->protocol = protocol;
@ -114,6 +115,7 @@ static struct tunnel *tunnel_new(
t->type = pa_xstrdup(type); t->type = pa_xstrdup(type);
t->domain = pa_xstrdup(domain); t->domain = pa_xstrdup(domain);
t->module_index = PA_IDXSET_INVALID; t->module_index = PA_IDXSET_INVALID;
return t; return t;
} }
@ -134,88 +136,87 @@ static void resolver_cb(
AvahiStringList *txt, AvahiStringList *txt,
AvahiLookupResultFlags flags, AvahiLookupResultFlags flags,
void *userdata) { void *userdata) {
struct userdata *u = userdata; struct userdata *u = userdata;
struct tunnel *tnl; struct tunnel *tnl;
char *device = NULL, *nicename, *dname, *vname, *args;
char at[AVAHI_ADDRESS_STR_MAX];
AvahiStringList *l;
pa_module *m;
pa_assert(u); pa_assert(u);
tnl = tunnel_new(interface, protocol, name, type, domain); 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))); pa_log("Resolving of '%s' failed: %s", name, avahi_strerror(avahi_client_errno(u->client)));
else { goto finish;
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;
}
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")) {
pa_xfree(device);
device = value;
value = NULL;
}
avahi_free(key);
avahi_free(value);
}
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;
}
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);
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);
} }
finish: if ((nicename = strstr(name, "@"))) {
++nicename;
if (strlen(nicename) > 0) {
pa_log_debug("Found RAOP: %s", nicename);
nicename = pa_escape(nicename, "\"'");
} else
nicename = NULL;
}
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;
}
avahi_free(key);
avahi_free(value);
}
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;
}
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);
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);
finish:
avahi_service_resolver_free(r); avahi_service_resolver_free(r);
if (tnl) if (tnl)
@ -229,7 +230,6 @@ static void browser_cb(
const char *name, const char *type, const char *domain, const char *name, const char *type, const char *domain,
AvahiLookupResultFlags flags, AvahiLookupResultFlags flags,
void *userdata) { void *userdata) {
struct userdata *u = userdata; struct userdata *u = userdata;
struct tunnel *t; struct tunnel *t;
@ -248,7 +248,7 @@ static void browser_cb(
/* We ignore the returned resolver object here, since the we don't /* 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 * 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) { } else if (event == AVAHI_BROWSER_REMOVE) {
struct tunnel *t2; struct tunnel *t2;
@ -275,9 +275,7 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void *userda
case AVAHI_CLIENT_S_REGISTERING: case AVAHI_CLIENT_S_REGISTERING:
case AVAHI_CLIENT_S_RUNNING: case AVAHI_CLIENT_S_RUNNING:
case AVAHI_CLIENT_S_COLLISION: case AVAHI_CLIENT_S_COLLISION:
if (!u->sink_browser) { if (!u->sink_browser) {
if (!(u->sink_browser = avahi_service_browser_new( if (!(u->sink_browser = avahi_service_browser_new(
c, c,
AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
@ -299,16 +297,16 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void *userda
pa_log_debug("Avahi daemon disconnected."); 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))) { 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_log("avahi_client_new() failed: %s", avahi_strerror(error));
pa_module_unload_request(u->module, true); pa_module_unload_request(u->module, true);
} }
} }
/* Fall through */ /* Fall through. */
case AVAHI_CLIENT_CONNECTING: case AVAHI_CLIENT_CONNECTING:
if (u->sink_browser) { if (u->sink_browser) {
avahi_service_browser_free(u->sink_browser); avahi_service_browser_free(u->sink_browser);
u->sink_browser = NULL; u->sink_browser = NULL;
@ -316,12 +314,12 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void *userda
break; break;
default: ; default:
break;
} }
} }
int pa__init(pa_module*m) { int pa__init(pa_module *m) {
struct userdata *u; struct userdata *u;
pa_modargs *ma = NULL; pa_modargs *ma = NULL;
int error; int error;
@ -358,8 +356,9 @@ fail:
return -1; return -1;
} }
void pa__done(pa_module*m) { void pa__done(pa_module *m) {
struct userdata*u; struct userdata *u;
pa_assert(m); pa_assert(m);
if (!(u = m->userdata)) if (!(u = m->userdata))

View file

@ -124,10 +124,10 @@ enum {
SINK_MESSAGE_RIP_SOCKET SINK_MESSAGE_RIP_SOCKET
}; };
/* Forward declaration */ /* Forward declarations: */
static void sink_set_volume_cb(pa_sink *); 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; int so_sndbuf = 0;
socklen_t sl = sizeof(int); socklen_t sl = sizeof(int);
struct userdata *u = userdata; struct userdata *u = userdata;
@ -143,7 +143,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)); 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); sink_set_volume_cb(u->sink);
pa_log_debug("Connection authenticated, handing fd to IO thread..."); pa_log_debug("Connection authenticated, handing fd to IO thread...");
@ -174,7 +174,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
pa_smoother_pause(u->smoother, pa_rtclock_now()); 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) { if (u->fd >= 0) {
pa_raop_flush(u->raop); pa_raop_flush(u->raop);
} }
@ -187,7 +187,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); pa_smoother_resume(u->smoother, pa_rtclock_now(), true);
/* The connection can be closed when idle, so check to /* 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) if (u->fd < 0)
pa_raop_connect(u->raop); pa_raop_connect(u->raop);
else else
@ -226,7 +226,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
/*pollfd->events = */pollfd->revents = 0; /*pollfd->events = */pollfd->revents = 0;
if (u->sink->thread_info.state == PA_SINK_SUSPENDED) { 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); pa_raop_flush(u->raop);
} }
return 0; return 0;
@ -268,19 +268,19 @@ static void sink_set_volume_cb(pa_sink *s) {
pa_assert(u); 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) if (s->muted)
return; return;
/* Calculate the max volume of all channels. /* Calculate the max volume of all channels.
We'll use this as our (single) volume on the APEX device and emulate * We'll use this as our (single) volume on the APEX device and emulate
any variation in channel volumes in software */ * any variation in channel volumes in software. */
v = pa_cvolume_max(&s->real_volume); 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); 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_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)); pa_log_debug("Requested volume: %s", pa_cvolume_snprint_verbose(t, sizeof(t), &s->real_volume, &s->channel_map, false));
@ -289,7 +289,7 @@ static void sink_set_volume_cb(pa_sink *s) {
pa_cvolume_snprint_verbose(t, sizeof(t), &s->soft_volume, &s->channel_map, true)); pa_cvolume_snprint_verbose(t, sizeof(t), &s->soft_volume, &s->channel_map, true));
/* Any necessary software volume manipulation is done so set /* 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); pa_raop_client_set_volume(u->raop, v);
} }
@ -333,7 +333,7 @@ static void thread_func(void *userdata) {
struct pollfd *pollfd; struct pollfd *pollfd;
pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); 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) { if (/*PA_SINK_IS_OPENED(u->sink->thread_info.state) && */pollfd->revents) {
pa_usec_t usec; pa_usec_t usec;
int64_t n; int64_t n;
@ -364,29 +364,29 @@ static void thread_func(void *userdata) {
if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) { if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {
size_t rl; size_t rl;
/* We render real data */ /* We render real data. */
if (u->raw_memchunk.length <= 0) { if (u->raw_memchunk.length <= 0) {
if (u->raw_memchunk.memblock) if (u->raw_memchunk.memblock)
pa_memblock_unref(u->raw_memchunk.memblock); pa_memblock_unref(u->raw_memchunk.memblock);
pa_memchunk_reset(&u->raw_memchunk); pa_memchunk_reset(&u->raw_memchunk);
/* Grab unencoded data */ /* Grab unencoded data. */
pa_sink_render(u->sink, u->block_size, &u->raw_memchunk); pa_sink_render(u->sink, u->block_size, &u->raw_memchunk);
} }
pa_assert(u->raw_memchunk.length > 0); pa_assert(u->raw_memchunk.length > 0);
/* Encode it */ /* Encode it. */
rl = u->raw_memchunk.length; rl = u->raw_memchunk.length;
u->encoding_overhead += u->next_encoding_overhead; u->encoding_overhead += u->next_encoding_overhead;
pa_raop_client_encode_sample(u->raop, &u->raw_memchunk, &u->encoded_memchunk); 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->next_encoding_overhead = (u->encoded_memchunk.length - (rl - u->raw_memchunk.length));
u->encoding_ratio = u->encoded_memchunk.length / (rl - u->raw_memchunk.length); u->encoding_ratio = u->encoded_memchunk.length / (rl - u->raw_memchunk.length);
} else { } else {
/* We render some silence into our memchunk */ /* We render some silence into our memchunk. */
memcpy(&u->encoded_memchunk, &silence, sizeof(pa_memchunk)); memcpy(&u->encoded_memchunk, &silence, sizeof(pa_memchunk));
pa_memblock_ref(silence.memblock); 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->next_encoding_overhead = silence_overhead;
u->encoding_ratio = silence_ratio; u->encoding_ratio = silence_ratio;
} }
@ -405,8 +405,7 @@ static void thread_func(void *userdata) {
continue; continue;
else if (errno == EAGAIN) { else if (errno == EAGAIN) {
/* OK, we filled all socket buffers up /* OK, we filled all socket buffers up now. */
* now. */
goto filled_up; goto filled_up;
} else { } else {
@ -423,22 +422,21 @@ static void thread_func(void *userdata) {
pollfd->revents = 0; pollfd->revents = 0;
if (u->encoded_memchunk.length > 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; u->encoding_overhead += u->next_encoding_overhead;
/* OK, we wrote less that we asked for, /* OK, we wrote less that we asked for,
* hence we can assume that the socket * hence we can assume that the socket
* buffers are full now */ * buffers are full now. */
goto filled_up; goto filled_up;
} }
} }
} }
filled_up: filled_up:
/* At this spot we know that the socket buffers are /* At this spot we know that the socket buffers are
* fully filled up. This is the best time to estimate * 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; n = u->offset - u->encoding_overhead;
@ -460,7 +458,7 @@ static void thread_func(void *userdata) {
pa_smoother_put(u->smoother, pa_rtclock_now(), usec); 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;*/ pollfd->events = POLLOUT; /*PA_SINK_IS_OPENED(u->sink->thread_info.state) ? POLLOUT : 0;*/
} }
@ -482,7 +480,7 @@ static void thread_func(void *userdata) {
} }
/* We expect this to happen on occasion if we are not sending data. /* 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) if (u->rtpoll_item)
pa_rtpoll_item_free(u->rtpoll_item); pa_rtpoll_item_free(u->rtpoll_item);
u->rtpoll_item = NULL; u->rtpoll_item = NULL;
@ -492,7 +490,7 @@ static void thread_func(void *userdata) {
fail: fail:
/* If this was no regular exit from the loop we have to continue /* 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_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); pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);
@ -502,7 +500,7 @@ finish:
pa_log_debug("Thread shutting down"); pa_log_debug("Thread shutting down");
} }
int pa__init(pa_module*m) { int pa__init(pa_module *m) {
struct userdata *u = NULL; struct userdata *u = NULL;
pa_sample_spec ss; pa_sample_spec ss;
pa_modargs *ma = NULL; pa_modargs *ma = NULL;
@ -645,7 +643,7 @@ int pa__get_n_used(pa_module *m) {
return pa_sink_linked_by(u->sink); return pa_sink_linked_by(u->sink);
} }
void pa__done(pa_module*m) { void pa__done(pa_module *m) {
struct userdata *u; struct userdata *u;
pa_assert(m); pa_assert(m);

View file

@ -95,9 +95,9 @@ struct pa_raop_client {
/* Encryption Related bits */ /* Encryption Related bits */
AES_KEY aes; AES_KEY aes;
uint8_t aes_iv[AES_CHUNKSIZE]; /* initialization vector 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_nv[AES_CHUNKSIZE]; /* Next vector for aes-cbc */
uint8_t aes_key[AES_CHUNKSIZE]; /* key for aes-cbc */ uint8_t aes_key[AES_CHUNKSIZE]; /* Key for aes-cbc */
pa_socket_client *sc; pa_socket_client *sc;
int fd; int fd;
@ -106,9 +106,9 @@ struct pa_raop_client {
uint32_t rtptime; uint32_t rtptime;
pa_raop_client_cb_t callback; pa_raop_client_cb_t callback;
void* userdata; void *userdata;
pa_raop_client_closed_cb_t closed_callback; pa_raop_client_closed_cb_t closed_callback;
void* closed_userdata; void *closed_userdata;
}; };
/** /**
@ -130,32 +130,32 @@ static inline void bit_writer(uint8_t **buffer, uint8_t *bit_pos, int *size, uin
if (!*bit_pos) if (!*bit_pos)
*size += 1; *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; bits_left = 7 - *bit_pos + 1;
/* Calc the overflow of bits in relation to how much space we have left... */ /* Calc the overflow of bits in relation to how much space we have left... */
bit_overflow = bits_left - data_bit_len; bit_overflow = bits_left - data_bit_len;
if (bit_overflow >= 0) { if (bit_overflow >= 0) {
/* We can fit the new data in our current byte */ /* 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 */ * As we write from MSB->LSB we need to left shift by the overflow amount. */
bit_data = data << bit_overflow; bit_data = data << bit_overflow;
if (*bit_pos) if (*bit_pos)
**buffer |= bit_data; **buffer |= bit_data;
else else
**buffer = bit_data; **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) { 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; *buffer += 1;
*bit_pos = 0; *bit_pos = 0;
} else { } else {
*bit_pos += data_bit_len; *bit_pos += data_bit_len;
} }
} else { } else {
/* bit_overflow is negative, there for we will need a new byte from our buffer */ /* 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 */ * Firstly fill up what's left in the current byte. */
bit_data = data >> -bit_overflow; bit_data = data >> -bit_overflow;
**buffer |= bit_data; **buffer |= bit_data;
/* Increment our buffer pointer and size counter*/ /* Increment our buffer pointer and size counter. */
*buffer += 1; *buffer += 1;
*size += 1; *size += 1;
**buffer = data << (8 + bit_overflow); **buffer = data << (8 + bit_overflow);
@ -191,7 +191,7 @@ static int rsa_encrypt(uint8_t *text, int len, uint8_t *res) {
return size; 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; uint8_t *buf;
int i=0, j; int i=0, j;
@ -246,8 +246,8 @@ static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata
c->callback(c->fd, c->userdata); c->callback(c->fd, c->userdata);
} }
static void rtsp_cb(pa_rtsp_client *rtsp, pa_rtsp_state state, pa_headerlist* headers, void *userdata) { static void rtsp_cb(pa_rtsp_client *rtsp, pa_rtsp_state state, pa_headerlist *headers, void *userdata) {
pa_raop_client* c = userdata; pa_raop_client *c = userdata;
pa_assert(c); pa_assert(c);
pa_assert(rtsp); pa_assert(rtsp);
pa_assert(rtsp == c->rtsp); pa_assert(rtsp == c->rtsp);
@ -263,12 +263,12 @@ static void rtsp_cb(pa_rtsp_client *rtsp, pa_rtsp_state state, pa_headerlist* he
pa_log_debug("RAOP: CONNECTED"); pa_log_debug("RAOP: CONNECTED");
ip = pa_rtsp_localip(c->rtsp); 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); url = pa_sprintf_malloc("rtsp://%s/%s", ip, c->sid);
pa_rtsp_set_url(c->rtsp, url); pa_rtsp_set_url(c->rtsp, url);
pa_xfree(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); i = rsa_encrypt(c->aes_key, AES_CHUNKSIZE, rsakey);
pa_base64_encode(rsakey, i, &key); pa_base64_encode(rsakey, i, &key);
rtrimchar(key, '='); rtrimchar(key, '=');
@ -367,7 +367,7 @@ static void rtsp_cb(pa_rtsp_client *rtsp, pa_rtsp_state state, pa_headerlist* he
pa_rtsp_client_free(c->rtsp); pa_rtsp_client_free(c->rtsp);
c->rtsp = NULL; c->rtsp = NULL;
if (c->fd > 0) { 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; c->fd = -1;
} }
if (c->sc) { if (c->sc) {
@ -381,7 +381,7 @@ 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_parsed_address a;
pa_raop_client* c; pa_raop_client* c;
@ -410,10 +410,11 @@ pa_raop_client* pa_raop_client_new(pa_core *core, const char* host) {
pa_raop_client_free(c); pa_raop_client_free(c);
return NULL; return NULL;
} }
return c; return c;
} }
void pa_raop_client_free(pa_raop_client* c) { void pa_raop_client_free(pa_raop_client *c) {
pa_assert(c); pa_assert(c);
if (c->rtsp) if (c->rtsp)
@ -424,7 +425,7 @@ void pa_raop_client_free(pa_raop_client* c) {
pa_xfree(c); pa_xfree(c);
} }
int pa_raop_connect(pa_raop_client* c) { int pa_raop_connect(pa_raop_client *c) {
char *sci; char *sci;
struct { struct {
uint32_t a; uint32_t a;
@ -441,30 +442,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)"); 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_iv, sizeof(c->aes_iv));
pa_random(c->aes_key, sizeof(c->aes_key)); pa_random(c->aes_key, sizeof(c->aes_key));
memcpy(c->aes_nv, c->aes_iv, sizeof(c->aes_nv)); memcpy(c->aes_nv, c->aes_iv, sizeof(c->aes_nv));
AES_set_encrypt_key(c->aes_key, 128, &c->aes); 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)); pa_random(&rand_data, sizeof(rand_data));
c->sid = pa_sprintf_malloc("%u", rand_data.a); c->sid = pa_sprintf_malloc("%u", rand_data.a);
sci = pa_sprintf_malloc("%08x%08x",rand_data.b, rand_data.c); sci = pa_sprintf_malloc("%08x%08x",rand_data.b, rand_data.c);
pa_rtsp_add_header(c->rtsp, "Client-Instance", sci); pa_rtsp_add_header(c->rtsp, "Client-Instance", sci);
pa_xfree(sci); pa_xfree(sci);
pa_rtsp_set_callback(c->rtsp, rtsp_cb, c); pa_rtsp_set_callback(c->rtsp, rtsp_cb, c);
return pa_rtsp_connect(c->rtsp); 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_assert(c);
pa_rtsp_flush(c->rtsp, c->seq, c->rtptime); pa_rtsp_flush(c->rtsp, c->seq, c->rtptime);
return 0; 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; int rv;
double db; double db;
char *param; char *param;
@ -479,13 +481,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); 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); rv = pa_rtsp_setparameter(c->rtsp, param);
pa_xfree(param); pa_xfree(param);
return rv; 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; uint16_t len;
size_t bufmax; size_t bufmax;
uint8_t *bp, bpos; uint8_t *bp, bpos;
@ -513,25 +516,25 @@ int pa_raop_client_encode_sample(pa_raop_client* c, pa_memchunk* raw, pa_memchun
bsize = (int)(raw->length / 4); bsize = (int)(raw->length / 4);
length = bsize * 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; bufmax = length + header_size + 16;
pa_memchunk_reset(encoded); pa_memchunk_reset(encoded);
encoded->memblock = pa_memblock_new(c->core->mempool, bufmax); encoded->memblock = pa_memblock_new(c->core->mempool, bufmax);
b = pa_memblock_acquire(encoded->memblock); b = pa_memblock_acquire(encoded->memblock);
memcpy(b, header, header_size); memcpy(b, header, header_size);
/* Now write the actual samples */ /* Now write the actual samples. */
bp = b + header_size; bp = b + header_size;
size = bpos = 0; size = bpos = 0;
bit_writer(&bp,&bpos,&size,1,3); /* channel=1, stereo */ bit_writer(&bp,&bpos,&size,1,3); /* channel=1, stereo */
bit_writer(&bp,&bpos,&size,0,4); /* unknown */ bit_writer(&bp,&bpos,&size,0,4); /* Unknown */
bit_writer(&bp,&bpos,&size,0,8); /* unknown */ bit_writer(&bp,&bpos,&size,0,8); /* Unknown */
bit_writer(&bp,&bpos,&size,0,4); /* unknown */ bit_writer(&bp,&bpos,&size,0,4); /* Unknown */
bit_writer(&bp,&bpos,&size,1,1); /* hassize */ bit_writer(&bp,&bpos,&size,1,1); /* Hassize */
bit_writer(&bp,&bpos,&size,0,2); /* unused */ bit_writer(&bp,&bpos,&size,0,2); /* Unused */
bit_writer(&bp,&bpos,&size,1,1); /* is-not-compressed */ bit_writer(&bp,&bpos,&size,1,1); /* Is-not-compressed */
/* size of data, integer, big endian */ /* Size of data, integer, big endian. */
bit_writer(&bp,&bpos,&size,(bsize>>24)&0xff,8); bit_writer(&bp,&bpos,&size,(bsize>>24)&0xff,8);
bit_writer(&bp,&bpos,&size,(bsize>>16)&0xff,8); bit_writer(&bp,&bpos,&size,(bsize>>16)&0xff,8);
bit_writer(&bp,&bpos,&size,(bsize>>8)&0xff,8); bit_writer(&bp,&bpos,&size,(bsize>>8)&0xff,8);
@ -540,7 +543,7 @@ int pa_raop_client_encode_sample(pa_raop_client* c, pa_memchunk* raw, pa_memchun
ibp = p = pa_memblock_acquire(raw->memblock); ibp = p = pa_memblock_acquire(raw->memblock);
maxibp = p + raw->length - 4; maxibp = p + raw->length - 4;
while (ibp <= maxibp) { 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+1),8);
bit_writer(&bp,&bpos,&size,*(ibp+0),8); bit_writer(&bp,&bpos,&size,*(ibp+0),8);
bit_writer(&bp,&bpos,&size,*(ibp+3),8); bit_writer(&bp,&bpos,&size,*(ibp+3),8);
@ -552,28 +555,28 @@ int pa_raop_client_encode_sample(pa_raop_client* c, pa_memchunk* raw, pa_memchun
pa_memblock_release(raw->memblock); pa_memblock_release(raw->memblock);
encoded->length = header_size + size; 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; len = size + header_size - 4;
*(b + 2) = len >> 8; *(b + 2) = len >> 8;
*(b + 3) = len & 0xff; *(b + 3) = len & 0xff;
/* encrypt our data */ /* Encrypt our data. */
aes_encrypt(c, (b + header_size), size); aes_encrypt(c, (b + header_size), size);
/* We're done with the chunk */ /* We're done with the chunk. */
pa_memblock_release(encoded->memblock); pa_memblock_release(encoded->memblock);
return 0; 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); pa_assert(c);
c->callback = callback; c->callback = callback;
c->userdata = userdata; 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); pa_assert(c);
c->closed_callback = callback; c->closed_callback = callback;

View file

@ -24,19 +24,19 @@
typedef struct pa_raop_client pa_raop_client; typedef struct pa_raop_client pa_raop_client;
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);
void pa_raop_client_free(pa_raop_client* c); void pa_raop_client_free(pa_raop_client *c);
int pa_raop_connect(pa_raop_client* c); int pa_raop_connect(pa_raop_client *c);
int pa_raop_flush(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_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_encode_sample(pa_raop_client *c, pa_memchunk *raw, pa_memchunk *encoded);
typedef void (*pa_raop_client_cb_t)(int fd, void *userdata); 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); 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 #endif

View file

@ -73,7 +73,7 @@ struct pa_rtsp_client {
char *transport; char *transport;
}; };
pa_rtsp_client* pa_rtsp_client_new(pa_mainloop_api *mainloop, const char* hostname, uint16_t port, const char* useragent) { pa_rtsp_client* pa_rtsp_client_new(pa_mainloop_api *mainloop, const char *hostname, uint16_t port, const char *useragent) {
pa_rtsp_client *c; pa_rtsp_client *c;
pa_assert(mainloop); pa_assert(mainloop);
@ -94,7 +94,7 @@ pa_rtsp_client* pa_rtsp_client_new(pa_mainloop_api *mainloop, const char* hostna
return c; return c;
} }
void pa_rtsp_client_free(pa_rtsp_client* c) { void pa_rtsp_client_free(pa_rtsp_client *c) {
pa_assert(c); pa_assert(c);
if (c->sc) if (c->sc)
@ -355,25 +355,25 @@ void pa_rtsp_disconnect(pa_rtsp_client *c) {
c->ioline = NULL; c->ioline = NULL;
} }
const char* pa_rtsp_localip(pa_rtsp_client* c) { const char* pa_rtsp_localip(pa_rtsp_client *c) {
pa_assert(c); pa_assert(c);
return c->localip; return c->localip;
} }
uint32_t pa_rtsp_serverport(pa_rtsp_client* c) { uint32_t pa_rtsp_serverport(pa_rtsp_client *c) {
pa_assert(c); pa_assert(c);
return c->rtp_port; return c->rtp_port;
} }
void pa_rtsp_set_url(pa_rtsp_client* c, const char* url) { void pa_rtsp_set_url(pa_rtsp_client *c, const char *url) {
pa_assert(c); pa_assert(c);
c->url = pa_xstrdup(url); c->url = pa_xstrdup(url);
} }
void pa_rtsp_add_header(pa_rtsp_client *c, const char* key, const char* value) { void pa_rtsp_add_header(pa_rtsp_client *c, const char *key, const char *value) {
pa_assert(c); pa_assert(c);
pa_assert(key); pa_assert(key);
pa_assert(value); pa_assert(value);
@ -381,19 +381,19 @@ void pa_rtsp_add_header(pa_rtsp_client *c, const char* key, const char* value) {
pa_headerlist_puts(c->headers, key, value); pa_headerlist_puts(c->headers, key, value);
} }
void pa_rtsp_remove_header(pa_rtsp_client *c, const char* key) { void pa_rtsp_remove_header(pa_rtsp_client *c, const char *key) {
pa_assert(c); pa_assert(c);
pa_assert(key); pa_assert(key);
pa_headerlist_remove(c->headers, key); pa_headerlist_remove(c->headers, key);
} }
static int rtsp_exec(pa_rtsp_client* c, const char* cmd, static int rtsp_exec(pa_rtsp_client *c, const char *cmd,
const char* content_type, const char* content, const char *content_type, const char *content,
int expect_response, int expect_response,
pa_headerlist* headers) { pa_headerlist *headers) {
pa_strbuf* buf; pa_strbuf *buf;
char* hdrs; char *hdrs;
pa_assert(c); pa_assert(c);
pa_assert(c->url); pa_assert(c->url);
@ -443,17 +443,22 @@ static int rtsp_exec(pa_rtsp_client* c, const char* cmd,
return 0; return 0;
} }
int pa_rtsp_announce(pa_rtsp_client *c, const char* sdp) { int pa_rtsp_announce(pa_rtsp_client *c, const char *sdp) {
int rv;
pa_assert(c); pa_assert(c);
if (!sdp) if (!sdp)
return -1; return -1;
c->state = STATE_ANNOUNCE; c->state = STATE_ANNOUNCE;
return rtsp_exec(c, "ANNOUNCE", "application/sdp", sdp, 1, NULL); rv = rtsp_exec(c, "ANNOUNCE", "application/sdp", sdp, 1, NULL);
return rv;
} }
int pa_rtsp_setup(pa_rtsp_client* c) { int pa_rtsp_setup(pa_rtsp_client *c) {
pa_headerlist* headers; pa_headerlist *headers;
int rv; int rv;
pa_assert(c); pa_assert(c);
@ -463,16 +468,18 @@ int pa_rtsp_setup(pa_rtsp_client* c) {
c->state = STATE_SETUP; c->state = STATE_SETUP;
rv = rtsp_exec(c, "SETUP", NULL, NULL, 1, headers); rv = rtsp_exec(c, "SETUP", NULL, NULL, 1, headers);
pa_headerlist_free(headers); pa_headerlist_free(headers);
return rv; return rv;
} }
int pa_rtsp_record(pa_rtsp_client* c, uint16_t* seq, uint32_t* rtptime) { int pa_rtsp_record(pa_rtsp_client *c, uint16_t *seq, uint32_t *rtptime) {
pa_headerlist* headers; pa_headerlist *headers;
int rv;
char *info; char *info;
int rv;
pa_assert(c); pa_assert(c);
if (!c->session) { if (!c->session) {
/* No session in progress */ /* No session in progress */
return -1; return -1;
@ -489,30 +496,40 @@ int pa_rtsp_record(pa_rtsp_client* c, uint16_t* seq, uint32_t* rtptime) {
c->state = STATE_RECORD; c->state = STATE_RECORD;
rv = rtsp_exec(c, "RECORD", NULL, NULL, 1, headers); rv = rtsp_exec(c, "RECORD", NULL, NULL, 1, headers);
pa_headerlist_free(headers); pa_headerlist_free(headers);
return rv; return rv;
} }
int pa_rtsp_teardown(pa_rtsp_client *c) { int pa_rtsp_teardown(pa_rtsp_client *c) {
int rv;
pa_assert(c); pa_assert(c);
c->state = STATE_TEARDOWN; c->state = STATE_TEARDOWN;
return rtsp_exec(c, "TEARDOWN", NULL, NULL, 0, NULL); rv = rtsp_exec(c, "TEARDOWN", NULL, NULL, 0, NULL);
return rv;
} }
int pa_rtsp_setparameter(pa_rtsp_client *c, const char* param) { int pa_rtsp_setparameter(pa_rtsp_client *c, const char *param) {
int rv;
pa_assert(c); pa_assert(c);
if (!param) if (!param)
return -1; return -1;
c->state = STATE_SET_PARAMETER; c->state = STATE_SET_PARAMETER;
return rtsp_exec(c, "SET_PARAMETER", "text/parameters", param, 1, NULL); rv = rtsp_exec(c, "SET_PARAMETER", "text/parameters", param, 1, NULL);
return rv;
} }
int pa_rtsp_flush(pa_rtsp_client *c, uint16_t seq, uint32_t rtptime) { int pa_rtsp_flush(pa_rtsp_client *c, uint16_t seq, uint32_t rtptime) {
pa_headerlist* headers; pa_headerlist* headers;
int rv;
char *info; char *info;
int rv;
pa_assert(c); pa_assert(c);
@ -523,6 +540,7 @@ int pa_rtsp_flush(pa_rtsp_client *c, uint16_t seq, uint32_t rtptime) {
c->state = STATE_FLUSH; c->state = STATE_FLUSH;
rv = rtsp_exec(c, "FLUSH", NULL, NULL, 1, headers); rv = rtsp_exec(c, "FLUSH", NULL, NULL, 1, headers);
pa_headerlist_free(headers); pa_headerlist_free(headers);
return rv; return rv;
} }

View file

@ -41,29 +41,29 @@ typedef enum {
STATE_SET_PARAMETER, STATE_SET_PARAMETER,
STATE_DISCONNECTED STATE_DISCONNECTED
} pa_rtsp_state; } pa_rtsp_state;
typedef void (*pa_rtsp_cb_t)(pa_rtsp_client *c, pa_rtsp_state state, pa_headerlist* hl, void *userdata); typedef void (*pa_rtsp_cb_t)(pa_rtsp_client *c, pa_rtsp_state state, pa_headerlist *hl, void *userdata);
pa_rtsp_client* pa_rtsp_client_new(pa_mainloop_api *mainloop, const char* hostname, uint16_t port, const char* useragent); pa_rtsp_client* pa_rtsp_client_new(pa_mainloop_api *mainloop, const char *hostname, uint16_t port, const char *useragent);
void pa_rtsp_client_free(pa_rtsp_client* c); void pa_rtsp_client_free(pa_rtsp_client *c);
int pa_rtsp_connect(pa_rtsp_client* c); int pa_rtsp_connect(pa_rtsp_client *c);
void pa_rtsp_set_callback(pa_rtsp_client *c, pa_rtsp_cb_t callback, void *userdata); void pa_rtsp_set_callback(pa_rtsp_client *c, pa_rtsp_cb_t callback, void *userdata);
void pa_rtsp_disconnect(pa_rtsp_client* c); void pa_rtsp_disconnect(pa_rtsp_client *c);
const char* pa_rtsp_localip(pa_rtsp_client* c); const char* pa_rtsp_localip(pa_rtsp_client *c);
uint32_t pa_rtsp_serverport(pa_rtsp_client* c); uint32_t pa_rtsp_serverport(pa_rtsp_client *c);
void pa_rtsp_set_url(pa_rtsp_client* c, const char* url); void pa_rtsp_set_url(pa_rtsp_client *c, const char *url);
void pa_rtsp_add_header(pa_rtsp_client *c, const char* key, const char* value); void pa_rtsp_add_header(pa_rtsp_client *c, const char *key, const char *value);
void pa_rtsp_remove_header(pa_rtsp_client *c, const char* key); void pa_rtsp_remove_header(pa_rtsp_client *c, const char *key);
int pa_rtsp_announce(pa_rtsp_client* c, const char* sdp); int pa_rtsp_announce(pa_rtsp_client *c, const char *sdp);
int pa_rtsp_setup(pa_rtsp_client* c); int pa_rtsp_setup(pa_rtsp_client *c);
int pa_rtsp_record(pa_rtsp_client* c, uint16_t* seq, uint32_t* rtptime); int pa_rtsp_record(pa_rtsp_client *c, uint16_t *seq, uint32_t *rtptime);
int pa_rtsp_teardown(pa_rtsp_client* c); int pa_rtsp_teardown(pa_rtsp_client *c);
int pa_rtsp_setparameter(pa_rtsp_client* c, const char* param); int pa_rtsp_setparameter(pa_rtsp_client *c, const char *param);
int pa_rtsp_flush(pa_rtsp_client* c, uint16_t seq, uint32_t rtptime); int pa_rtsp_flush(pa_rtsp_client *c, uint16_t seq, uint32_t rtptime);
#endif #endif