From f44ba092651aa75055e109e04b4164ea92ae7fdc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 19 Jun 2006 21:53:48 +0000 Subject: big s/polyp/pulse/g git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1033 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 980 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 980 insertions(+) create mode 100644 src/pulse/context.c (limited to 'src/pulse/context.c') diff --git a/src/pulse/context.c b/src/pulse/context.c new file mode 100644 index 00000000..648024c3 --- /dev/null +++ b/src/pulse/context.c @@ -0,0 +1,980 @@ +/* $Id$ */ + +/*** + This file is part of PulseAudio. + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SYS_WAIT_H +#include +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif + +#include "../pulsecore/winsock.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" + +#include "client-conf.h" + +#ifdef HAVE_X11 +#include "client-conf-x11.h" +#endif + +#include "context.h" + +#define AUTOSPAWN_LOCK "autospawn.lock" + +static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { + [PA_COMMAND_REQUEST] = pa_command_request, + [PA_COMMAND_OVERFLOW] = pa_command_overflow_or_underflow, + [PA_COMMAND_UNDERFLOW] = pa_command_overflow_or_underflow, + [PA_COMMAND_PLAYBACK_STREAM_KILLED] = pa_command_stream_killed, + [PA_COMMAND_RECORD_STREAM_KILLED] = pa_command_stream_killed, + [PA_COMMAND_SUBSCRIBE_EVENT] = pa_command_subscribe_event +}; + +static void unlock_autospawn_lock_file(pa_context *c) { + assert(c); + + if (c->autospawn_lock_fd >= 0) { + char lf[PATH_MAX]; + pa_runtime_path(AUTOSPAWN_LOCK, lf, sizeof(lf)); + + pa_unlock_lockfile(lf, c->autospawn_lock_fd); + c->autospawn_lock_fd = -1; + } +} + +pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { + pa_context *c; + + assert(mainloop); + assert(name); + + c = pa_xnew(pa_context, 1); + c->ref = 1; + c->name = pa_xstrdup(name); + c->mainloop = mainloop; + c->client = NULL; + c->pstream = NULL; + c->pdispatch = NULL; + c->playback_streams = pa_dynarray_new(); + c->record_streams = pa_dynarray_new(); + + PA_LLIST_HEAD_INIT(pa_stream, c->streams); + PA_LLIST_HEAD_INIT(pa_operation, c->operations); + + c->error = PA_OK; + c->state = PA_CONTEXT_UNCONNECTED; + c->ctag = 0; + c->csyncid = 0; + + c->state_callback = NULL; + c->state_userdata = NULL; + + c->subscribe_callback = NULL; + c->subscribe_userdata = NULL; + + c->memblock_stat = pa_memblock_stat_new(); + c->local = -1; + c->server_list = NULL; + c->server = NULL; + c->autospawn_lock_fd = -1; + memset(&c->spawn_api, 0, sizeof(c->spawn_api)); + c->do_autospawn = 0; + +#ifdef SIGPIPE + pa_check_signal_is_blocked(SIGPIPE); +#endif + + c->conf = pa_client_conf_new(); + pa_client_conf_load(c->conf, NULL); +#ifdef HAVE_X11 + pa_client_conf_from_x11(c->conf, NULL); +#endif + pa_client_conf_env(c->conf); + + return c; +} + +static void context_free(pa_context *c) { + assert(c); + + unlock_autospawn_lock_file(c); + + while (c->operations) + pa_operation_cancel(c->operations); + + while (c->streams) + pa_stream_set_state(c->streams, PA_STREAM_TERMINATED); + + if (c->client) + pa_socket_client_unref(c->client); + if (c->pdispatch) + pa_pdispatch_unref(c->pdispatch); + if (c->pstream) { + pa_pstream_close(c->pstream); + pa_pstream_unref(c->pstream); + } + + if (c->record_streams) + pa_dynarray_free(c->record_streams, NULL, NULL); + if (c->playback_streams) + pa_dynarray_free(c->playback_streams, NULL, NULL); + + pa_memblock_stat_unref(c->memblock_stat); + + if (c->conf) + pa_client_conf_free(c->conf); + + pa_strlist_free(c->server_list); + + pa_xfree(c->name); + pa_xfree(c->server); + pa_xfree(c); +} + +pa_context* pa_context_ref(pa_context *c) { + assert(c); + assert(c->ref >= 1); + + c->ref++; + return c; +} + +void pa_context_unref(pa_context *c) { + assert(c); + assert(c->ref >= 1); + + if (--c->ref <= 0) + context_free(c); +} + +void pa_context_set_state(pa_context *c, pa_context_state_t st) { + assert(c); + assert(c->ref >= 1); + + if (c->state == st) + return; + + pa_context_ref(c); + + c->state = st; + if (c->state_callback) + c->state_callback(c, c->state_userdata); + + if (st == PA_CONTEXT_FAILED || st == PA_CONTEXT_TERMINATED) { + pa_stream *s; + + s = c->streams ? pa_stream_ref(c->streams) : NULL; + while (s) { + pa_stream *n = s->next ? pa_stream_ref(s->next) : NULL; + pa_stream_set_state(s, st == PA_CONTEXT_FAILED ? PA_STREAM_FAILED : PA_STREAM_TERMINATED); + pa_stream_unref(s); + s = n; + } + + if (c->pdispatch) + pa_pdispatch_unref(c->pdispatch); + c->pdispatch = NULL; + + if (c->pstream) { + pa_pstream_close(c->pstream); + pa_pstream_unref(c->pstream); + } + c->pstream = NULL; + + if (c->client) + pa_socket_client_unref(c->client); + c->client = NULL; + } + + pa_context_unref(c); +} + +void pa_context_fail(pa_context *c, int error) { + assert(c); + assert(c->ref >= 1); + + pa_context_set_error(c, error); + pa_context_set_state(c, PA_CONTEXT_FAILED); +} + +int pa_context_set_error(pa_context *c, int error) { + assert(error >= 0); + assert(error < PA_ERR_MAX); + + if (c) + c->error = error; + + return error; +} + +static void pstream_die_callback(pa_pstream *p, void *userdata) { + pa_context *c = userdata; + + assert(p); + assert(c); + + pa_context_fail(c, PA_ERR_CONNECTIONTERMINATED); +} + +static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const void *creds, void *userdata) { + pa_context *c = userdata; + + assert(p); + assert(packet); + assert(c); + + pa_context_ref(c); + + if (pa_pdispatch_run(c->pdispatch, packet, creds, c) < 0) + pa_context_fail(c, PA_ERR_PROTOCOL); + + pa_context_unref(c); +} + +static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata) { + pa_context *c = userdata; + pa_stream *s; + + assert(p); + assert(chunk); + assert(chunk->memblock); + assert(chunk->length); + assert(c); + assert(c->ref >= 1); + + pa_context_ref(c); + + if ((s = pa_dynarray_get(c->record_streams, channel))) { + + assert(seek == PA_SEEK_RELATIVE && offset == 0); + + pa_memblockq_seek(s->record_memblockq, offset, seek); + pa_memblockq_push_align(s->record_memblockq, chunk); + + if (s->read_callback) { + size_t l; + + if ((l = pa_memblockq_get_length(s->record_memblockq)) > 0) + s->read_callback(s, l, s->read_userdata); + } + } + + pa_context_unref(c); +} + +int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t) { + assert(c); + assert(c->ref >= 1); + + if (command == PA_COMMAND_ERROR) { + assert(t); + + if (pa_tagstruct_getu32(t, &c->error) < 0) { + pa_context_fail(c, PA_ERR_PROTOCOL); + return -1; + + } + } else if (command == PA_COMMAND_TIMEOUT) + c->error = PA_ERR_TIMEOUT; + else { + pa_context_fail(c, PA_ERR_PROTOCOL); + return -1; + } + + return 0; +} + +static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_context *c = userdata; + + assert(pd); + assert(c); + assert(c->state == PA_CONTEXT_AUTHORIZING || c->state == PA_CONTEXT_SETTING_NAME); + + pa_context_ref(c); + + if (command != PA_COMMAND_REPLY) { + + if (pa_context_handle_error(c, command, t) < 0) + pa_context_fail(c, PA_ERR_PROTOCOL); + + pa_context_fail(c, c->error); + goto finish; + } + + switch(c->state) { + case PA_CONTEXT_AUTHORIZING: { + pa_tagstruct *reply; + + if (pa_tagstruct_getu32(t, &c->version) < 0 || + !pa_tagstruct_eof(t)) { + pa_context_fail(c, PA_ERR_PROTOCOL); + goto finish; + } + + /* Minimum supported version */ + if (c->version < 8) { + pa_context_fail(c, PA_ERR_VERSION); + goto finish; + } + + reply = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag); + pa_tagstruct_puts(reply, c->name); + pa_pstream_send_tagstruct(c->pstream, reply); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c, NULL); + + pa_context_set_state(c, PA_CONTEXT_SETTING_NAME); + break; + } + + case PA_CONTEXT_SETTING_NAME : + pa_context_set_state(c, PA_CONTEXT_READY); + break; + + default: + assert(0); + } + +finish: + pa_context_unref(c); +} + +static void setup_context(pa_context *c, pa_iochannel *io) { + pa_tagstruct *t; + uint32_t tag; + + assert(c); + assert(io); + + pa_context_ref(c); + + assert(!c->pstream); + c->pstream = pa_pstream_new(c->mainloop, io, c->memblock_stat); + + pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); + pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); + pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); + + assert(!c->pdispatch); + c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); + + if (!c->conf->cookie_valid) { + pa_context_fail(c, PA_ERR_AUTHKEY); + goto finish; + } + + t = pa_tagstruct_command(c, PA_COMMAND_AUTH, &tag); + pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION); + pa_tagstruct_put_arbitrary(t, c->conf->cookie, sizeof(c->conf->cookie)); + pa_pstream_send_tagstruct_with_creds(c->pstream, t, 1); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c, NULL); + + pa_context_set_state(c, PA_CONTEXT_AUTHORIZING); + +finish: + + pa_context_unref(c); +} + +static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata); + +#ifndef OS_IS_WIN32 + +static int context_connect_spawn(pa_context *c) { + pid_t pid; + int status, r; + int fds[2] = { -1, -1} ; + pa_iochannel *io; + + pa_context_ref(c); + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { + pa_log(__FILE__": socketpair(): %s", pa_cstrerror(errno)); + pa_context_fail(c, PA_ERR_INTERNAL); + goto fail; + } + + pa_fd_set_cloexec(fds[0], 1); + + pa_socket_low_delay(fds[0]); + pa_socket_low_delay(fds[1]); + + if (c->spawn_api.prefork) + c->spawn_api.prefork(); + + if ((pid = fork()) < 0) { + pa_log(__FILE__": fork(): %s", pa_cstrerror(errno)); + pa_context_fail(c, PA_ERR_INTERNAL); + + if (c->spawn_api.postfork) + c->spawn_api.postfork(); + + goto fail; + } else if (!pid) { + /* Child */ + + char t[128]; + const char *state = NULL; +#define MAX_ARGS 64 + const char * argv[MAX_ARGS+1]; + int n; + + /* Not required, since fds[0] has CLOEXEC enabled anyway */ + close(fds[0]); + + if (c->spawn_api.atfork) + c->spawn_api.atfork(); + + /* Setup argv */ + + n = 0; + + argv[n++] = c->conf->daemon_binary; + argv[n++] = "--daemonize=yes"; + + snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]); + argv[n++] = strdup(t); + + while (n < MAX_ARGS) { + char *a; + + if (!(a = pa_split_spaces(c->conf->extra_arguments, &state))) + break; + + argv[n++] = a; + } + + argv[n++] = NULL; + + execv(argv[0], (char * const *) argv); + _exit(1); +#undef MAX_ARGS + } + + /* Parent */ + + r = waitpid(pid, &status, 0); + + if (c->spawn_api.postfork) + c->spawn_api.postfork(); + + if (r < 0) { + pa_log(__FILE__": waitpid(): %s", pa_cstrerror(errno)); + pa_context_fail(c, PA_ERR_INTERNAL); + goto fail; + } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + pa_context_fail(c, PA_ERR_CONNECTIONREFUSED); + goto fail; + } + + close(fds[1]); + + c->local = 1; + + io = pa_iochannel_new(c->mainloop, fds[0], fds[0]); + + setup_context(c, io); + unlock_autospawn_lock_file(c); + + pa_context_unref(c); + + return 0; + +fail: + if (fds[0] != -1) + close(fds[0]); + if (fds[1] != -1) + close(fds[1]); + + unlock_autospawn_lock_file(c); + + pa_context_unref(c); + + return -1; +} + +#endif /* OS_IS_WIN32 */ + +static int try_next_connection(pa_context *c) { + char *u = NULL; + int r = -1; + + assert(c); + assert(!c->client); + + for (;;) { + pa_xfree(u); + u = NULL; + + c->server_list = pa_strlist_pop(c->server_list, &u); + + if (!u) { + +#ifndef OS_IS_WIN32 + if (c->do_autospawn) { + r = context_connect_spawn(c); + goto finish; + } +#endif + + pa_context_fail(c, PA_ERR_CONNECTIONREFUSED); + goto finish; + } + + pa_log_debug(__FILE__": Trying to connect to %s...", u); + + pa_xfree(c->server); + c->server = pa_xstrdup(u); + + if (!(c->client = pa_socket_client_new_string(c->mainloop, u, PA_NATIVE_DEFAULT_PORT))) + continue; + + c->local = pa_socket_client_is_local(c->client); + pa_socket_client_set_callback(c->client, on_connection, c); + break; + } + + r = 0; + +finish: + pa_xfree(u); + + return r; +} + +static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata) { + pa_context *c = userdata; + + assert(client); + assert(c); + assert(c->state == PA_CONTEXT_CONNECTING); + + pa_context_ref(c); + + pa_socket_client_unref(client); + c->client = NULL; + + if (!io) { + /* Try the item in the list */ + if (errno == ECONNREFUSED || errno == ETIMEDOUT || errno == EHOSTUNREACH) { + try_next_connection(c); + goto finish; + } + + pa_context_fail(c, PA_ERR_CONNECTIONREFUSED); + goto finish; + } + + unlock_autospawn_lock_file(c); + setup_context(c, io); + +finish: + pa_context_unref(c); +} + +int pa_context_connect( + pa_context *c, + const char *server, + pa_context_flags_t flags, + const pa_spawn_api *api) { + + int r = -1; + + assert(c); + assert(c->ref >= 1); + + PA_CHECK_VALIDITY(c, c->state == PA_CONTEXT_UNCONNECTED, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY(c, !(flags & ~PA_CONTEXT_NOAUTOSPAWN), PA_ERR_INVALID); + PA_CHECK_VALIDITY(c, !server || *server, PA_ERR_INVALID); + + if (!server) + server = c->conf->default_server; + + pa_context_ref(c); + + assert(!c->server_list); + + if (server) { + if (!(c->server_list = pa_strlist_parse(server))) { + pa_context_fail(c, PA_ERR_INVALIDSERVER); + goto finish; + } + } else { + char *d; + char ufn[PATH_MAX]; + + /* Prepend in reverse order */ + + if ((d = getenv("DISPLAY"))) { + char *e; + d = pa_xstrdup(d); + if ((e = strchr(d, ':'))) + *e = 0; + + if (*d) + c->server_list = pa_strlist_prepend(c->server_list, d); + + pa_xfree(d); + } + + c->server_list = pa_strlist_prepend(c->server_list, "tcp6:localhost"); + c->server_list = pa_strlist_prepend(c->server_list, "localhost"); + c->server_list = pa_strlist_prepend(c->server_list, pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET, ufn, sizeof(ufn))); + + /* Wrap the connection attempts in a single transaction for sane autospawn locking */ + if (!(flags & PA_CONTEXT_NOAUTOSPAWN) && c->conf->autospawn) { + char lf[PATH_MAX]; + + pa_runtime_path(AUTOSPAWN_LOCK, lf, sizeof(lf)); + pa_make_secure_parent_dir(lf); + assert(c->autospawn_lock_fd <= 0); + c->autospawn_lock_fd = pa_lock_lockfile(lf); + + if (api) + c->spawn_api = *api; + c->do_autospawn = 1; + } + + } + + pa_context_set_state(c, PA_CONTEXT_CONNECTING); + r = try_next_connection(c); + +finish: + pa_context_unref(c); + + return r; +} + +void pa_context_disconnect(pa_context *c) { + assert(c); + assert(c->ref >= 1); + + pa_context_set_state(c, PA_CONTEXT_TERMINATED); +} + +pa_context_state_t pa_context_get_state(pa_context *c) { + assert(c); + assert(c->ref >= 1); + + return c->state; +} + +int pa_context_errno(pa_context *c) { + assert(c); + assert(c->ref >= 1); + + return c->error; +} + +void pa_context_set_state_callback(pa_context *c, pa_context_notify_cb_t cb, void *userdata) { + assert(c); + assert(c->ref >= 1); + + c->state_callback = cb; + c->state_userdata = userdata; +} + +int pa_context_is_pending(pa_context *c) { + assert(c); + assert(c->ref >= 1); + + PA_CHECK_VALIDITY(c, + c->state == PA_CONTEXT_CONNECTING || + c->state == PA_CONTEXT_AUTHORIZING || + c->state == PA_CONTEXT_SETTING_NAME || + c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + + return (c->pstream && pa_pstream_is_pending(c->pstream)) || + (c->pdispatch && pa_pdispatch_is_pending(c->pdispatch)) || + c->client; +} + +static void set_dispatch_callbacks(pa_operation *o); + +static void pdispatch_drain_callback(PA_GCC_UNUSED pa_pdispatch*pd, void *userdata) { + set_dispatch_callbacks(userdata); +} + +static void pstream_drain_callback(PA_GCC_UNUSED pa_pstream *s, void *userdata) { + set_dispatch_callbacks(userdata); +} + +static void set_dispatch_callbacks(pa_operation *o) { + int done = 1; + + assert(o); + assert(o->ref >= 1); + assert(o->context); + assert(o->context->ref >= 1); + assert(o->context->state == PA_CONTEXT_READY); + + pa_pstream_set_drain_callback(o->context->pstream, NULL, NULL); + pa_pdispatch_set_drain_callback(o->context->pdispatch, NULL, NULL); + + if (pa_pdispatch_is_pending(o->context->pdispatch)) { + pa_pdispatch_set_drain_callback(o->context->pdispatch, pdispatch_drain_callback, o); + done = 0; + } + + if (pa_pstream_is_pending(o->context->pstream)) { + pa_pstream_set_drain_callback(o->context->pstream, pstream_drain_callback, o); + done = 0; + } + + if (done) { + if (o->callback) { + pa_context_notify_cb_t cb = (pa_context_notify_cb_t) o->callback; + cb(o->context, o->userdata); + } + + pa_operation_done(o); + pa_operation_unref(o); + } +} + +pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *userdata) { + pa_operation *o; + + assert(c); + assert(c->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + PA_CHECK_VALIDITY_RETURN_NULL(c, pa_context_is_pending(c), PA_ERR_BADSTATE); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + set_dispatch_callbacks(pa_operation_ref(o)); + + return o; +} + +void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_operation *o = userdata; + int success = 1; + + assert(pd); + assert(o); + assert(o->ref >= 1); + + if (!o->context) + goto finish; + + if (command != PA_COMMAND_REPLY) { + if (pa_context_handle_error(o->context, command, t) < 0) + goto finish; + + success = 0; + } else if (!pa_tagstruct_eof(t)) { + pa_context_fail(o->context, PA_ERR_PROTOCOL); + goto finish; + } + + if (o->callback) { + pa_context_success_cb_t cb = (pa_context_success_cb_t) o->callback; + cb(o->context, success, o->userdata); + } + +finish: + pa_operation_done(o); + pa_operation_unref(o); +} + +pa_operation* pa_context_exit_daemon(pa_context *c, pa_context_success_cb_t cb, void *userdata) { + pa_tagstruct *t; + pa_operation *o; + uint32_t tag; + + assert(c); + assert(c->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_EXIT, &tag); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} + +pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, pa_pdispatch_cb_t internal_cb, pa_operation_cb_t cb, void *userdata) { + pa_tagstruct *t; + pa_operation *o; + uint32_t tag; + + assert(c); + assert(c->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + + o = pa_operation_new(c, NULL, cb, userdata); + + t = pa_tagstruct_command(c, command, &tag); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, internal_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} + +pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) { + pa_tagstruct *t; + pa_operation *o; + uint32_t tag; + + assert(c); + assert(c->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_SET_DEFAULT_SINK, &tag); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} + +pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) { + pa_tagstruct *t; + pa_operation *o; + uint32_t tag; + + assert(c); + assert(c->ref >= 1); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_SET_DEFAULT_SOURCE, &tag); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} + +int pa_context_is_local(pa_context *c) { + assert(c); + + return c->local; +} + +pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) { + pa_tagstruct *t; + pa_operation *o; + uint32_t tag; + + assert(c); + assert(c->ref >= 1); + assert(name); + + PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); + + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); + + t = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag); + pa_tagstruct_puts(t, name); + pa_pstream_send_tagstruct(c->pstream, t); + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref); + + return o; +} + +const char* pa_get_library_version(void) { + return PACKAGE_VERSION; +} + +const char* pa_context_get_server(pa_context *c) { + assert(c); + assert(c->ref >= 1); + + if (!c->server) + return NULL; + + if (*c->server == '{') { + char *e = strchr(c->server+1, '}'); + return e ? e+1 : c->server; + } + + return c->server; +} + +uint32_t pa_context_get_protocol_version(PA_GCC_UNUSED pa_context *c) { + return PA_PROTOCOL_VERSION; +} + +uint32_t pa_context_get_server_protocol_version(pa_context *c) { + assert(c); + assert(c->ref >= 1); + + return c->version; +} + +pa_tagstruct *pa_tagstruct_command(pa_context *c, uint32_t command, uint32_t *tag) { + pa_tagstruct *t; + + assert(c); + assert(tag); + + t = pa_tagstruct_new(NULL, 0); + pa_tagstruct_putu32(t, command); + pa_tagstruct_putu32(t, *tag = c->ctag++); + + return t; +} -- cgit From b8f9ae00f341c936eb27dd51d307f99682a09685 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 14 Jul 2006 23:06:44 +0000 Subject: remove checking for SIGPIPE blocking from client code. Because we use send(,,MSG_NOSIGNAL) for most socket writes now the reason for SIGPIPE blocking is no longer give. We keep this check for the server side however, because pipes create SIGPIPE too but cannot be used with MSG_NOSIGNAL. Some modules use pipes for internal and external communication. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1086 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src/pulse/context.c') diff --git a/src/pulse/context.c b/src/pulse/context.c index 648024c3..5724765b 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -132,10 +132,6 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { memset(&c->spawn_api, 0, sizeof(c->spawn_api)); c->do_autospawn = 0; -#ifdef SIGPIPE - pa_check_signal_is_blocked(SIGPIPE); -#endif - c->conf = pa_client_conf_new(); pa_client_conf_load(c->conf, NULL); #ifdef HAVE_X11 -- cgit From 4b352e5fac5ff546315139f7b791074261544f66 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Mon, 17 Jul 2006 11:26:29 +0000 Subject: Restore SIGPIPE warning when the platform doesn't have MSG_NOSIGNAL. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1097 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/pulse/context.c') diff --git a/src/pulse/context.c b/src/pulse/context.c index 5724765b..228053bc 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -132,6 +132,12 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { memset(&c->spawn_api, 0, sizeof(c->spawn_api)); c->do_autospawn = 0; +#ifndef MSG_NOSIGNAL +#ifdef SIGPIPE + pa_check_signal_is_blocked(SIGPIPE); +#endif +#endif + c->conf = pa_client_conf_new(); pa_client_conf_load(c->conf, NULL); #ifdef HAVE_X11 -- cgit From 9c87a65ce91c38b60c19ae108a51a2e8ce46a85c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 19 Jul 2006 17:44:19 +0000 Subject: * add new --system command line parameter to the daemon for running PulseAudio as system-wide instance * add PA_ prefixes to all global #defines * modify auth-by-creds: define a new group "pulse-access" which is used for authentication * add proper privilige dropping when running in --system mode * create runtime directory once on startup and not by each module seperately git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1105 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'src/pulse/context.c') diff --git a/src/pulse/context.c b/src/pulse/context.c index 228053bc..a25e2f78 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -33,6 +33,8 @@ #include #include #include +#include +#include #ifdef HAVE_SYS_WAIT_H #include @@ -270,7 +272,7 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) { pa_context_fail(c, PA_ERR_CONNECTIONTERMINATED); } -static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const void *creds, void *userdata) { +static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const struct ucred *creds, void *userdata) { pa_context *c = userdata; assert(p); @@ -420,7 +422,23 @@ static void setup_context(pa_context *c, pa_iochannel *io) { t = pa_tagstruct_command(c, PA_COMMAND_AUTH, &tag); pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION); pa_tagstruct_put_arbitrary(t, c->conf->cookie, sizeof(c->conf->cookie)); - pa_pstream_send_tagstruct_with_creds(c->pstream, t, 1); + +#ifdef SCM_CREDENTIALS +{ + struct ucred ucred; + + ucred.pid = getpid(); + ucred.uid = getuid(); + + if ((ucred.gid = pa_get_gid_of_group(PA_ACCESS_GROUP)) == (gid_t) -1) + ucred.gid = getgid(); + + pa_pstream_send_tagstruct_with_creds(c->pstream, t, &ucred); +} +#else + pa_pstream_send_tagstruct_with_creds(c->pstream, t, NULL); +#endif + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c, NULL); pa_context_set_state(c, PA_CONTEXT_AUTHORIZING); @@ -680,7 +698,7 @@ int pa_context_connect( char lf[PATH_MAX]; pa_runtime_path(AUTOSPAWN_LOCK, lf, sizeof(lf)); - pa_make_secure_parent_dir(lf); + pa_make_secure_parent_dir(lf, 0700, getuid(), getgid()); assert(c->autospawn_lock_fd <= 0); c->autospawn_lock_fd = pa_lock_lockfile(lf); -- cgit From 340803b30c154ead29795454416592ff9d0e0df2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 19 Jul 2006 18:14:14 +0000 Subject: use access group dedclared in ~/.pulse/client.conf instead of PA_ACCESS_GROUP git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1108 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/pulse/context.c') diff --git a/src/pulse/context.c b/src/pulse/context.c index a25e2f78..f6452d4e 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -430,7 +430,7 @@ static void setup_context(pa_context *c, pa_iochannel *io) { ucred.pid = getpid(); ucred.uid = getuid(); - if ((ucred.gid = pa_get_gid_of_group(PA_ACCESS_GROUP)) == (gid_t) -1) + if ((ucred.gid = pa_get_gid_of_group(c->conf->access_group)) == (gid_t) -1) ucred.gid = getgid(); pa_pstream_send_tagstruct_with_creds(c->pstream, t, &ucred); -- cgit From a382492204ad3588c0c837e120e5bc31578df72a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 19 Jul 2006 21:48:35 +0000 Subject: * add new function pa_check_in_group() * abstract credential APis a little bit by introducing HAVE_CREDS and a structure pa_creds * rework credential authentication * fix module-volume-restore and friends for usage in system-wide instance * remove loopback= argument from moulde-*-protocol-tcp since it is a superset of listen= and usually a bad idea anyway since the user shouldn't load the TCP module at all if he doesn't want remote access * rename a few variables in the jack modules to make sure they don't conflict with symbols defined in the system headers * add server address for system-wide daemons to the default server list for the the client libs * update todo git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1109 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'src/pulse/context.c') diff --git a/src/pulse/context.c b/src/pulse/context.c index f6452d4e..0150204c 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -62,6 +62,7 @@ #include #include #include +#include #include "internal.h" @@ -272,7 +273,7 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) { pa_context_fail(c, PA_ERR_CONNECTIONTERMINATED); } -static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const struct ucred *creds, void *userdata) { +static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) { pa_context *c = userdata; assert(p); @@ -423,15 +424,17 @@ static void setup_context(pa_context *c, pa_iochannel *io) { pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION); pa_tagstruct_put_arbitrary(t, c->conf->cookie, sizeof(c->conf->cookie)); -#ifdef SCM_CREDENTIALS +#ifdef HAVE_CREDS { - struct ucred ucred; + pa_creds ucred; + gid_t g; - ucred.pid = getpid(); ucred.uid = getuid(); + ucred.gid = getgid(); - if ((ucred.gid = pa_get_gid_of_group(c->conf->access_group)) == (gid_t) -1) - ucred.gid = getgid(); + if ((g = pa_get_gid_of_group(c->conf->access_group)) != (gid_t) -1) + if (pa_check_in_group(g) > 0) + ucred.gid = g; pa_pstream_send_tagstruct_with_creds(c->pstream, t, &ucred); } @@ -690,7 +693,12 @@ int pa_context_connect( } c->server_list = pa_strlist_prepend(c->server_list, "tcp6:localhost"); - c->server_list = pa_strlist_prepend(c->server_list, "localhost"); + c->server_list = pa_strlist_prepend(c->server_list, "tcp4:localhost"); + + /* The system wide instance */ + c->server_list = pa_strlist_prepend(c->server_list, PA_SYSTEM_RUNTIME_PATH "/" PA_NATIVE_DEFAULT_UNIX_SOCKET); + + /* The per-user instance */ c->server_list = pa_strlist_prepend(c->server_list, pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET, ufn, sizeof(ufn))); /* Wrap the connection attempts in a single transaction for sane autospawn locking */ -- cgit From 7ba93ebae21742522bfe430e229a859370a888d1 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 20 Jul 2006 00:13:12 +0000 Subject: Protect platform dependent headers with ifdefs. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1112 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/pulse/context.c') diff --git a/src/pulse/context.c b/src/pulse/context.c index 0150204c..efc1685b 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -33,8 +33,6 @@ #include #include #include -#include -#include #ifdef HAVE_SYS_WAIT_H #include @@ -43,6 +41,9 @@ #ifdef HAVE_SYS_SOCKET_H #include #endif +#ifdef HAVE_SYS_UN_H +#include +#endif #ifdef HAVE_NETDB_H #include #endif -- cgit From a3e7595ac179ca32bc5c876b25a4e80171c3d917 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 20 Jul 2006 00:21:50 +0000 Subject: Make -1 mean "current group/user" so that some platform dependent calls can be centralised. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1113 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/pulse/context.c') diff --git a/src/pulse/context.c b/src/pulse/context.c index efc1685b..30a257fe 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -707,7 +707,7 @@ int pa_context_connect( char lf[PATH_MAX]; pa_runtime_path(AUTOSPAWN_LOCK, lf, sizeof(lf)); - pa_make_secure_parent_dir(lf, 0700, getuid(), getgid()); + pa_make_secure_parent_dir(lf, 0700, (uid_t)-1, (gid_t)-1); assert(c->autospawn_lock_fd <= 0); c->autospawn_lock_fd = pa_lock_lockfile(lf); -- cgit From da1ec271bbc1907c32811cd61f41390a7d3ac1e8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Jul 2006 21:28:44 +0000 Subject: remove configurable client access group, since can never work on Linux anway, since SCM_CREDENTAILS doesn't allow sending supplementary GIDs git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1127 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src/pulse/context.c') diff --git a/src/pulse/context.c b/src/pulse/context.c index 30a257fe..34f517f0 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -428,14 +428,9 @@ static void setup_context(pa_context *c, pa_iochannel *io) { #ifdef HAVE_CREDS { pa_creds ucred; - gid_t g; ucred.uid = getuid(); ucred.gid = getgid(); - - if ((g = pa_get_gid_of_group(c->conf->access_group)) != (gid_t) -1) - if (pa_check_in_group(g) > 0) - ucred.gid = g; pa_pstream_send_tagstruct_with_creds(c->pstream, t, &ucred); } -- cgit From 0e436a6926af56f37a74a03bb5e143e078ca0d55 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Aug 2006 19:55:18 +0000 Subject: Rework memory management to allow shared memory data transfer. The central idea is to allocate all audio memory blocks from a per-process memory pool which is available as read-only SHM segment to other local processes. Then, instead of writing the actual audio data to the socket just write references to this shared memory pool. To work optimally all memory blocks should now be of type PA_MEMBLOCK_POOL or PA_MEMBLOCK_POOL_EXTERNAL. The function pa_memblock_new() now generates memory blocks of this type by default. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1266 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/pulse/context.c') diff --git a/src/pulse/context.c b/src/pulse/context.c index 34f517f0..b3530542 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -128,7 +128,7 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { c->subscribe_callback = NULL; c->subscribe_userdata = NULL; - c->memblock_stat = pa_memblock_stat_new(); + c->mempool = pa_mempool_new(1); c->local = -1; c->server_list = NULL; c->server = NULL; @@ -177,7 +177,7 @@ static void context_free(pa_context *c) { if (c->playback_streams) pa_dynarray_free(c->playback_streams, NULL, NULL); - pa_memblock_stat_unref(c->memblock_stat); + pa_mempool_free(c->mempool); if (c->conf) pa_client_conf_free(c->conf); @@ -407,7 +407,9 @@ static void setup_context(pa_context *c, pa_iochannel *io) { pa_context_ref(c); assert(!c->pstream); - c->pstream = pa_pstream_new(c->mainloop, io, c->memblock_stat); + c->pstream = pa_pstream_new(c->mainloop, io, c->mempool); + + pa_pstream_use_shm(c->pstream, 1); pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); -- cgit From e385d93e5aad6a6fce754c00c804ff1d6a6746d4 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Aug 2006 21:38:40 +0000 Subject: remove all occurences of pa_logXXX(__FILE__": and replace them by pa_logXXX(" git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1272 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/pulse/context.c') diff --git a/src/pulse/context.c b/src/pulse/context.c index b3530542..df627ee6 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -462,7 +462,7 @@ static int context_connect_spawn(pa_context *c) { pa_context_ref(c); if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { - pa_log(__FILE__": socketpair(): %s", pa_cstrerror(errno)); + pa_log("socketpair(): %s", pa_cstrerror(errno)); pa_context_fail(c, PA_ERR_INTERNAL); goto fail; } @@ -476,7 +476,7 @@ static int context_connect_spawn(pa_context *c) { c->spawn_api.prefork(); if ((pid = fork()) < 0) { - pa_log(__FILE__": fork(): %s", pa_cstrerror(errno)); + pa_log("fork(): %s", pa_cstrerror(errno)); pa_context_fail(c, PA_ERR_INTERNAL); if (c->spawn_api.postfork) @@ -532,7 +532,7 @@ static int context_connect_spawn(pa_context *c) { c->spawn_api.postfork(); if (r < 0) { - pa_log(__FILE__": waitpid(): %s", pa_cstrerror(errno)); + pa_log("waitpid(): %s", pa_cstrerror(errno)); pa_context_fail(c, PA_ERR_INTERNAL); goto fail; } else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { @@ -594,7 +594,7 @@ static int try_next_connection(pa_context *c) { goto finish; } - pa_log_debug(__FILE__": Trying to connect to %s...", u); + pa_log_debug("Trying to connect to %s...", u); pa_xfree(c->server); c->server = pa_xstrdup(u); -- cgit From 40875d6d05d00eb54265907be36b76ed7fc590ea Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 18 Aug 2006 23:45:23 +0000 Subject: enable SHM support on the client side only if both the client and the server run as the same user and the server supports it git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1278 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) (limited to 'src/pulse/context.c') diff --git a/src/pulse/context.c b/src/pulse/context.c index df627ee6..55b49a79 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -129,7 +129,7 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { c->subscribe_userdata = NULL; c->mempool = pa_mempool_new(1); - c->local = -1; + c->is_local = -1; c->server_list = NULL; c->server = NULL; c->autospawn_lock_fd = -1; @@ -376,6 +376,21 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t goto finish; } + /* Enable shared memory support if possible */ + if (c->version >= 10 && + pa_mempool_is_shared(c->mempool) && + c->is_local) { + + /* Only enable SHM if both sides are owned by the same + * user. This is a security measure because otherwise + * data private to the user might leak. */ + + const pa_creds *creds; + if ((creds = pa_pdispatch_creds(pd))) + if (getuid() == creds->uid) + pa_pstream_use_shm(c->pstream, 1); + } + reply = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag); pa_tagstruct_puts(reply, c->name); pa_pstream_send_tagstruct(c->pstream, reply); @@ -409,8 +424,6 @@ static void setup_context(pa_context *c, pa_iochannel *io) { assert(!c->pstream); c->pstream = pa_pstream_new(c->mainloop, io, c->mempool); - pa_pstream_use_shm(c->pstream, 1); - pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); @@ -431,13 +444,16 @@ static void setup_context(pa_context *c, pa_iochannel *io) { { pa_creds ucred; + if (pa_iochannel_creds_supported(io)) + pa_iochannel_creds_enable(io); + ucred.uid = getuid(); ucred.gid = getgid(); pa_pstream_send_tagstruct_with_creds(c->pstream, t, &ucred); } #else - pa_pstream_send_tagstruct_with_creds(c->pstream, t, NULL); + pa_pstream_send_tagstruct(c->pstream, t, NULL); #endif pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c, NULL); @@ -542,7 +558,7 @@ static int context_connect_spawn(pa_context *c) { close(fds[1]); - c->local = 1; + c->is_local = 1; io = pa_iochannel_new(c->mainloop, fds[0], fds[0]); @@ -602,7 +618,7 @@ static int try_next_connection(pa_context *c) { if (!(c->client = pa_socket_client_new_string(c->mainloop, u, PA_NATIVE_DEFAULT_PORT))) continue; - c->local = pa_socket_client_is_local(c->client); + c->is_local = pa_socket_client_is_local(c->client); pa_socket_client_set_callback(c->client, on_connection, c); break; } @@ -938,7 +954,7 @@ pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_ int pa_context_is_local(pa_context *c) { assert(c); - return c->local; + return c->is_local; } pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) { -- cgit From d785b8fa877b829d9d38082968b35117f7c9d9ec Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 19 Aug 2006 01:18:30 +0000 Subject: add new "disable-shm" option to client.conf git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1284 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/pulse/context.c') diff --git a/src/pulse/context.c b/src/pulse/context.c index 55b49a79..b4641590 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -128,7 +128,6 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { c->subscribe_callback = NULL; c->subscribe_userdata = NULL; - c->mempool = pa_mempool_new(1); c->is_local = -1; c->server_list = NULL; c->server = NULL; @@ -149,6 +148,8 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { #endif pa_client_conf_env(c->conf); + c->mempool = pa_mempool_new(!c->conf->disable_shm); + return c; } -- cgit From 25c0640ac2206872f76df70368180c74153581e3 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 22 Aug 2006 07:12:50 +0000 Subject: Add an ifdef for when we do not have creds. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1307 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/pulse/context.c') diff --git a/src/pulse/context.c b/src/pulse/context.c index b4641590..f2af4727 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -385,11 +385,13 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t /* Only enable SHM if both sides are owned by the same * user. This is a security measure because otherwise * data private to the user might leak. */ - + +#ifdef HAVE_CREDS const pa_creds *creds; if ((creds = pa_pdispatch_creds(pd))) if (getuid() == creds->uid) pa_pstream_use_shm(c->pstream, 1); +#endif } reply = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag); -- cgit From 8a16c731514a7d25e37ea70080e4c3d42fb5e5d4 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 22 Aug 2006 07:18:07 +0000 Subject: Fix call to pa_pstream_send_tagstruct(). git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1308 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/pulse/context.c') diff --git a/src/pulse/context.c b/src/pulse/context.c index f2af4727..2f9106a5 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -456,7 +456,7 @@ static void setup_context(pa_context *c, pa_iochannel *io) { pa_pstream_send_tagstruct_with_creds(c->pstream, t, &ucred); } #else - pa_pstream_send_tagstruct(c->pstream, t, NULL); + pa_pstream_send_tagstruct(c->pstream, t); #endif pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c, NULL); -- cgit From 095f35725d644e0284c4b2d99b6fab71290eaeaa Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 22 Aug 2006 15:36:37 +0000 Subject: Proceed with connect even when no cookie is loaded. Allows you to connect to server which do not require a cookie under all circumstances. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1324 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'src/pulse/context.c') diff --git a/src/pulse/context.c b/src/pulse/context.c index 2f9106a5..b700657b 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -434,10 +434,8 @@ static void setup_context(pa_context *c, pa_iochannel *io) { assert(!c->pdispatch); c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); - if (!c->conf->cookie_valid) { - pa_context_fail(c, PA_ERR_AUTHKEY); - goto finish; - } + if (!c->conf->cookie_valid) + pa_log_warn("No cookie loaded. Attempting to connect without."); t = pa_tagstruct_command(c, PA_COMMAND_AUTH, &tag); pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION); @@ -463,8 +461,6 @@ static void setup_context(pa_context *c, pa_iochannel *io) { pa_context_set_state(c, PA_CONTEXT_AUTHORIZING); -finish: - pa_context_unref(c); } -- cgit From 40ecf869d0f77a3af2ce59bc060c4bccd2baec25 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 6 Sep 2006 22:19:54 +0000 Subject: don't hit an assert in the client if posix shm is not available git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1376 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'src/pulse/context.c') diff --git a/src/pulse/context.c b/src/pulse/context.c index b700657b..a458c6b1 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -98,6 +98,8 @@ static void unlock_autospawn_lock_file(pa_context *c) { } } +static void context_free(pa_context *c); + pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { pa_context *c; @@ -148,7 +150,16 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { #endif pa_client_conf_env(c->conf); - c->mempool = pa_mempool_new(!c->conf->disable_shm); + if (!(c->mempool = pa_mempool_new(!c->conf->disable_shm))) { + + if (!c->conf->disable_shm) + c->mempool = pa_mempool_new(0); + + if (!c->mempool) { + context_free(c); + return NULL; + } + } return c; } @@ -178,7 +189,8 @@ static void context_free(pa_context *c) { if (c->playback_streams) pa_dynarray_free(c->playback_streams, NULL, NULL); - pa_mempool_free(c->mempool); + if (c->mempool) + pa_mempool_free(c->mempool); if (c->conf) pa_client_conf_free(c->conf); -- cgit From 521daf6f0ac4fa6a2fbfb5d523c0c743342dca2b Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Thu, 4 Jan 2007 13:43:45 +0000 Subject: Huge trailing whitespace cleanup. Let's keep the tree pure from here on, mmmkay? git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1418 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 156 ++++++++++++++++++++++++++-------------------------- 1 file changed, 78 insertions(+), 78 deletions(-) (limited to 'src/pulse/context.c') diff --git a/src/pulse/context.c b/src/pulse/context.c index a458c6b1..7ef43b30 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -2,17 +2,17 @@ /*** This file is part of PulseAudio. - + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -88,11 +88,11 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { static void unlock_autospawn_lock_file(pa_context *c) { assert(c); - + if (c->autospawn_lock_fd >= 0) { char lf[PATH_MAX]; pa_runtime_path(AUTOSPAWN_LOCK, lf, sizeof(lf)); - + pa_unlock_lockfile(lf, c->autospawn_lock_fd); c->autospawn_lock_fd = -1; } @@ -102,10 +102,10 @@ static void context_free(pa_context *c); pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { pa_context *c; - + assert(mainloop); assert(name); - + c = pa_xnew(pa_context, 1); c->ref = 1; c->name = pa_xstrdup(name); @@ -118,7 +118,7 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { PA_LLIST_HEAD_INIT(pa_stream, c->streams); PA_LLIST_HEAD_INIT(pa_operation, c->operations); - + c->error = PA_OK; c->state = PA_CONTEXT_UNCONNECTED; c->ctag = 0; @@ -138,7 +138,7 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { c->do_autospawn = 0; #ifndef MSG_NOSIGNAL -#ifdef SIGPIPE +#ifdef SIGPIPE pa_check_signal_is_blocked(SIGPIPE); #endif #endif @@ -183,7 +183,7 @@ static void context_free(pa_context *c) { pa_pstream_close(c->pstream); pa_pstream_unref(c->pstream); } - + if (c->record_streams) pa_dynarray_free(c->record_streams, NULL, NULL); if (c->playback_streams) @@ -196,7 +196,7 @@ static void context_free(pa_context *c) { pa_client_conf_free(c->conf); pa_strlist_free(c->server_list); - + pa_xfree(c->name); pa_xfree(c->server); pa_xfree(c); @@ -205,7 +205,7 @@ static void context_free(pa_context *c) { pa_context* pa_context_ref(pa_context *c) { assert(c); assert(c->ref >= 1); - + c->ref++; return c; } @@ -221,7 +221,7 @@ void pa_context_unref(pa_context *c) { void pa_context_set_state(pa_context *c, pa_context_state_t st) { assert(c); assert(c->ref >= 1); - + if (c->state == st) return; @@ -233,7 +233,7 @@ void pa_context_set_state(pa_context *c, pa_context_state_t st) { if (st == PA_CONTEXT_FAILED || st == PA_CONTEXT_TERMINATED) { pa_stream *s; - + s = c->streams ? pa_stream_ref(c->streams) : NULL; while (s) { pa_stream *n = s->next ? pa_stream_ref(s->next) : NULL; @@ -245,13 +245,13 @@ void pa_context_set_state(pa_context *c, pa_context_state_t st) { if (c->pdispatch) pa_pdispatch_unref(c->pdispatch); c->pdispatch = NULL; - + if (c->pstream) { pa_pstream_close(c->pstream); pa_pstream_unref(c->pstream); } c->pstream = NULL; - + if (c->client) pa_socket_client_unref(c->client); c->client = NULL; @@ -263,7 +263,7 @@ void pa_context_set_state(pa_context *c, pa_context_state_t st) { void pa_context_fail(pa_context *c, int error) { assert(c); assert(c->ref >= 1); - + pa_context_set_error(c, error); pa_context_set_state(c, PA_CONTEXT_FAILED); } @@ -283,19 +283,19 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) { assert(p); assert(c); - + pa_context_fail(c, PA_ERR_CONNECTIONTERMINATED); } static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) { pa_context *c = userdata; - + assert(p); assert(packet); assert(c); pa_context_ref(c); - + if (pa_pdispatch_run(c->pdispatch, packet, creds, c) < 0) pa_context_fail(c, PA_ERR_PROTOCOL); @@ -305,7 +305,7 @@ static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_c static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata) { pa_context *c = userdata; pa_stream *s; - + assert(p); assert(chunk); assert(chunk->memblock); @@ -321,7 +321,7 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o pa_memblockq_seek(s->record_memblockq, offset, seek); pa_memblockq_push_align(s->record_memblockq, chunk); - + if (s->read_callback) { size_t l; @@ -339,11 +339,11 @@ int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t) { if (command == PA_COMMAND_ERROR) { assert(t); - + if (pa_tagstruct_getu32(t, &c->error) < 0) { pa_context_fail(c, PA_ERR_PROTOCOL); return -1; - + } } else if (command == PA_COMMAND_TIMEOUT) c->error = PA_ERR_TIMEOUT; @@ -357,15 +357,15 @@ int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t) { static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_context *c = userdata; - + assert(pd); assert(c); assert(c->state == PA_CONTEXT_AUTHORIZING || c->state == PA_CONTEXT_SETTING_NAME); pa_context_ref(c); - + if (command != PA_COMMAND_REPLY) { - + if (pa_context_handle_error(c, command, t) < 0) pa_context_fail(c, PA_ERR_PROTOCOL); @@ -398,7 +398,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t * user. This is a security measure because otherwise * data private to the user might leak. */ -#ifdef HAVE_CREDS +#ifdef HAVE_CREDS const pa_creds *creds; if ((creds = pa_pdispatch_creds(pd))) if (getuid() == creds->uid) @@ -418,7 +418,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t case PA_CONTEXT_SETTING_NAME : pa_context_set_state(c, PA_CONTEXT_READY); break; - + default: assert(0); } @@ -430,12 +430,12 @@ finish: static void setup_context(pa_context *c, pa_iochannel *io) { pa_tagstruct *t; uint32_t tag; - + assert(c); assert(io); pa_context_ref(c); - + assert(!c->pstream); c->pstream = pa_pstream_new(c->mainloop, io, c->mempool); @@ -462,13 +462,13 @@ static void setup_context(pa_context *c, pa_iochannel *io) { ucred.uid = getuid(); ucred.gid = getgid(); - + pa_pstream_send_tagstruct_with_creds(c->pstream, t, &ucred); } #else pa_pstream_send_tagstruct(c->pstream, t); #endif - + pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c, NULL); pa_context_set_state(c, PA_CONTEXT_AUTHORIZING); @@ -487,7 +487,7 @@ static int context_connect_spawn(pa_context *c) { pa_iochannel *io; pa_context_ref(c); - + if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { pa_log("socketpair(): %s", pa_cstrerror(errno)); pa_context_fail(c, PA_ERR_INTERNAL); @@ -495,7 +495,7 @@ static int context_connect_spawn(pa_context *c) { } pa_fd_set_cloexec(fds[0], 1); - + pa_socket_low_delay(fds[0]); pa_socket_low_delay(fds[1]); @@ -508,7 +508,7 @@ static int context_connect_spawn(pa_context *c) { if (c->spawn_api.postfork) c->spawn_api.postfork(); - + goto fail; } else if (!pid) { /* Child */ @@ -521,17 +521,17 @@ static int context_connect_spawn(pa_context *c) { /* Not required, since fds[0] has CLOEXEC enabled anyway */ close(fds[0]); - + if (c->spawn_api.atfork) c->spawn_api.atfork(); /* Setup argv */ n = 0; - + argv[n++] = c->conf->daemon_binary; argv[n++] = "--daemonize=yes"; - + snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]); argv[n++] = strdup(t); @@ -540,7 +540,7 @@ static int context_connect_spawn(pa_context *c) { if (!(a = pa_split_spaces(c->conf->extra_arguments, &state))) break; - + argv[n++] = a; } @@ -549,7 +549,7 @@ static int context_connect_spawn(pa_context *c) { execv(argv[0], (char * const *) argv); _exit(1); #undef MAX_ARGS - } + } /* Parent */ @@ -557,7 +557,7 @@ static int context_connect_spawn(pa_context *c) { if (c->spawn_api.postfork) c->spawn_api.postfork(); - + if (r < 0) { pa_log("waitpid(): %s", pa_cstrerror(errno)); pa_context_fail(c, PA_ERR_INTERNAL); @@ -570,7 +570,7 @@ static int context_connect_spawn(pa_context *c) { close(fds[1]); c->is_local = 1; - + io = pa_iochannel_new(c->mainloop, fds[0], fds[0]); setup_context(c, io); @@ -598,16 +598,16 @@ fail: static int try_next_connection(pa_context *c) { char *u = NULL; int r = -1; - + assert(c); assert(!c->client); for (;;) { pa_xfree(u); u = NULL; - + c->server_list = pa_strlist_pop(c->server_list, &u); - + if (!u) { #ifndef OS_IS_WIN32 @@ -616,19 +616,19 @@ static int try_next_connection(pa_context *c) { goto finish; } #endif - + pa_context_fail(c, PA_ERR_CONNECTIONREFUSED); goto finish; } - - pa_log_debug("Trying to connect to %s...", u); + + pa_log_debug("Trying to connect to %s...", u); pa_xfree(c->server); c->server = pa_xstrdup(u); if (!(c->client = pa_socket_client_new_string(c->mainloop, u, PA_NATIVE_DEFAULT_PORT))) continue; - + c->is_local = pa_socket_client_is_local(c->client); pa_socket_client_set_callback(c->client, on_connection, c); break; @@ -638,13 +638,13 @@ static int try_next_connection(pa_context *c) { finish: pa_xfree(u); - + return r; } static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata) { pa_context *c = userdata; - + assert(client); assert(c); assert(c->state == PA_CONTEXT_CONNECTING); @@ -677,9 +677,9 @@ int pa_context_connect( const char *server, pa_context_flags_t flags, const pa_spawn_api *api) { - + int r = -1; - + assert(c); assert(c->ref >= 1); @@ -693,7 +693,7 @@ int pa_context_connect( pa_context_ref(c); assert(!c->server_list); - + if (server) { if (!(c->server_list = pa_strlist_parse(server))) { pa_context_fail(c, PA_ERR_INVALIDSERVER); @@ -704,7 +704,7 @@ int pa_context_connect( char ufn[PATH_MAX]; /* Prepend in reverse order */ - + if ((d = getenv("DISPLAY"))) { char *e; d = pa_xstrdup(d); @@ -716,7 +716,7 @@ int pa_context_connect( pa_xfree(d); } - + c->server_list = pa_strlist_prepend(c->server_list, "tcp6:localhost"); c->server_list = pa_strlist_prepend(c->server_list, "tcp4:localhost"); @@ -744,38 +744,38 @@ int pa_context_connect( pa_context_set_state(c, PA_CONTEXT_CONNECTING); r = try_next_connection(c); - + finish: pa_context_unref(c); - + return r; } void pa_context_disconnect(pa_context *c) { assert(c); assert(c->ref >= 1); - + pa_context_set_state(c, PA_CONTEXT_TERMINATED); } pa_context_state_t pa_context_get_state(pa_context *c) { assert(c); assert(c->ref >= 1); - + return c->state; } int pa_context_errno(pa_context *c) { assert(c); assert(c->ref >= 1); - + return c->error; } void pa_context_set_state_callback(pa_context *c, pa_context_notify_cb_t cb, void *userdata) { assert(c); assert(c->ref >= 1); - + c->state_callback = cb; c->state_userdata = userdata; } @@ -807,7 +807,7 @@ static void pstream_drain_callback(PA_GCC_UNUSED pa_pstream *s, void *userdata) static void set_dispatch_callbacks(pa_operation *o) { int done = 1; - + assert(o); assert(o->ref >= 1); assert(o->context); @@ -816,7 +816,7 @@ static void set_dispatch_callbacks(pa_operation *o) { pa_pstream_set_drain_callback(o->context->pstream, NULL, NULL); pa_pdispatch_set_drain_callback(o->context->pdispatch, NULL, NULL); - + if (pa_pdispatch_is_pending(o->context->pdispatch)) { pa_pdispatch_set_drain_callback(o->context->pdispatch, pdispatch_drain_callback, o); done = 0; @@ -832,7 +832,7 @@ static void set_dispatch_callbacks(pa_operation *o) { pa_context_notify_cb_t cb = (pa_context_notify_cb_t) o->callback; cb(o->context, o->userdata); } - + pa_operation_done(o); pa_operation_unref(o); } @@ -840,13 +840,13 @@ static void set_dispatch_callbacks(pa_operation *o) { pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *userdata) { pa_operation *o; - + assert(c); assert(c->ref >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, pa_context_is_pending(c), PA_ERR_BADSTATE); - + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); set_dispatch_callbacks(pa_operation_ref(o)); @@ -856,7 +856,7 @@ pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *u void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) { pa_operation *o = userdata; int success = 1; - + assert(pd); assert(o); assert(o->ref >= 1); @@ -907,12 +907,12 @@ pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, pa pa_tagstruct *t; pa_operation *o; uint32_t tag; - + assert(c); assert(c->ref >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); - + o = pa_operation_new(c, NULL, cb, userdata); t = pa_tagstruct_command(c, command, &tag); @@ -926,7 +926,7 @@ pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, pa_co pa_tagstruct *t; pa_operation *o; uint32_t tag; - + assert(c); assert(c->ref >= 1); @@ -951,7 +951,7 @@ pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_ assert(c->ref >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); - + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_command(c, PA_COMMAND_SET_DEFAULT_SOURCE, &tag); @@ -964,7 +964,7 @@ pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_ int pa_context_is_local(pa_context *c) { assert(c); - + return c->is_local; } @@ -978,7 +978,7 @@ pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_su assert(name); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); - + o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata); t = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag); @@ -999,12 +999,12 @@ const char* pa_context_get_server(pa_context *c) { if (!c->server) return NULL; - + if (*c->server == '{') { char *e = strchr(c->server+1, '}'); return e ? e+1 : c->server; } - + return c->server; } @@ -1024,7 +1024,7 @@ pa_tagstruct *pa_tagstruct_command(pa_context *c, uint32_t command, uint32_t *ta assert(c); assert(tag); - + t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, command); pa_tagstruct_putu32(t, *tag = c->ctag++); -- cgit From 06211b7c8fd329137ae9003818543912a87d9898 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 13 Feb 2007 15:35:19 +0000 Subject: Add copyright notices to all relevant files. (based on svn log) git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1426 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/pulse/context.c') diff --git a/src/pulse/context.c b/src/pulse/context.c index 7ef43b30..58a5a879 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -3,6 +3,9 @@ /*** This file is part of PulseAudio. + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, -- cgit From a67c21f093202f142438689d3f7cfbdf4ea82eea Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 28 Oct 2007 19:13:50 +0000 Subject: merge 'lennart' branch back into trunk. git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@1971 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 198 ++++++++++++++++++++++++++-------------------------- 1 file changed, 98 insertions(+), 100 deletions(-) (limited to 'src/pulse/context.c') diff --git a/src/pulse/context.c b/src/pulse/context.c index 58a5a879..805cd44e 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -27,7 +27,6 @@ #endif #include -#include #include #include #include @@ -67,6 +66,7 @@ #include #include #include +#include #include "internal.h" @@ -90,7 +90,7 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { }; static void unlock_autospawn_lock_file(pa_context *c) { - assert(c); + pa_assert(c); if (c->autospawn_lock_fd >= 0) { char lf[PATH_MAX]; @@ -106,11 +106,11 @@ static void context_free(pa_context *c); pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { pa_context *c; - assert(mainloop); - assert(name); + pa_assert(mainloop); + pa_assert(name); c = pa_xnew(pa_context, 1); - c->ref = 1; + PA_REFCNT_INIT(c); c->name = pa_xstrdup(name); c->mainloop = mainloop; c->client = NULL; @@ -168,7 +168,7 @@ pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) { } static void context_free(pa_context *c) { - assert(c); + pa_assert(c); unlock_autospawn_lock_file(c); @@ -183,7 +183,7 @@ static void context_free(pa_context *c) { if (c->pdispatch) pa_pdispatch_unref(c->pdispatch); if (c->pstream) { - pa_pstream_close(c->pstream); + pa_pstream_unlink(c->pstream); pa_pstream_unref(c->pstream); } @@ -206,24 +206,24 @@ static void context_free(pa_context *c) { } pa_context* pa_context_ref(pa_context *c) { - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); - c->ref++; + PA_REFCNT_INC(c); return c; } void pa_context_unref(pa_context *c) { - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); - if (--c->ref <= 0) + if (PA_REFCNT_DEC(c) <= 0) context_free(c); } void pa_context_set_state(pa_context *c, pa_context_state_t st) { - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); if (c->state == st) return; @@ -250,7 +250,7 @@ void pa_context_set_state(pa_context *c, pa_context_state_t st) { c->pdispatch = NULL; if (c->pstream) { - pa_pstream_close(c->pstream); + pa_pstream_unlink(c->pstream); pa_pstream_unref(c->pstream); } c->pstream = NULL; @@ -264,16 +264,16 @@ void pa_context_set_state(pa_context *c, pa_context_state_t st) { } void pa_context_fail(pa_context *c, int error) { - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); pa_context_set_error(c, error); pa_context_set_state(c, PA_CONTEXT_FAILED); } int pa_context_set_error(pa_context *c, int error) { - assert(error >= 0); - assert(error < PA_ERR_MAX); + pa_assert(error >= 0); + pa_assert(error < PA_ERR_MAX); if (c) c->error = error; @@ -284,8 +284,8 @@ int pa_context_set_error(pa_context *c, int error) { static void pstream_die_callback(pa_pstream *p, void *userdata) { pa_context *c = userdata; - assert(p); - assert(c); + pa_assert(p); + pa_assert(c); pa_context_fail(c, PA_ERR_CONNECTIONTERMINATED); } @@ -293,9 +293,9 @@ static void pstream_die_callback(pa_pstream *p, void *userdata) { static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) { pa_context *c = userdata; - assert(p); - assert(packet); - assert(c); + pa_assert(p); + pa_assert(packet); + pa_assert(c); pa_context_ref(c); @@ -309,18 +309,19 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o pa_context *c = userdata; pa_stream *s; - assert(p); - assert(chunk); - assert(chunk->memblock); - assert(chunk->length); - assert(c); - assert(c->ref >= 1); + pa_assert(p); + pa_assert(chunk); + pa_assert(chunk->memblock); + pa_assert(chunk->length); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); pa_context_ref(c); if ((s = pa_dynarray_get(c->record_streams, channel))) { - assert(seek == PA_SEEK_RELATIVE && offset == 0); + pa_assert(seek == PA_SEEK_RELATIVE); + pa_assert(offset == 0); pa_memblockq_seek(s->record_memblockq, offset, seek); pa_memblockq_push_align(s->record_memblockq, chunk); @@ -337,11 +338,11 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o } int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t) { - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); if (command == PA_COMMAND_ERROR) { - assert(t); + pa_assert(t); if (pa_tagstruct_getu32(t, &c->error) < 0) { pa_context_fail(c, PA_ERR_PROTOCOL); @@ -361,9 +362,9 @@ int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t) { static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_context *c = userdata; - assert(pd); - assert(c); - assert(c->state == PA_CONTEXT_AUTHORIZING || c->state == PA_CONTEXT_SETTING_NAME); + pa_assert(pd); + pa_assert(c); + pa_assert(c->state == PA_CONTEXT_AUTHORIZING || c->state == PA_CONTEXT_SETTING_NAME); pa_context_ref(c); @@ -423,7 +424,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t break; default: - assert(0); + pa_assert(0); } finish: @@ -434,19 +435,19 @@ static void setup_context(pa_context *c, pa_iochannel *io) { pa_tagstruct *t; uint32_t tag; - assert(c); - assert(io); + pa_assert(c); + pa_assert(io); pa_context_ref(c); - assert(!c->pstream); + pa_assert(!c->pstream); c->pstream = pa_pstream_new(c->mainloop, io, c->mempool); pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c); pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c); pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c); - assert(!c->pdispatch); + pa_assert(!c->pdispatch); c->pdispatch = pa_pdispatch_new(c->mainloop, command_table, PA_COMMAND_MAX); if (!c->conf->cookie_valid) @@ -497,10 +498,10 @@ static int context_connect_spawn(pa_context *c) { goto fail; } - pa_fd_set_cloexec(fds[0], 1); + pa_make_fd_cloexec(fds[0]); - pa_socket_low_delay(fds[0]); - pa_socket_low_delay(fds[1]); + pa_make_socket_low_delay(fds[0]); + pa_make_socket_low_delay(fds[1]); if (c->spawn_api.prefork) c->spawn_api.prefork(); @@ -523,7 +524,7 @@ static int context_connect_spawn(pa_context *c) { int n; /* Not required, since fds[0] has CLOEXEC enabled anyway */ - close(fds[0]); + pa_assert_se(pa_close(fds[0]) == 0); if (c->spawn_api.atfork) c->spawn_api.atfork(); @@ -535,7 +536,7 @@ static int context_connect_spawn(pa_context *c) { argv[n++] = c->conf->daemon_binary; argv[n++] = "--daemonize=yes"; - snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]); + pa_snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]); argv[n++] = strdup(t); while (n < MAX_ARGS) { @@ -570,7 +571,7 @@ static int context_connect_spawn(pa_context *c) { goto fail; } - close(fds[1]); + pa_assert_se(pa_close(fds[1]) == 0); c->is_local = 1; @@ -584,10 +585,7 @@ static int context_connect_spawn(pa_context *c) { return 0; fail: - if (fds[0] != -1) - close(fds[0]); - if (fds[1] != -1) - close(fds[1]); + pa_close_pipe(fds); unlock_autospawn_lock_file(c); @@ -602,8 +600,8 @@ static int try_next_connection(pa_context *c) { char *u = NULL; int r = -1; - assert(c); - assert(!c->client); + pa_assert(c); + pa_assert(!c->client); for (;;) { pa_xfree(u); @@ -648,9 +646,9 @@ finish: static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata) { pa_context *c = userdata; - assert(client); - assert(c); - assert(c->state == PA_CONTEXT_CONNECTING); + pa_assert(client); + pa_assert(c); + pa_assert(c->state == PA_CONTEXT_CONNECTING); pa_context_ref(c); @@ -683,8 +681,8 @@ int pa_context_connect( int r = -1; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY(c, c->state == PA_CONTEXT_UNCONNECTED, PA_ERR_BADSTATE); PA_CHECK_VALIDITY(c, !(flags & ~PA_CONTEXT_NOAUTOSPAWN), PA_ERR_INVALID); @@ -695,7 +693,7 @@ int pa_context_connect( pa_context_ref(c); - assert(!c->server_list); + pa_assert(!c->server_list); if (server) { if (!(c->server_list = pa_strlist_parse(server))) { @@ -735,7 +733,7 @@ int pa_context_connect( pa_runtime_path(AUTOSPAWN_LOCK, lf, sizeof(lf)); pa_make_secure_parent_dir(lf, 0700, (uid_t)-1, (gid_t)-1); - assert(c->autospawn_lock_fd <= 0); + pa_assert(c->autospawn_lock_fd <= 0); c->autospawn_lock_fd = pa_lock_lockfile(lf); if (api) @@ -755,37 +753,37 @@ finish: } void pa_context_disconnect(pa_context *c) { - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); pa_context_set_state(c, PA_CONTEXT_TERMINATED); } pa_context_state_t pa_context_get_state(pa_context *c) { - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); return c->state; } int pa_context_errno(pa_context *c) { - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); return c->error; } void pa_context_set_state_callback(pa_context *c, pa_context_notify_cb_t cb, void *userdata) { - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); c->state_callback = cb; c->state_userdata = userdata; } int pa_context_is_pending(pa_context *c) { - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY(c, c->state == PA_CONTEXT_CONNECTING || @@ -811,11 +809,11 @@ static void pstream_drain_callback(PA_GCC_UNUSED pa_pstream *s, void *userdata) static void set_dispatch_callbacks(pa_operation *o) { int done = 1; - assert(o); - assert(o->ref >= 1); - assert(o->context); - assert(o->context->ref >= 1); - assert(o->context->state == PA_CONTEXT_READY); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); + pa_assert(o->context); + pa_assert(PA_REFCNT_VALUE(o->context) >= 1); + pa_assert(o->context->state == PA_CONTEXT_READY); pa_pstream_set_drain_callback(o->context->pstream, NULL, NULL); pa_pdispatch_set_drain_callback(o->context->pdispatch, NULL, NULL); @@ -844,8 +842,8 @@ static void set_dispatch_callbacks(pa_operation *o) { pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *userdata) { pa_operation *o; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); PA_CHECK_VALIDITY_RETURN_NULL(c, pa_context_is_pending(c), PA_ERR_BADSTATE); @@ -860,9 +858,9 @@ void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_U pa_operation *o = userdata; int success = 1; - assert(pd); - assert(o); - assert(o->ref >= 1); + pa_assert(pd); + pa_assert(o); + pa_assert(PA_REFCNT_VALUE(o) >= 1); if (!o->context) goto finish; @@ -892,8 +890,8 @@ pa_operation* pa_context_exit_daemon(pa_context *c, pa_context_success_cb_t cb, pa_operation *o; uint32_t tag; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); @@ -911,8 +909,8 @@ pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, pa pa_operation *o; uint32_t tag; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); @@ -930,8 +928,8 @@ pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, pa_co pa_operation *o; uint32_t tag; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); @@ -950,8 +948,8 @@ pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_ pa_operation *o; uint32_t tag; - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); @@ -966,7 +964,7 @@ pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_ } int pa_context_is_local(pa_context *c) { - assert(c); + pa_assert(c); return c->is_local; } @@ -976,9 +974,9 @@ pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_su pa_operation *o; uint32_t tag; - assert(c); - assert(c->ref >= 1); - assert(name); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + pa_assert(name); PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE); @@ -997,8 +995,8 @@ const char* pa_get_library_version(void) { } const char* pa_context_get_server(pa_context *c) { - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); if (!c->server) return NULL; @@ -1016,8 +1014,8 @@ uint32_t pa_context_get_protocol_version(PA_GCC_UNUSED pa_context *c) { } uint32_t pa_context_get_server_protocol_version(pa_context *c) { - assert(c); - assert(c->ref >= 1); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); return c->version; } @@ -1025,8 +1023,8 @@ uint32_t pa_context_get_server_protocol_version(pa_context *c) { pa_tagstruct *pa_tagstruct_command(pa_context *c, uint32_t command, uint32_t *tag) { pa_tagstruct *t; - assert(c); - assert(tag); + pa_assert(c); + pa_assert(tag); t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, command); -- cgit From 14a9b80afbb0bddc216462b72156f14e032e1b5e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 21 Nov 2007 01:30:40 +0000 Subject: - Check process name when dealing with PID files - Add new PA_STREAM_FIX_CHANNELS, FIX_RATE, FIX_FORMAT, DONT_MOVE, VARIABLE_RATES to pa_sream_flags_t adn implement it - Expose those flags in pacat - Add notifications about device suspend/resume to the protocol and expose them in libpulse - Allow changing of buffer_attr during playback - allow disabling for remixing globally - hookup polkit support git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2067 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src/pulse/context.c') diff --git a/src/pulse/context.c b/src/pulse/context.c index 805cd44e..bc960e21 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -86,6 +86,10 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_UNDERFLOW] = pa_command_overflow_or_underflow, [PA_COMMAND_PLAYBACK_STREAM_KILLED] = pa_command_stream_killed, [PA_COMMAND_RECORD_STREAM_KILLED] = pa_command_stream_killed, + [PA_COMMAND_PLAYBACK_STREAM_MOVED] = pa_command_stream_moved, + [PA_COMMAND_RECORD_STREAM_MOVED] = pa_command_stream_moved, + [PA_COMMAND_PLAYBACK_STREAM_SUSPENDED] = pa_command_stream_suspended, + [PA_COMMAND_RECORD_STREAM_SUSPENDED] = pa_command_stream_suspended, [PA_COMMAND_SUBSCRIBE_EVENT] = pa_command_subscribe_event }; @@ -396,7 +400,7 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t /* Enable shared memory support if possible */ if (c->version >= 10 && pa_mempool_is_shared(c->mempool) && - c->is_local) { + c->is_local > 0) { /* Only enable SHM if both sides are owned by the same * user. This is a security measure because otherwise @@ -965,6 +969,9 @@ pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_ int pa_context_is_local(pa_context *c) { pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + PA_CHECK_VALIDITY(c, c->is_local >= 0, PA_ERR_BADSTATE); return c->is_local; } -- cgit From 2d34bca4a13bc43eeda54535630e37703806d53f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 24 Nov 2007 16:24:54 +0000 Subject: rearrange #includes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@2081 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulse/context.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/pulse/context.c') diff --git a/src/pulse/context.c b/src/pulse/context.c index bc960e21..7243a29d 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -50,12 +50,12 @@ #include #endif -#include "../pulsecore/winsock.h" - -#include #include #include +#include +#include + #include #include #include -- cgit