#include <string.h>
#include <stdio.h>
#include <stdlib.h>
-#include <limits.h>
#include <pulse/rtclock.h>
#include <pulse/sample.h>
#include <pulsecore/source.h>
#include <pulsecore/core-scache.h>
#include <pulsecore/sample-util.h>
-#include <pulsecore/authkey.h>
#include <pulsecore/namereg.h>
#include <pulsecore/log.h>
#include <pulsecore/core-util.h>
#include <pulsecore/macro.h>
#include <pulsecore/thread-mq.h>
#include <pulsecore/shared.h>
-
-#include "endianmacros.h"
+#include <pulsecore/endianmacros.h>
#include "protocol-esound.h"
pa_msgobject parent;
uint32_t index;
- pa_bool_t dead;
+ bool dead;
pa_esound_protocol *protocol;
pa_esound_options *options;
pa_iochannel *io;
pa_client *client;
- pa_bool_t authorized, swap_byte_order;
+ bool authorized, swap_byte_order;
void *write_data;
size_t write_data_alloc, write_data_index, write_data_length;
void *read_data;
pa_memblock *current_memblock;
size_t memblock_index;
pa_atomic_t missing;
- pa_bool_t underrun;
+ bool underrun;
} playback;
struct {
memcpy((uint8_t*) c->write_data + i, data, length);
}
-static void format_esd2native(int format, pa_bool_t swap_bytes, pa_sample_spec *ss) {
+static void format_esd2native(int format, bool swap_bytes, pa_sample_spec *ss) {
pa_assert(ss);
ss->channels = (uint8_t) (((format & ESD_MASK_CHAN) == ESD_STEREO) ? 2 : 1);
return format;
}
-#define CHECK_VALIDITY(expression, ...) do { \
- if (!(expression)) { \
- pa_log_warn(__FILE__ ": " __VA_ARGS__); \
- return -1; \
- } \
-} while(0);
+#define CHECK_VALIDITY(expression, ...) do { \
+ if (PA_UNLIKELY(!(expression))) { \
+ pa_log_warn(__FILE__ ": " __VA_ARGS__); \
+ return -1; \
+ } \
+ } while(0);
/*** esound commands ***/
if ((key = pa_auth_cookie_read(c->options->auth_cookie, ESD_KEY_LEN)))
if (memcmp(data, key, ESD_KEY_LEN) == 0)
- c->authorized = TRUE;
+ c->authorized = true;
}
if (!c->authorized) {
memcpy(&ekey, data, sizeof(uint32_t));
if (ekey == ESD_ENDIAN_KEY)
- c->swap_byte_order = FALSE;
+ c->swap_byte_order = false;
else if (ekey == ESD_SWAP_ENDIAN_KEY)
- c->swap_byte_order = TRUE;
+ c->swap_byte_order = true;
else {
pa_log_warn("Client sent invalid endian key");
return -1;
size_t l;
pa_sink *sink = NULL;
pa_sink_input_new_data sdata;
+ pa_memchunk silence;
connection_assert_ref(c);
pa_assert(data);
sdata.driver = __FILE__;
sdata.module = c->options->module;
sdata.client = c->client;
- sdata.sink = sink;
+ if (sink)
+ pa_sink_input_new_data_set_sink(&sdata, sink, false);
pa_sink_input_new_data_set_sample_spec(&sdata, &ss);
pa_sink_input_new(&c->sink_input, c->protocol->core, &sdata);
CHECK_VALIDITY(c->sink_input, "Failed to create sink input.");
l = (size_t) ((double) pa_bytes_per_second(&ss)*PLAYBACK_BUFFER_SECONDS);
+ pa_sink_input_get_silence(c->sink_input, &silence);
c->input_memblockq = pa_memblockq_new(
+ "esound protocol connection input_memblockq",
0,
l,
l,
- pa_frame_size(&ss),
+ &ss,
(size_t) -1,
l/PLAYBACK_BUFFER_FRAGMENTS,
0,
- NULL);
+ &silence);
+ pa_memblock_unref(silence.memblock);
pa_iochannel_socket_set_rcvbuf(c->io, l);
c->sink_input->parent.process_msg = sink_input_process_msg;
c->protocol->n_player++;
- pa_atomic_store(&c->playback.missing, (int) pa_memblockq_missing(c->input_memblockq));
+ pa_atomic_store(&c->playback.missing, (int) pa_memblockq_pop_missing(c->input_memblockq));
pa_sink_input_put(c->sink_input);
sdata.driver = __FILE__;
sdata.module = c->options->module;
sdata.client = c->client;
- sdata.source = source;
+ if (source)
+ pa_source_output_new_data_set_source(&sdata, source, false);
pa_source_output_new_data_set_sample_spec(&sdata, &ss);
pa_source_output_new(&c->source_output, c->protocol->core, &sdata);
l = (size_t) (pa_bytes_per_second(&ss)*RECORD_BUFFER_SECONDS);
c->output_memblockq = pa_memblockq_new(
+ "esound protocol connection output_memblockq",
0,
l,
l,
- pa_frame_size(&ss),
+ &ss,
1,
0,
0,
memset(terminator, 0, sizeof(terminator));
- for (conn = pa_idxset_first(c->protocol->connections, &idx); conn; conn = pa_idxset_next(c->protocol->connections, &idx)) {
+ PA_IDXSET_FOREACH(conn, c->protocol->connections, idx) {
int32_t id, format = ESD_BITS16 | ESD_STEREO, rate = 44100, lvolume = ESD_VOLUME_BASE, rvolume = ESD_VOLUME_BASE;
char name[ESD_NAME_MAX];
if (conn->sink_input) {
pa_cvolume volume;
- pa_sink_input_get_volume(conn->sink_input, &volume, TRUE);
+ pa_sink_input_get_volume(conn->sink_input, &volume, true);
rate = (int32_t) conn->sink_input->sample_spec.rate;
lvolume = (int32_t) ((volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM);
rvolume = (int32_t) ((volume.values[volume.channels == 2 ? 1 : 0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM);
pa_scache_entry *ce;
idx = PA_IDXSET_INVALID;
- for (ce = pa_idxset_first(c->protocol->core->scache, &idx); ce; ce = pa_idxset_next(c->protocol->core->scache, &idx)) {
+
+ PA_IDXSET_FOREACH(ce, c->protocol->core->scache, idx) {
int32_t id, rate, lvolume, rvolume, format, len;
char name[ESD_NAME_MAX];
pa_channel_map stereo = { .channels = 2, .map = { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT } };
volume.values[1] = (rvolume*PA_VOLUME_NORM)/ESD_VOLUME_BASE;
volume.channels = conn->sink_input->sample_spec.channels;
- pa_sink_input_set_volume(conn->sink_input, &volume, TRUE, TRUE);
+ pa_sink_input_set_volume(conn->sink_input, &volume, true, true);
ok = 1;
} else
ok = 0;
pa_cvolume_remap(&volume, &stereo, &ce->channel_map);
ce->volume = volume;
- ce->volume_is_set = TRUE;
+ ce->volume_is_set = true;
ok = 1;
}
connection_write_prepare(c, sizeof(int32_t) * 2);
connection_write(c, &ok, sizeof(int32_t));
- if (request == ESD_PROTO_STANDBY)
- ok = pa_sink_suspend_all(c->protocol->core, TRUE, PA_SUSPEND_USER) >= 0;
- else {
+ pa_log_debug("%s of all sinks and sources requested by client %" PRIu32 ".",
+ request == ESD_PROTO_STANDBY ? "Suspending" : "Resuming", c->client->index);
+
+ if (request == ESD_PROTO_STANDBY) {
+ ok = pa_sink_suspend_all(c->protocol->core, true, PA_SUSPEND_USER) >= 0;
+ ok &= pa_source_suspend_all(c->protocol->core, true, PA_SUSPEND_USER) >= 0;
+ } else {
pa_assert(request == ESD_PROTO_RESUME);
- ok = pa_sink_suspend_all(c->protocol->core, FALSE, PA_SUSPEND_USER) >= 0;
+ ok = pa_sink_suspend_all(c->protocol->core, false, PA_SUSPEND_USER) >= 0;
+ ok &= pa_source_suspend_all(c->protocol->core, false, PA_SUSPEND_USER) >= 0;
}
connection_write(c, &ok, sizeof(int32_t));
c->request = PA_MAYBE_INT32_SWAP(c->swap_byte_order, c->request);
if (c->request < ESD_PROTO_CONNECT || c->request >= ESD_PROTO_MAX) {
- pa_log("recieved invalid request.");
+ pa_log("received invalid request.");
return -1;
}
/* pa_log("executing request #%u", c->request); */
if (!handler->proc) {
- pa_log("recieved unimplemented request #%u.", c->request);
+ pa_log("received unimplemented request #%u.", c->request);
return -1;
}
/* pa_log("STREAMING_DATA"); */
- if (!(l = (size_t) pa_atomic_load(&c->playback.missing)))
+ if ((l = (size_t) pa_atomic_load(&c->playback.missing)) <= 0)
return 0;
if (c->playback.current_memblock) {
c->playback.memblock_index += (size_t) r;
- pa_asyncmsgq_post(c->sink_input->sink->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, 0, &chunk, NULL);
pa_atomic_sub(&c->playback.missing, (int) r);
+ pa_asyncmsgq_post(c->sink_input->sink->asyncmsgq, PA_MSGOBJECT(c->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, 0, &chunk, NULL);
}
return 0;
pa_assert(c->write_data_index < c->write_data_length);
if ((r = pa_iochannel_write(c->io, (uint8_t*) c->write_data+c->write_data_index, c->write_data_length-c->write_data_index)) < 0) {
-
- if (r < 0 && (errno == EINTR || errno == EAGAIN))
- return 0;
-
pa_log("write(): %s", pa_cstrerror(errno));
return -1;
}
if (c->write_data_index >= c->write_data_length)
c->write_data_length = c->write_data_index = 0;
+ return 1;
+
} else if (c->state == ESD_STREAMING_DATA && c->source_output) {
pa_memchunk chunk;
ssize_t r;
pa_memblock_unref(chunk.memblock);
if (r < 0) {
-
- if (r < 0 && (errno == EINTR || errno == EAGAIN))
- return 0;
-
pa_log("write(): %s", pa_cstrerror(errno));
return -1;
}
pa_memblockq_drop(c->output_memblockq, (size_t) r);
+ return 1;
}
return 0;
* here, instead of simply waiting for read() to return 0. */
goto fail;
- if (pa_iochannel_is_writable(c->io))
- if (do_write(c) < 0)
+ while (pa_iochannel_is_writable(c->io)) {
+ int r = do_write(c);
+ if (r < 0)
goto fail;
+ if (r == 0)
+ break;
+ }
return;
fail:
if (c->state == ESD_STREAMING_DATA && c->sink_input) {
- c->dead = TRUE;
+ c->dead = true;
pa_iochannel_free(c->io);
c->io = NULL;
if (pa_memblockq_is_readable(c->input_memblockq) && c->playback.underrun) {
pa_log_debug("Requesting rewind due to end of underrun.");
- pa_sink_input_request_rewind(c->sink_input, 0, FALSE, TRUE, FALSE);
+ pa_sink_input_request_rewind(c->sink_input, 0, false, true, false);
}
/* pa_log("got data, %u", pa_memblockq_get_length(c->input_memblockq)); */
if (pa_memblockq_peek(c->input_memblockq, chunk) < 0) {
- c->playback.underrun = TRUE;
+ c->playback.underrun = true;
if (c->dead && pa_sink_input_safe_to_remove(i))
pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(c), CONNECTION_MESSAGE_UNLINK_CONNECTION, NULL, 0, NULL, NULL);
} else {
size_t m;
- chunk->length = PA_MIN(length, chunk->length);
-
- c->playback.underrun = FALSE;
+ c->playback.underrun = false;
+ chunk->length = PA_MIN(length, chunk->length);
pa_memblockq_drop(c->input_memblockq, chunk->length);
m = pa_memblockq_pop_missing(c->input_memblockq);
c->client->userdata = c;
c->options = pa_esound_options_ref(o);
- c->authorized = FALSE;
- c->swap_byte_order = FALSE;
- c->dead = FALSE;
+ c->authorized = false;
+ c->swap_byte_order = false;
+ c->dead = false;
c->read_data_length = 0;
c->read_data = pa_xmalloc(c->read_data_alloc = proto_map[ESD_PROTO_CONNECT].data_length);
c->playback.current_memblock = NULL;
c->playback.memblock_index = 0;
- c->playback.underrun = TRUE;
+ c->playback.underrun = true;
pa_atomic_store(&c->playback.missing, 0);
pa_memchunk_reset(&c->scache.memchunk);
if (o->auth_anonymous) {
pa_log_info("Client authenticated anonymously.");
- c->authorized = TRUE;
+ c->authorized = true;
}
if (!c->authorized &&
pa_ip_acl_check(o->auth_ip_acl, pa_iochannel_get_recv_fd(io)) > 0) {
pa_log_info("Client authenticated by IP ACL.");
- c->authorized = TRUE;
+ c->authorized = true;
}
if (!c->authorized)
while ((c = pa_idxset_first(p->connections, NULL)))
connection_unlink(c);
- pa_idxset_free(p->connections, NULL, NULL);
+ pa_idxset_free(p->connections, NULL);
pa_assert_se(pa_shared_remove(p->core, "esound-protocol") >= 0);
}
int pa_esound_options_parse(pa_esound_options *o, pa_core *c, pa_modargs *ma) {
- pa_bool_t enabled;
+ bool enabled;
const char *acl;
pa_assert(o);
o->auth_ip_acl = ipa;
}
- enabled = TRUE;
+ enabled = true;
if (pa_modargs_get_value_boolean(ma, "auth-cookie-enabled", &enabled) < 0) {
pa_log("auth-cookie-enabled= expects a boolean argument.");
return -1;
if (!(cn = pa_modargs_get_value(ma, "cookie", NULL)))
cn = DEFAULT_COOKIE_FILE;
- if (!(o->auth_cookie = pa_auth_cookie_get(c, cn, ESD_KEY_LEN)))
+ if (!(o->auth_cookie = pa_auth_cookie_get(c, cn, true, ESD_KEY_LEN)))
return -1;
} else