static void profile_init(pa_bluetooth_backend *b, pa_bluetooth_profile_t profile) { static const DBusObjectPathVTable vtable_profile = { .message_function = profile_handler, }; const char *object_name; const char *uuid; pa_assert(b); switch (profile) { case PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT: object_name = HSP_AG_PROFILE; uuid = PA_BLUETOOTH_UUID_HSP_AG; break; case PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY: object_name = HSP_HS_PROFILE; uuid = PA_BLUETOOTH_UUID_HSP_HS; break; default: pa_assert_not_reached(); break; } pa_assert_se(dbus_connection_register_object_path(pa_dbus_connection_get(b->connection), object_name, &vtable_profile, b)); register_profile(b, object_name, uuid); }
char *pa_sample_spec_to_mime_type(const pa_sample_spec *ss, const pa_channel_map *cm) { pa_assert(pa_channel_map_compatible(cm, ss)); pa_assert(pa_sample_spec_valid(ss)); if (!pa_sample_spec_is_mime(ss, cm)) return NULL; switch (ss->format) { case PA_SAMPLE_S16BE: case PA_SAMPLE_S24BE: case PA_SAMPLE_U8: /* Stupid UPnP implementations (PS3...) choke on spaces in * the mime type, that's why we write only ';' here, * instead of '; '. */ return pa_sprintf_malloc("audio/%s;rate=%u;channels=%u", ss->format == PA_SAMPLE_S16BE ? "L16" : (ss->format == PA_SAMPLE_S24BE ? "L24" : "L8"), ss->rate, ss->channels); case PA_SAMPLE_ULAW: return pa_xstrdup("audio/basic"); default: pa_assert_not_reached(); } }
static void get_service_data(struct service *s, pa_sample_spec *ret_ss, pa_channel_map *ret_map, const char **ret_name, pa_proplist **ret_proplist, enum service_subtype *ret_subtype) { pa_assert(s); pa_assert(ret_ss); pa_assert(ret_proplist); pa_assert(ret_subtype); if (pa_sink_isinstance(s->device)) { pa_sink *sink = PA_SINK(s->device); *ret_ss = sink->sample_spec; *ret_map = sink->channel_map; *ret_name = sink->name; *ret_proplist = sink->proplist; *ret_subtype = sink->flags & PA_SINK_HARDWARE ? SUBTYPE_HARDWARE : SUBTYPE_VIRTUAL; } else if (pa_source_isinstance(s->device)) { pa_source *source = PA_SOURCE(s->device); *ret_ss = source->sample_spec; *ret_map = source->channel_map; *ret_name = source->name; *ret_proplist = source->proplist; *ret_subtype = source->monitor_of ? SUBTYPE_MONITOR : (source->flags & PA_SOURCE_HARDWARE ? SUBTYPE_HARDWARE : SUBTYPE_VIRTUAL); } else pa_assert_not_reached(); }
/* Runs in PA mainloop context */ static void get_service_data(struct service *s, pa_object *device) { pa_assert(s); if (pa_sink_isinstance(device)) { pa_sink *sink = PA_SINK(device); s->is_sink = true; s->service_type = SERVICE_TYPE_SINK; s->ss = sink->sample_spec; s->cm = sink->channel_map; s->name = pa_xstrdup(sink->name); s->proplist = pa_proplist_copy(sink->proplist); s->subtype = sink->flags & PA_SINK_HARDWARE ? SUBTYPE_HARDWARE : SUBTYPE_VIRTUAL; } else if (pa_source_isinstance(device)) { pa_source *source = PA_SOURCE(device); s->is_sink = false; s->service_type = SERVICE_TYPE_SOURCE; s->ss = source->sample_spec; s->cm = source->channel_map; s->name = pa_xstrdup(source->name); s->proplist = pa_proplist_copy(source->proplist); s->subtype = source->monitor_of ? SUBTYPE_MONITOR : (source->flags & PA_SOURCE_HARDWARE ? SUBTYPE_HARDWARE : SUBTYPE_VIRTUAL); } else pa_assert_not_reached(); }
static DBusHandlerResult handle_get_address(DBusConnection *conn, DBusMessage *msg, pa_dbusobj_server_lookup *sl) { DBusHandlerResult r = DBUS_HANDLER_RESULT_HANDLED; DBusMessage *reply = NULL; char *address = NULL; DBusMessageIter msg_iter; DBusMessageIter variant_iter; pa_assert(conn); pa_assert(msg); pa_assert(sl); switch (get_address(sl->core->server_type, &address)) { case SUCCESS: if (!(reply = dbus_message_new_method_return(msg))) { r = DBUS_HANDLER_RESULT_NEED_MEMORY; goto finish; } dbus_message_iter_init_append(reply, &msg_iter); if (!dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_VARIANT, "s", &variant_iter)) { r = DBUS_HANDLER_RESULT_NEED_MEMORY; goto finish; } if (!dbus_message_iter_append_basic(&variant_iter, DBUS_TYPE_STRING, &address)) { r = DBUS_HANDLER_RESULT_NEED_MEMORY; goto finish; } if (!dbus_message_iter_close_container(&msg_iter, &variant_iter)) { r = DBUS_HANDLER_RESULT_NEED_MEMORY; goto finish; } if (!dbus_connection_send(conn, reply, NULL)) { r = DBUS_HANDLER_RESULT_NEED_MEMORY; goto finish; } r = DBUS_HANDLER_RESULT_HANDLED; goto finish; case SERVER_FROM_TYPE_FAILED: if (!(reply = dbus_message_new_error(msg, DBUS_ERROR_FAILED, "PulseAudio internal error: get_dbus_server_from_type() failed."))) { r = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; goto finish; } if (!dbus_connection_send(conn, reply, NULL)) { r = DBUS_HANDLER_RESULT_NEED_MEMORY; goto finish; } r = DBUS_HANDLER_RESULT_HANDLED; goto finish; default: pa_assert_not_reached(); } finish: pa_xfree(address); if (reply) dbus_message_unref(reply); return r; }
int pa_conversion_parse_list(pa_conversion_string_t type, const char *separator, const char *str, uint32_t *dst, char **unknown_entries) { switch (type) { case CONV_STRING_FORMAT: return parse_list(string_conversion_table_format, separator, str, dst, unknown_entries); case CONV_STRING_OUTPUT_CHANNELS: return parse_list(string_conversion_table_output_channels, separator, str, dst, unknown_entries); case CONV_STRING_INPUT_CHANNELS: return parse_list(string_conversion_table_input_channels, separator, str, dst, unknown_entries); case CONV_STRING_OUTPUT_DEVICE: return parse_list(string_conversion_table_output_device, separator, str, dst, unknown_entries); case CONV_STRING_INPUT_DEVICE: return parse_list(string_conversion_table_input_device, separator, str, dst, unknown_entries); case CONV_STRING_OUTPUT_FLAG: return parse_list(string_conversion_table_output_flag, separator, str, dst, unknown_entries); case CONV_STRING_INPUT_FLAG: return parse_list(string_conversion_table_input_flag, separator, str, dst, unknown_entries); } pa_assert_not_reached(); return 0; }
void pa_fdsem_wait(pa_fdsem *f) { pa_assert(f); flush(f); if (pa_atomic_cmpxchg(&f->data->signalled, 1, 0)) return; pa_atomic_inc(&f->data->waiting); while (!pa_atomic_cmpxchg(&f->data->signalled, 1, 0)) { char x[10]; ssize_t r; #ifdef HAVE_SYS_EVENTFD_H if (f->efd >= 0) { uint64_t u; if ((r = pa_read(f->efd, &u, sizeof(u), NULL)) != sizeof(u)) { if (r >= 0 || errno != EINTR) { pa_log_error("Invalid read from eventfd: %s", r < 0 ? pa_cstrerror(errno) : "EOF"); pa_assert_not_reached(); } continue; } r = (ssize_t) u; } else #endif if ((r = pa_read(f->fds[0], &x, sizeof(x), NULL)) <= 0) { if (r >= 0 || errno != EINTR) { pa_log_error("Invalid read from pipe: %s", r < 0 ? pa_cstrerror(errno) : "EOF"); pa_assert_not_reached(); } continue; } pa_atomic_sub(&f->data->in_pipe, (int) r); } pa_assert_se(pa_atomic_dec(&f->data->waiting) >= 1); }
pa_memchunk* pa_silence_memchunk_get(pa_silence_cache *cache, pa_mempool *pool, pa_memchunk* ret, const pa_sample_spec *spec, size_t length) { pa_memblock *b; size_t l; pa_assert(cache); pa_assert(pa_sample_spec_valid(spec)); if (!(b = cache->blocks[spec->format])) switch (spec->format) { case PA_SAMPLE_U8: cache->blocks[PA_SAMPLE_U8] = b = silence_memblock_new(pool, 0x80); break; case PA_SAMPLE_S16LE: case PA_SAMPLE_S16BE: case PA_SAMPLE_S32LE: case PA_SAMPLE_S32BE: case PA_SAMPLE_S24LE: case PA_SAMPLE_S24BE: case PA_SAMPLE_S24_32LE: case PA_SAMPLE_S24_32BE: case PA_SAMPLE_FLOAT32LE: case PA_SAMPLE_FLOAT32BE: cache->blocks[PA_SAMPLE_S16LE] = b = silence_memblock_new(pool, 0); cache->blocks[PA_SAMPLE_S16BE] = pa_memblock_ref(b); cache->blocks[PA_SAMPLE_S32LE] = pa_memblock_ref(b); cache->blocks[PA_SAMPLE_S32BE] = pa_memblock_ref(b); cache->blocks[PA_SAMPLE_S24LE] = pa_memblock_ref(b); cache->blocks[PA_SAMPLE_S24BE] = pa_memblock_ref(b); cache->blocks[PA_SAMPLE_S24_32LE] = pa_memblock_ref(b); cache->blocks[PA_SAMPLE_S24_32BE] = pa_memblock_ref(b); cache->blocks[PA_SAMPLE_FLOAT32LE] = pa_memblock_ref(b); cache->blocks[PA_SAMPLE_FLOAT32BE] = pa_memblock_ref(b); break; case PA_SAMPLE_ALAW: cache->blocks[PA_SAMPLE_ALAW] = b = silence_memblock_new(pool, 0xd5); break; case PA_SAMPLE_ULAW: cache->blocks[PA_SAMPLE_ULAW] = b = silence_memblock_new(pool, 0xff); break; default: pa_assert_not_reached(); } pa_assert(b); ret->memblock = pa_memblock_ref(b); l = pa_memblock_get_length(b); if (length > l || length == 0) length = l; ret->length = pa_frame_align(length, spec); ret->index = 0; return ret; }
void pa_fdsem_post(pa_fdsem *f) { pa_assert(f); if (pa_atomic_cmpxchg(&f->data->signalled, 0, 1)) { if (pa_atomic_load(&f->data->waiting)) { ssize_t r; char x = 'x'; pa_atomic_inc(&f->data->in_pipe); for (;;) { #ifdef HAVE_SYS_EVENTFD_H if (f->efd >= 0) { uint64_t u = 1; if ((r = pa_write(f->efd, &u, sizeof(u), NULL)) != sizeof(u)) { if (r >= 0 || errno != EINTR) { pa_log_error("Invalid write to eventfd: %s", r < 0 ? pa_cstrerror(errno) : "EOF"); pa_assert_not_reached(); } continue; } } else #endif if ((r = pa_write(f->fds[1], &x, 1, NULL)) != 1) { if (r >= 0 || errno != EINTR) { pa_log_error("Invalid write to pipe: %s", r < 0 ? pa_cstrerror(errno) : "EOF"); pa_assert_not_reached(); } continue; } break; } } } }
static bool shall_ignore(pa_object *o) { pa_object_assert_ref(o); if (pa_sink_isinstance(o)) return !!(PA_SINK(o)->flags & PA_SINK_NETWORK); if (pa_source_isinstance(o)) return PA_SOURCE(o)->monitor_of || (PA_SOURCE(o)->flags & PA_SOURCE_NETWORK); pa_assert_not_reached(); }
static void profile_done(pa_bluetooth_backend *b, pa_bluetooth_profile_t profile) { pa_assert(b); switch (profile) { case PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT: dbus_connection_unregister_object_path(pa_dbus_connection_get(b->connection), HSP_AG_PROFILE); break; default: pa_assert_not_reached(); break; } }
static void flush(pa_fdsem *f) { ssize_t r; pa_assert(f); if (pa_atomic_load(&f->data->in_pipe) <= 0) return; do { char x[10]; #ifdef HAVE_SYS_EVENTFD_H if (f->efd >= 0) { uint64_t u; if ((r = pa_read(f->efd, &u, sizeof(u), NULL)) != sizeof(u)) { if (r >= 0 || errno != EINTR) { pa_log_error("Invalid read from eventfd: %s", r < 0 ? pa_cstrerror(errno) : "EOF"); pa_assert_not_reached(); } continue; } r = (ssize_t) u; } else #endif if ((r = pa_read(f->fds[0], &x, sizeof(x), NULL)) <= 0) { if (r >= 0 || errno != EINTR) { pa_log_error("Invalid read from pipe: %s", r < 0 ? pa_cstrerror(errno) : "EOF"); pa_assert_not_reached(); } continue; } } while (pa_atomic_sub(&f->data->in_pipe, (int) r) > (int) r); }
static inline const char *status_to_string(meego_parameter_status_t status) { switch (status) { case MEEGO_PARAM_ENABLE: return "MEEGO_PARAM_ENABLE"; case MEEGO_PARAM_DISABLE: return "MEEGO_PARAM_DISABLE"; case MEEGO_PARAM_UPDATE: return "MEEGO_PARAM_UPDATE"; case MEEGO_PARAM_MODE_CHANGE: return "MEEGO_PARAM_MODE_CHANGE"; default: pa_assert_not_reached(); } }
/* Note: returns sizeof(char*) for strings, object paths and signatures. */ static unsigned basic_type_size(int type) { switch (type) { case DBUS_TYPE_BOOLEAN: return sizeof(dbus_bool_t); case DBUS_TYPE_BYTE: return 1; case DBUS_TYPE_INT16: return sizeof(dbus_int16_t); case DBUS_TYPE_UINT16: return sizeof(dbus_uint16_t); case DBUS_TYPE_INT32: return sizeof(dbus_int32_t); case DBUS_TYPE_UINT32: return sizeof(dbus_uint32_t); case DBUS_TYPE_INT64: return sizeof(dbus_int64_t); case DBUS_TYPE_UINT64: return sizeof(dbus_uint64_t); case DBUS_TYPE_DOUBLE: return sizeof(double); case DBUS_TYPE_STRING: case DBUS_TYPE_OBJECT_PATH: case DBUS_TYPE_SIGNATURE: return sizeof(char*); default: pa_assert_not_reached(); } }
static pa_source_output_flags_t get_dont_inhibit_auto_suspend_flag(pa_source *source, enum inhibit_auto_suspend inhibit_auto_suspend) { pa_assert(source); switch (inhibit_auto_suspend) { case INHIBIT_AUTO_SUSPEND_ALWAYS: return 0; case INHIBIT_AUTO_SUSPEND_NEVER: return PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND; case INHIBIT_AUTO_SUSPEND_ONLY_WITH_NON_MONITOR_SOURCES: return source->monitor_of ? 0 : PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND; } pa_assert_not_reached(); }
static const char *signature_from_basic_type(int type) { switch (type) { case DBUS_TYPE_BOOLEAN: return DBUS_TYPE_BOOLEAN_AS_STRING; case DBUS_TYPE_BYTE: return DBUS_TYPE_BYTE_AS_STRING; case DBUS_TYPE_INT16: return DBUS_TYPE_INT16_AS_STRING; case DBUS_TYPE_UINT16: return DBUS_TYPE_UINT16_AS_STRING; case DBUS_TYPE_INT32: return DBUS_TYPE_INT32_AS_STRING; case DBUS_TYPE_UINT32: return DBUS_TYPE_UINT32_AS_STRING; case DBUS_TYPE_INT64: return DBUS_TYPE_INT64_AS_STRING; case DBUS_TYPE_UINT64: return DBUS_TYPE_UINT64_AS_STRING; case DBUS_TYPE_DOUBLE: return DBUS_TYPE_DOUBLE_AS_STRING; case DBUS_TYPE_STRING: return DBUS_TYPE_STRING_AS_STRING; case DBUS_TYPE_OBJECT_PATH: return DBUS_TYPE_OBJECT_PATH_AS_STRING; case DBUS_TYPE_SIGNATURE: return DBUS_TYPE_SIGNATURE_AS_STRING; default: pa_assert_not_reached(); } }
void pa_shm_free(pa_shm *m) { pa_assert(m); pa_assert(m->ptr); pa_assert(m->size > 0); #ifdef MAP_FAILED pa_assert(m->ptr != MAP_FAILED); #endif if (m->type == PA_MEM_TYPE_PRIVATE) { privatemem_free(m); goto finish; } #if defined(HAVE_SHM_OPEN) || defined(HAVE_MEMFD) if (munmap(m->ptr, PA_PAGE_ALIGN(m->size)) < 0) pa_log("munmap() failed: %s", pa_cstrerror(errno)); #ifdef HAVE_SHM_OPEN if (m->type == PA_MEM_TYPE_SHARED_POSIX && m->do_unlink) { char fn[32]; segment_name(fn, sizeof(fn), m->id); if (shm_unlink(fn) < 0) pa_log(" shm_unlink(%s) failed: %s", fn, pa_cstrerror(errno)); } #endif #ifdef HAVE_MEMFD if (m->type == PA_MEM_TYPE_SHARED_MEMFD && m->fd != -1) pa_assert_se(pa_close(m->fd) == 0); #endif #else /* We shouldn't be here without shm or memfd support */ pa_assert_not_reached(); #endif finish: pa_zero(*m); }
void pa_shm_free(pa_shm *m) { pa_assert(m); pa_assert(m->ptr); pa_assert(m->size > 0); #ifdef MAP_FAILED pa_assert(m->ptr != MAP_FAILED); #endif if (!m->shared) { #ifdef MAP_ANONYMOUS if (munmap(m->ptr, m->size) < 0) pa_log("munmap() failed: %s", pa_cstrerror(errno)); #elif defined(HAVE_POSIX_MEMALIGN) free(m->ptr); #else pa_xfree(m->ptr); #endif } else { #ifdef HAVE_SHM_OPEN if (munmap(m->ptr, PA_PAGE_ALIGN(m->size)) < 0) pa_log("munmap() failed: %s", pa_cstrerror(errno)); if (m->do_unlink) { char fn[32]; segment_name(fn, sizeof(fn), m->id); if (shm_unlink(fn) < 0) pa_log(" shm_unlink(%s) failed: %s", fn, pa_cstrerror(errno)); } #else /* We shouldn't be here without shm support */ pa_assert_not_reached(); #endif } pa_zero(*m); }
static uint8_t silence_byte(pa_sample_format_t format) { switch (format) { case PA_SAMPLE_U8: return 0x80; case PA_SAMPLE_S16LE: case PA_SAMPLE_S16BE: case PA_SAMPLE_S32LE: case PA_SAMPLE_S32BE: case PA_SAMPLE_FLOAT32LE: case PA_SAMPLE_FLOAT32BE: case PA_SAMPLE_S24LE: case PA_SAMPLE_S24BE: case PA_SAMPLE_S24_32LE: case PA_SAMPLE_S24_32BE: return 0; case PA_SAMPLE_ALAW: return 0xd5; case PA_SAMPLE_ULAW: return 0xff; default: pa_assert_not_reached(); } }
static pa_memblock* generate_block(pa_mempool *pool, const pa_sample_spec *ss) { pa_memblock *r; void *d; unsigned i; pa_assert_se(r = pa_memblock_new(pool, pa_frame_size(ss) * 10)); d = pa_memblock_acquire(r); switch (ss->format) { case PA_SAMPLE_U8: case PA_SAMPLE_ULAW: case PA_SAMPLE_ALAW: { static const uint8_t u8_samples[] = { 0x00, 0xFF, 0x7F, 0x80, 0x9f, 0x3f, 0x01, 0xF0, 0x20, 0x21 }; memcpy(d, u8_samples, sizeof(u8_samples)); break; } case PA_SAMPLE_S16NE: case PA_SAMPLE_S16RE: { static const uint16_t u16_samples[] = { 0x0000, 0xFFFF, 0x7FFF, 0x8000, 0x9fff, 0x3fff, 0x0001, 0xF000, 0x0020, 0x0021 }; memcpy(d, u16_samples, sizeof(u16_samples)); break; } case PA_SAMPLE_S24_32NE: case PA_SAMPLE_S24_32RE: case PA_SAMPLE_S32NE: case PA_SAMPLE_S32RE: { static const uint32_t u32_samples[] = { 0x00000001, 0xFFFF0002, 0x7FFF0003, 0x80000004, 0x9fff0005, 0x3fff0006, 0x00010007, 0xF0000008, 0x00200009, 0x0021000A }; memcpy(d, u32_samples, sizeof(u32_samples)); break; } case PA_SAMPLE_S24NE: case PA_SAMPLE_S24RE: { /* Need to be on a byte array because they are not aligned */ static const uint8_t u24_samples[] = { 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x02, 0x7F, 0xFF, 0x03, 0x80, 0x00, 0x04, 0x9f, 0xff, 0x05, 0x3f, 0xff, 0x06, 0x01, 0x00, 0x07, 0xF0, 0x00, 0x08, 0x20, 0x00, 0x09, 0x21, 0x00, 0x0A }; memcpy(d, u24_samples, sizeof(u24_samples)); break; } case PA_SAMPLE_FLOAT32NE: case PA_SAMPLE_FLOAT32RE: { float *u = d; static const float float_samples[] = { 0.0f, -1.0f, 1.0f, 4711.0f, 0.222f, 0.33f, -.3f, 99.0f, -0.555f, -.123f }; if (ss->format == PA_SAMPLE_FLOAT32RE) { for (i = 0; i < 10; i++) u[i] = PA_FLOAT32_SWAP(float_samples[i]); } else memcpy(d, float_samples, sizeof(float_samples)); break; } default: pa_assert_not_reached(); } pa_memblock_release(r); return r; }
static void compare_block(const pa_sample_spec *ss, const pa_memchunk *chunk, int iter) { void *d; unsigned i; d = pa_memblock_acquire(chunk->memblock); switch (ss->format) { case PA_SAMPLE_U8: { const uint8_t *v = u8_result[iter]; uint8_t *u = d; for (i = 0; i < chunk->length / pa_frame_size(ss); i++) { fail_unless(*u == *v, NULL); ++u; ++v; } break; } case PA_SAMPLE_ALAW: { const uint8_t *v = alaw_result[iter]; uint8_t *u = d; for (i = 0; i < chunk->length / pa_frame_size(ss); i++) { fail_unless(*u == *v, NULL); ++u; ++v; } break; } case PA_SAMPLE_ULAW: { const uint8_t *v = ulaw_result[iter]; uint8_t *u = d; for (i = 0; i < chunk->length / pa_frame_size(ss); i++) { fail_unless(*u == *v, NULL); ++u; ++v; } break; } case PA_SAMPLE_S16LE: { const uint16_t *v = s16le_result[iter]; uint16_t *u = d; for (i = 0; i < chunk->length / pa_frame_size(ss); i++) { fail_unless(*u == *v, NULL); ++u; ++v; } break; } case PA_SAMPLE_S16BE: { const uint16_t *v = s16be_result[iter]; uint16_t *u = d; for (i = 0; i < chunk->length / pa_frame_size(ss); i++) { fail_unless(*u == *v, NULL); ++u; ++v; } break; } case PA_SAMPLE_FLOAT32LE: { const float *v = float32le_result[iter]; float *u = d; for (i = 0; i < chunk->length / pa_frame_size(ss); i++) { float uu = ss->format == PA_SAMPLE_FLOAT32NE ? *u : PA_FLOAT32_SWAP(*u); fail_unless(fabs(uu - *v) <= 1e-6, NULL); ++u; ++v; } break; } case PA_SAMPLE_FLOAT32BE: { const float *v = float32be_result[iter]; float *u = d; for (i = 0; i < chunk->length / pa_frame_size(ss); i++) { float uu = ss->format == PA_SAMPLE_FLOAT32NE ? *u : PA_FLOAT32_SWAP(*u); fail_unless(fabs(uu - *v) <= 1e-6, NULL); ++u; ++v; } break; } case PA_SAMPLE_S32LE: { const uint32_t *v = s32le_result[iter]; uint32_t *u = d; for (i = 0; i < chunk->length / pa_frame_size(ss); i++) { fail_unless(*u == *v, NULL); ++u; ++v; } break; } case PA_SAMPLE_S32BE: { const uint32_t *v = s32be_result[iter]; uint32_t *u = d; for (i = 0; i < chunk->length / pa_frame_size(ss); i++) { fail_unless(*u == *v, NULL); ++u; ++v; } break; } case PA_SAMPLE_S24_32LE: { const uint32_t *v = s24_32le_result[iter]; uint32_t *u = d; for (i = 0; i < chunk->length / pa_frame_size(ss); i++) { fail_unless(*u == *v, NULL); ++u; ++v; } break; } case PA_SAMPLE_S24_32BE: { const uint32_t *v = s24_32be_result[iter]; uint32_t *u = d; for (i = 0; i < chunk->length / pa_frame_size(ss); i++) { fail_unless(*u == *v, NULL); ++u; ++v; } break; } case PA_SAMPLE_S24LE: { const uint8_t *v = s24le_result[iter]; uint8_t *u = d; for (i = 0; i < chunk->length / pa_frame_size(ss); i++) { fail_unless(*u == *v, NULL); fail_unless(*(u+1) == *(v+1), NULL); fail_unless(*(u+2) == *(v+2), NULL); u += 3; v += 3; } break; } case PA_SAMPLE_S24BE: { const uint8_t *v = s24be_result[iter]; uint8_t *u = d; for (i = 0; i < chunk->length / pa_frame_size(ss); i++) { fail_unless(*u == *v, NULL); fail_unless(*(u+1) == *(v+1), NULL); fail_unless(*(u+2) == *(v+2), NULL); u += 3; v += 3; } break; } default: pa_assert_not_reached(); } pa_memblock_release(chunk->memblock); }
int main(int argc, char *argv[]) { pa_core *c = NULL; pa_strbuf *buf = NULL; pa_daemon_conf *conf = NULL; pa_mainloop *mainloop = NULL; char *s; char *configured_address; int r = 0, retval = 1, d = 0; bool valid_pid_file = false; bool ltdl_init = false; int passed_fd = -1; const char *e; #ifdef HAVE_FORK int daemon_pipe[2] = { -1, -1 }; int daemon_pipe2[2] = { -1, -1 }; #endif int autospawn_fd = -1; bool autospawn_locked = false; #ifdef HAVE_DBUS pa_dbusobj_server_lookup *server_lookup = NULL; /* /org/pulseaudio/server_lookup */ pa_dbus_connection *lookup_service_bus = NULL; /* Always the user bus. */ pa_dbus_connection *server_bus = NULL; /* The bus where we reserve org.pulseaudio.Server, either the user or the system bus. */ bool start_server; #endif pa_log_set_ident("pulseaudio"); pa_log_set_level(PA_LOG_NOTICE); pa_log_set_flags(PA_LOG_COLORS|PA_LOG_PRINT_FILE|PA_LOG_PRINT_LEVEL, PA_LOG_RESET); #if defined(__linux__) && defined(__OPTIMIZE__) /* Disable lazy relocations to make usage of external libraries more deterministic for our RT threads. We abuse __OPTIMIZE__ as a check whether we are a debug build or not. This all is admittedly a bit snake-oilish. */ if (!getenv("LD_BIND_NOW")) { char *rp; char *canonical_rp; /* We have to execute ourselves, because the libc caches the * value of $LD_BIND_NOW on initialization. */ pa_set_env("LD_BIND_NOW", "1"); if ((canonical_rp = pa_realpath(PA_BINARY))) { if ((rp = pa_readlink("/proc/self/exe"))) { if (pa_streq(rp, canonical_rp)) pa_assert_se(execv(rp, argv) == 0); else pa_log_warn("/proc/self/exe does not point to %s, cannot self execute. Are you playing games?", canonical_rp); pa_xfree(rp); } else pa_log_warn("Couldn't read /proc/self/exe, cannot self execute. Running in a chroot()?"); pa_xfree(canonical_rp); } else pa_log_warn("Couldn't canonicalize binary path, cannot self execute."); } #endif if ((e = getenv("PULSE_PASSED_FD"))) { passed_fd = atoi(e); if (passed_fd <= 2) passed_fd = -1; } /* We might be autospawned, in which case have no idea in which * context we have been started. Let's cleanup our execution * context as good as possible */ pa_reset_personality(); pa_drop_root(); pa_close_all(passed_fd, -1); pa_reset_sigs(-1); pa_unblock_sigs(-1); pa_reset_priority(); setlocale(LC_ALL, ""); pa_init_i18n(); conf = pa_daemon_conf_new(); if (pa_daemon_conf_load(conf, NULL) < 0) goto finish; if (pa_daemon_conf_env(conf) < 0) goto finish; if (pa_cmdline_parse(conf, argc, argv, &d) < 0) { pa_log(_("Failed to parse command line.")); goto finish; } if (conf->log_target) pa_log_set_target(conf->log_target); else { pa_log_target target = { .type = PA_LOG_STDERR, .file = NULL }; pa_log_set_target(&target); } pa_log_set_level(conf->log_level); if (conf->log_meta) pa_log_set_flags(PA_LOG_PRINT_META, PA_LOG_SET); if (conf->log_time) pa_log_set_flags(PA_LOG_PRINT_TIME, PA_LOG_SET); pa_log_set_show_backtrace(conf->log_backtrace); #ifdef HAVE_DBUS /* conf->system_instance and conf->local_server_type control almost the * same thing; make them agree about what is requested. */ switch (conf->local_server_type) { case PA_SERVER_TYPE_UNSET: conf->local_server_type = conf->system_instance ? PA_SERVER_TYPE_SYSTEM : PA_SERVER_TYPE_USER; break; case PA_SERVER_TYPE_USER: case PA_SERVER_TYPE_NONE: conf->system_instance = false; break; case PA_SERVER_TYPE_SYSTEM: conf->system_instance = true; break; default: pa_assert_not_reached(); } start_server = conf->local_server_type == PA_SERVER_TYPE_USER || (getuid() == 0 && conf->local_server_type == PA_SERVER_TYPE_SYSTEM); if (!start_server && conf->local_server_type == PA_SERVER_TYPE_SYSTEM) { pa_log_notice(_("System mode refused for non-root user. Only starting the D-Bus server lookup service.")); conf->system_instance = false; } #endif LTDL_SET_PRELOADED_SYMBOLS(); pa_ltdl_init(); ltdl_init = true; if (conf->dl_search_path) lt_dlsetsearchpath(conf->dl_search_path); #ifdef OS_IS_WIN32 { WSADATA data; WSAStartup(MAKEWORD(2, 0), &data); } #endif pa_random_seed(); switch (conf->cmd) { case PA_CMD_DUMP_MODULES: pa_dump_modules(conf, argc-d, argv+d); retval = 0; goto finish; case PA_CMD_DUMP_CONF: { if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } s = pa_daemon_conf_dump(conf); fputs(s, stdout); pa_xfree(s); retval = 0; goto finish; } case PA_CMD_DUMP_RESAMPLE_METHODS: { int i; if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } for (i = 0; i < PA_RESAMPLER_MAX; i++) if (pa_resample_method_supported(i)) printf("%s\n", pa_resample_method_to_string(i)); retval = 0; goto finish; } case PA_CMD_HELP : pa_cmdline_help(argv[0]); retval = 0; goto finish; case PA_CMD_VERSION : if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } printf(PACKAGE_NAME" "PACKAGE_VERSION"\n"); retval = 0; goto finish; case PA_CMD_CHECK: { pid_t pid; if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } if (pa_pid_file_check_running(&pid, "pulseaudio") < 0) pa_log_info(_("Daemon not running")); else { pa_log_info(_("Daemon running as PID %u"), pid); retval = 0; } goto finish; } case PA_CMD_KILL: if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } if (pa_pid_file_kill(SIGINT, NULL, "pulseaudio") < 0) pa_log(_("Failed to kill daemon: %s"), pa_cstrerror(errno)); else retval = 0; goto finish; case PA_CMD_CLEANUP_SHM: if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } if (pa_shm_cleanup() >= 0) retval = 0; goto finish; default: pa_assert(conf->cmd == PA_CMD_DAEMON || conf->cmd == PA_CMD_START); } if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } #ifdef HAVE_GETUID if (getuid() == 0 && !conf->system_instance) pa_log_warn(_("This program is not intended to be run as root (unless --system is specified).")); #ifndef HAVE_DBUS /* A similar, only a notice worthy check was done earlier, if D-Bus is enabled. */ else if (getuid() != 0 && conf->system_instance) { pa_log(_("Root privileges required.")); goto finish; } #endif #endif /* HAVE_GETUID */ if (conf->cmd == PA_CMD_START && conf->system_instance) { pa_log(_("--start not supported for system instances.")); goto finish; } if (conf->cmd == PA_CMD_START && (configured_address = check_configured_address())) { /* There is an server address in our config, but where did it come from? * By default a standard X11 login will load module-x11-publish which will * inject PULSE_SERVER X11 property. If the PA daemon crashes, we will end * up hitting this code path. So we have to check to see if our configured_address * is the same as the value that would go into this property so that we can * recover (i.e. autospawn) from a crash. */ char *ufn; bool start_anyway = false; if ((ufn = pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET))) { char *id; if ((id = pa_machine_id())) { pa_strlist *server_list; char formatted_ufn[256]; pa_snprintf(formatted_ufn, sizeof(formatted_ufn), "{%s}unix:%s", id, ufn); pa_xfree(id); if ((server_list = pa_strlist_parse(configured_address))) { char *u = NULL; /* We only need to check the first server */ server_list = pa_strlist_pop(server_list, &u); pa_strlist_free(server_list); start_anyway = (u && pa_streq(formatted_ufn, u)); pa_xfree(u); } } pa_xfree(ufn); } if (!start_anyway) { pa_log_notice(_("User-configured server at %s, refusing to start/autospawn."), configured_address); pa_xfree(configured_address); retval = 0; goto finish; } pa_log_notice(_("User-configured server at %s, which appears to be local. Probing deeper."), configured_address); pa_xfree(configured_address); } if (conf->system_instance && !conf->disallow_exit) pa_log_warn(_("Running in system mode, but --disallow-exit not set!")); if (conf->system_instance && !conf->disallow_module_loading) pa_log_warn(_("Running in system mode, but --disallow-module-loading not set!")); if (conf->system_instance && !conf->disable_shm) { pa_log_notice(_("Running in system mode, forcibly disabling SHM mode!")); conf->disable_shm = true; } if (conf->system_instance && conf->exit_idle_time >= 0) { pa_log_notice(_("Running in system mode, forcibly disabling exit idle time!")); conf->exit_idle_time = -1; } if (conf->cmd == PA_CMD_START) { /* If we shall start PA only when it is not running yet, we * first take the autospawn lock to make things * synchronous. */ if ((autospawn_fd = pa_autospawn_lock_init()) < 0) { pa_log("Failed to initialize autospawn lock"); goto finish; } if ((pa_autospawn_lock_acquire(true) < 0)) { pa_log("Failed to acquire autospawn lock"); goto finish; } autospawn_locked = true; } if (conf->daemonize) { #ifdef HAVE_FORK pid_t child; #endif if (pa_stdio_acquire() < 0) { pa_log(_("Failed to acquire stdio.")); goto finish; } #ifdef HAVE_FORK if (pipe(daemon_pipe) < 0) { pa_log(_("pipe() failed: %s"), pa_cstrerror(errno)); goto finish; } if ((child = fork()) < 0) { pa_log(_("fork() failed: %s"), pa_cstrerror(errno)); pa_close_pipe(daemon_pipe); goto finish; } if (child != 0) { ssize_t n; /* Father */ pa_assert_se(pa_close(daemon_pipe[1]) == 0); daemon_pipe[1] = -1; if ((n = pa_loop_read(daemon_pipe[0], &retval, sizeof(retval), NULL)) != sizeof(retval)) { if (n < 0) pa_log(_("read() failed: %s"), pa_cstrerror(errno)); retval = 1; } if (retval) pa_log(_("Daemon startup failed.")); else pa_log_info(_("Daemon startup successful.")); goto finish; } if (autospawn_fd >= 0) { /* The lock file is unlocked from the parent, so we need * to close it in the child */ pa_autospawn_lock_release(); pa_autospawn_lock_done(true); autospawn_locked = false; autospawn_fd = -1; } pa_assert_se(pa_close(daemon_pipe[0]) == 0); daemon_pipe[0] = -1; #endif if (!conf->log_target) { #ifdef HAVE_JOURNAL pa_log_target target = { .type = PA_LOG_JOURNAL, .file = NULL }; #else pa_log_target target = { .type = PA_LOG_SYSLOG, .file = NULL }; #endif pa_log_set_target(&target); }
static void dump_block(const pa_sample_spec *ss, const pa_memchunk *chunk) { void *d; unsigned i; d = pa_memblock_acquire(chunk->memblock); switch (ss->format) { case PA_SAMPLE_U8: case PA_SAMPLE_ULAW: case PA_SAMPLE_ALAW: { uint8_t *u = d; for (i = 0; i < chunk->length / pa_frame_size(ss); i++) printf(" 0x%02x ", *(u++)); break; } case PA_SAMPLE_S16NE: case PA_SAMPLE_S16RE: { uint16_t *u = d; for (i = 0; i < chunk->length / pa_frame_size(ss); i++) printf(" 0x%04x ", *(u++)); break; } case PA_SAMPLE_S32NE: case PA_SAMPLE_S32RE: { uint32_t *u = d; for (i = 0; i < chunk->length / pa_frame_size(ss); i++) printf("0x%08x ", *(u++)); break; } case PA_SAMPLE_S24_32NE: case PA_SAMPLE_S24_32RE: { uint32_t *u = d; for (i = 0; i < chunk->length / pa_frame_size(ss); i++) printf("0x%08x ", *(u++)); break; } case PA_SAMPLE_FLOAT32NE: case PA_SAMPLE_FLOAT32RE: { float *u = d; for (i = 0; i < chunk->length / pa_frame_size(ss); i++) { printf("%4.3g ", ss->format == PA_SAMPLE_FLOAT32NE ? *u : PA_FLOAT32_SWAP(*u)); u++; } break; } case PA_SAMPLE_S24LE: case PA_SAMPLE_S24BE: { uint8_t *u = d; for (i = 0; i < chunk->length / pa_frame_size(ss); i++) { printf(" 0x%06x ", PA_READ24NE(u)); u += pa_frame_size(ss); } break; } default: pa_assert_not_reached(); } printf("\n"); pa_memblock_release(chunk->memblock); }
int pa__init(pa_module*m) { struct userdata *u; pa_sample_spec ss; pa_channel_map map; pa_modargs *ma; char *t; pa_sink *master; pa_sink_input_new_data sink_input_data; pa_sink_new_data sink_data; const char *plugin, *label; LADSPA_Descriptor_Function descriptor_func; const char *e, *cdata; const LADSPA_Descriptor *d; unsigned long input_port, output_port, p, j, n_control; unsigned c; pa_bool_t *use_default = NULL; pa_assert(m); pa_assert_cc(sizeof(LADSPA_Data) == sizeof(float)); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments."); goto fail; } if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SINK))) { pa_log("Master sink not found"); goto fail; } ss = master->sample_spec; ss.format = PA_SAMPLE_FLOAT32; map = master->channel_map; if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { pa_log("Invalid sample format specification or channel map"); goto fail; } if (!(plugin = pa_modargs_get_value(ma, "plugin", NULL))) { pa_log("Missing LADSPA plugin name"); goto fail; } if (!(label = pa_modargs_get_value(ma, "label", NULL))) { pa_log("Missing LADSPA plugin label"); goto fail; } cdata = pa_modargs_get_value(ma, "control", NULL); u = pa_xnew0(struct userdata, 1); u->module = m; m->userdata = u; u->memblockq = pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH, 0, pa_frame_size(&ss), 1, 1, 0, NULL); if (!(e = getenv("LADSPA_PATH"))) e = LADSPA_PATH; /* FIXME: This is not exactly thread safe */ t = pa_xstrdup(lt_dlgetsearchpath()); lt_dlsetsearchpath(e); m->dl = lt_dlopenext(plugin); lt_dlsetsearchpath(t); pa_xfree(t); if (!m->dl) { pa_log("Failed to load LADSPA plugin: %s", lt_dlerror()); goto fail; } if (!(descriptor_func = (LADSPA_Descriptor_Function) pa_load_sym(m->dl, NULL, "ladspa_descriptor"))) { pa_log("LADSPA module lacks ladspa_descriptor() symbol."); goto fail; } for (j = 0;; j++) { if (!(d = descriptor_func(j))) { pa_log("Failed to find plugin label '%s' in plugin '%s'.", label, plugin); goto fail; } if (strcmp(d->Label, label) == 0) break; } u->descriptor = d; pa_log_debug("Module: %s", plugin); pa_log_debug("Label: %s", d->Label); pa_log_debug("Unique ID: %lu", d->UniqueID); pa_log_debug("Name: %s", d->Name); pa_log_debug("Maker: %s", d->Maker); pa_log_debug("Copyright: %s", d->Copyright); input_port = output_port = (unsigned long) -1; n_control = 0; for (p = 0; p < d->PortCount; p++) { if (LADSPA_IS_PORT_INPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_AUDIO(d->PortDescriptors[p])) { if (strcmp(d->PortNames[p], "Input") == 0) { pa_assert(input_port == (unsigned long) -1); input_port = p; } else { pa_log("Found audio input port on plugin we cannot handle: %s", d->PortNames[p]); goto fail; } } else if (LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_AUDIO(d->PortDescriptors[p])) { if (strcmp(d->PortNames[p], "Output") == 0) { pa_assert(output_port == (unsigned long) -1); output_port = p; } else { pa_log("Found audio output port on plugin we cannot handle: %s", d->PortNames[p]); goto fail; } } else if (LADSPA_IS_PORT_INPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p])) n_control++; else { pa_assert(LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[p]) && LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p])); pa_log_debug("Ignored control output port \"%s\".", d->PortNames[p]); } } if ((input_port == (unsigned long) -1) || (output_port == (unsigned long) -1)) { pa_log("Failed to identify input and output ports. " "Right now this module can only deal with plugins which provide an 'Input' and an 'Output' audio port. " "Patches welcome!"); goto fail; } u->block_size = pa_frame_align(pa_mempool_block_size_max(m->core->mempool), &ss); u->input = (LADSPA_Data*) pa_xnew(uint8_t, (unsigned) u->block_size); if (LADSPA_IS_INPLACE_BROKEN(d->Properties)) u->output = (LADSPA_Data*) pa_xnew(uint8_t, (unsigned) u->block_size); else u->output = u->input; u->channels = ss.channels; for (c = 0; c < ss.channels; c++) { if (!(u->handle[c] = d->instantiate(d, ss.rate))) { pa_log("Failed to instantiate plugin %s with label %s for channel %i", plugin, d->Label, c); goto fail; } d->connect_port(u->handle[c], input_port, u->input); d->connect_port(u->handle[c], output_port, u->output); } if (!cdata && n_control > 0) { pa_log("This plugin requires specification of %lu control parameters.", n_control); goto fail; } if (n_control > 0) { const char *state = NULL; char *k; unsigned long h; u->control = pa_xnew(LADSPA_Data, (unsigned) n_control); use_default = pa_xnew(pa_bool_t, (unsigned) n_control); p = 0; while ((k = pa_split(cdata, ",", &state)) && p < n_control) { double f; if (*k == 0) { use_default[p++] = TRUE; pa_xfree(k); continue; } if (pa_atod(k, &f) < 0) { pa_log("Failed to parse control value '%s'", k); pa_xfree(k); goto fail; } pa_xfree(k); use_default[p] = FALSE; u->control[p++] = (LADSPA_Data) f; } /* The previous loop doesn't take the last control value into account if it is left empty, so we do it here. */ if (*cdata == 0 || cdata[strlen(cdata) - 1] == ',') { if (p < n_control) use_default[p] = TRUE; p++; } if (p > n_control || k) { pa_log("Too many control values passed, %lu expected.", n_control); pa_xfree(k); goto fail; } if (p < n_control) { pa_log("Not enough control values passed, %lu expected, %lu passed.", n_control, p); goto fail; } h = 0; for (p = 0; p < d->PortCount; p++) { LADSPA_PortRangeHintDescriptor hint = d->PortRangeHints[p].HintDescriptor; if (!LADSPA_IS_PORT_CONTROL(d->PortDescriptors[p])) continue; if (LADSPA_IS_PORT_OUTPUT(d->PortDescriptors[p])) { for (c = 0; c < ss.channels; c++) d->connect_port(u->handle[c], p, &u->control_out); continue; } pa_assert(h < n_control); if (use_default[h]) { LADSPA_Data lower, upper; if (!LADSPA_IS_HINT_HAS_DEFAULT(hint)) { pa_log("Control port value left empty but plugin defines no default."); goto fail; } lower = d->PortRangeHints[p].LowerBound; upper = d->PortRangeHints[p].UpperBound; if (LADSPA_IS_HINT_SAMPLE_RATE(hint)) { lower *= (LADSPA_Data) ss.rate; upper *= (LADSPA_Data) ss.rate; } switch (hint & LADSPA_HINT_DEFAULT_MASK) { case LADSPA_HINT_DEFAULT_MINIMUM: u->control[h] = lower; break; case LADSPA_HINT_DEFAULT_MAXIMUM: u->control[h] = upper; break; case LADSPA_HINT_DEFAULT_LOW: if (LADSPA_IS_HINT_LOGARITHMIC(hint)) u->control[h] = (LADSPA_Data) exp(log(lower) * 0.75 + log(upper) * 0.25); else u->control[h] = (LADSPA_Data) (lower * 0.75 + upper * 0.25); break; case LADSPA_HINT_DEFAULT_MIDDLE: if (LADSPA_IS_HINT_LOGARITHMIC(hint)) u->control[h] = (LADSPA_Data) exp(log(lower) * 0.5 + log(upper) * 0.5); else u->control[h] = (LADSPA_Data) (lower * 0.5 + upper * 0.5); break; case LADSPA_HINT_DEFAULT_HIGH: if (LADSPA_IS_HINT_LOGARITHMIC(hint)) u->control[h] = (LADSPA_Data) exp(log(lower) * 0.25 + log(upper) * 0.75); else u->control[h] = (LADSPA_Data) (lower * 0.25 + upper * 0.75); break; case LADSPA_HINT_DEFAULT_0: u->control[h] = 0; break; case LADSPA_HINT_DEFAULT_1: u->control[h] = 1; break; case LADSPA_HINT_DEFAULT_100: u->control[h] = 100; break; case LADSPA_HINT_DEFAULT_440: u->control[h] = 440; break; default: pa_assert_not_reached(); } } if (LADSPA_IS_HINT_INTEGER(hint)) u->control[h] = roundf(u->control[h]); pa_log_debug("Binding %f to port %s", u->control[h], d->PortNames[p]); for (c = 0; c < ss.channels; c++) d->connect_port(u->handle[c], p, &u->control[h]); h++; } pa_assert(h == n_control); } if (d->activate) for (c = 0; c < u->channels; c++) d->activate(u->handle[c]); /* Create sink */ pa_sink_new_data_init(&sink_data); sink_data.driver = __FILE__; sink_data.module = m; if (!(sink_data.name = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", NULL)))) sink_data.name = pa_sprintf_malloc("%s.ladspa", master->name); pa_sink_new_data_set_sample_spec(&sink_data, &ss); pa_sink_new_data_set_channel_map(&sink_data, &map); pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name); pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "filter"); pa_proplist_sets(sink_data.proplist, "device.ladspa.module", plugin); pa_proplist_sets(sink_data.proplist, "device.ladspa.label", d->Label); pa_proplist_sets(sink_data.proplist, "device.ladspa.name", d->Name); pa_proplist_sets(sink_data.proplist, "device.ladspa.maker", d->Maker); pa_proplist_sets(sink_data.proplist, "device.ladspa.copyright", d->Copyright); pa_proplist_setf(sink_data.proplist, "device.ladspa.unique_id", "%lu", (unsigned long) d->UniqueID); if (pa_modargs_get_proplist(ma, "sink_properties", sink_data.proplist, PA_UPDATE_REPLACE) < 0) { pa_log("Invalid properties"); pa_sink_new_data_done(&sink_data); goto fail; } if ((u->auto_desc = !pa_proplist_contains(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION))) { const char *z; z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION); pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "LADSPA Plugin %s on %s", d->Name, z ? z : master->name); } u->sink = pa_sink_new(m->core, &sink_data, PA_SINK_HW_MUTE_CTRL|PA_SINK_HW_VOLUME_CTRL|PA_SINK_DECIBEL_VOLUME| (master->flags & (PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY))); pa_sink_new_data_done(&sink_data); if (!u->sink) { pa_log("Failed to create sink."); goto fail; } u->sink->parent.process_msg = sink_process_msg_cb; u->sink->set_state = sink_set_state_cb; u->sink->update_requested_latency = sink_update_requested_latency_cb; u->sink->request_rewind = sink_request_rewind_cb; u->sink->set_volume = sink_set_volume_cb; u->sink->set_mute = sink_set_mute_cb; u->sink->userdata = u; pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq); /* Create sink input */ pa_sink_input_new_data_init(&sink_input_data); sink_input_data.driver = __FILE__; sink_input_data.module = m; sink_input_data.sink = master; pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "LADSPA Stream"); pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter"); pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss); pa_sink_input_new_data_set_channel_map(&sink_input_data, &map); pa_sink_input_new(&u->sink_input, m->core, &sink_input_data); pa_sink_input_new_data_done(&sink_input_data); if (!u->sink_input) goto fail; u->sink_input->pop = sink_input_pop_cb; u->sink_input->process_rewind = sink_input_process_rewind_cb; u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb; u->sink_input->update_max_request = sink_input_update_max_request_cb; u->sink_input->update_sink_latency_range = sink_input_update_sink_latency_range_cb; u->sink_input->update_sink_fixed_latency = sink_input_update_sink_fixed_latency_cb; u->sink_input->kill = sink_input_kill_cb; u->sink_input->attach = sink_input_attach_cb; u->sink_input->detach = sink_input_detach_cb; u->sink_input->state_change = sink_input_state_change_cb; u->sink_input->may_move_to = sink_input_may_move_to_cb; u->sink_input->moving = sink_input_moving_cb; u->sink_input->volume_changed = sink_input_volume_changed_cb; u->sink_input->mute_changed = sink_input_mute_changed_cb; u->sink_input->userdata = u; pa_sink_put(u->sink); pa_sink_input_put(u->sink_input); pa_modargs_free(ma); pa_xfree(use_default); return 0; fail: if (ma) pa_modargs_free(ma); pa_xfree(use_default); pa__done(m); return -1; }
static void io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event_flags_t events, void*userdata) { struct userdata *u = userdata; char *name = NULL, *code = NULL; pa_assert(io); pa_assert(u); if (events & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) { pa_log("Lost connection to LIRC daemon."); goto fail; } if (events & PA_IO_EVENT_INPUT) { char *c; if (lirc_nextcode(&code) != 0 || !code) { pa_log("lirc_nextcode() failed."); goto fail; } c = pa_xstrdup(code); c[strcspn(c, "\n\r")] = 0; pa_log_debug("Raw IR code '%s'", c); pa_xfree(c); while (lirc_code2char(u->config, code, &name) == 0 && name) { enum { INVALID, UP, DOWN, MUTE, RESET, MUTE_TOGGLE } volchange = INVALID; pa_log_info("Translated IR code '%s'", name); if (strcasecmp(name, "volume-up") == 0) volchange = UP; else if (strcasecmp(name, "volume-down") == 0) volchange = DOWN; else if (strcasecmp(name, "mute") == 0) volchange = MUTE; else if (strcasecmp(name, "mute-toggle") == 0) volchange = MUTE_TOGGLE; else if (strcasecmp(name, "reset") == 0) volchange = RESET; if (volchange == INVALID) pa_log_warn("Received unknown IR code '%s'", name); else { pa_sink *s; if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK))) pa_log("Failed to get sink '%s'", u->sink_name); else { pa_cvolume cv = *pa_sink_get_volume(s, FALSE); switch (volchange) { case UP: pa_cvolume_inc_clamp(&cv, u->volume_step, u->volume_limit); pa_sink_set_volume(s, &cv, TRUE, TRUE); break; case DOWN: pa_cvolume_dec(&cv, u->volume_step); pa_sink_set_volume(s, &cv, TRUE, TRUE); break; case MUTE: pa_sink_set_mute(s, TRUE, TRUE); break; case RESET: pa_sink_set_mute(s, FALSE, TRUE); break; case MUTE_TOGGLE: pa_sink_set_mute(s, !pa_sink_get_mute(s, FALSE), TRUE); break; case INVALID: pa_assert_not_reached(); } } } } } pa_xfree(code); return; fail: u->module->core->mainloop->io_free(u->io); u->io = NULL; pa_module_unload_request(u->module, TRUE); pa_xfree(code); }
static void memblock_free(pa_memblock *b) { pa_assert(b); pa_assert(pa_atomic_load(&b->n_acquired) == 0); stat_remove(b); switch (b->type) { case PA_MEMBLOCK_USER : pa_assert(b->per_type.user.free_cb); b->per_type.user.free_cb(pa_atomic_ptr_load(&b->data)); /* Fall through */ case PA_MEMBLOCK_FIXED: if (pa_flist_push(PA_STATIC_FLIST_GET(unused_memblocks), b) < 0) pa_xfree(b); break; case PA_MEMBLOCK_APPENDED: /* We could attach it to unused_memblocks, but that would * probably waste some considerable amount of memory */ pa_xfree(b); break; case PA_MEMBLOCK_IMPORTED: { pa_memimport_segment *segment; pa_memimport *import; /* FIXME! This should be implemented lock-free */ pa_assert_se(segment = b->per_type.imported.segment); pa_assert_se(import = segment->import); pa_mutex_lock(import->mutex); pa_assert_se(pa_hashmap_remove(import->blocks, PA_UINT32_TO_PTR(b->per_type.imported.id))); pa_assert(segment->n_blocks >= 1); if (-- segment->n_blocks <= 0) segment_detach(segment); pa_mutex_unlock(import->mutex); import->release_cb(import, b->per_type.imported.id, import->userdata); if (pa_flist_push(PA_STATIC_FLIST_GET(unused_memblocks), b) < 0) pa_xfree(b); break; } case PA_MEMBLOCK_POOL_EXTERNAL: case PA_MEMBLOCK_POOL: { struct mempool_slot *slot; bool call_free; pa_assert_se(slot = mempool_slot_by_ptr(b->pool, pa_atomic_ptr_load(&b->data))); call_free = b->type == PA_MEMBLOCK_POOL_EXTERNAL; /* #ifdef HAVE_VALGRIND_MEMCHECK_H */ /* if (PA_UNLIKELY(pa_in_valgrind())) { */ /* VALGRIND_FREELIKE_BLOCK(slot, b->pool->block_size); */ /* } */ /* #endif */ /* The free list dimensions should easily allow all slots * to fit in, hence try harder if pushing this slot into * the free list fails */ while (pa_flist_push(b->pool->free_slots, slot) < 0) ; if (call_free) if (pa_flist_push(PA_STATIC_FLIST_GET(unused_memblocks), b) < 0) pa_xfree(b); break; } case PA_MEMBLOCK_TYPE_MAX: default: pa_assert_not_reached(); } }
static pa_memblock* generate_block(pa_mempool *pool, const pa_sample_spec *ss) { pa_memblock *r; void *d; unsigned i; pa_assert_se(r = pa_memblock_new(pool, pa_frame_size(ss) * 10)); d = pa_memblock_acquire(r); switch (ss->format) { case PA_SAMPLE_U8: case PA_SAMPLE_ULAW: case PA_SAMPLE_ALAW: { uint8_t *u = d; u[0] = 0x00; u[1] = 0xFF; u[2] = 0x7F; u[3] = 0x80; u[4] = 0x9f; u[5] = 0x3f; u[6] = 0x1; u[7] = 0xF0; u[8] = 0x20; u[9] = 0x21; break; } case PA_SAMPLE_S16NE: case PA_SAMPLE_S16RE: { uint16_t *u = d; u[0] = 0x0000; u[1] = 0xFFFF; u[2] = 0x7FFF; u[3] = 0x8000; u[4] = 0x9fff; u[5] = 0x3fff; u[6] = 0x1; u[7] = 0xF000; u[8] = 0x20; u[9] = 0x21; break; } case PA_SAMPLE_S32NE: case PA_SAMPLE_S32RE: { uint32_t *u = d; u[0] = 0x00000001; u[1] = 0xFFFF0002; u[2] = 0x7FFF0003; u[3] = 0x80000004; u[4] = 0x9fff0005; u[5] = 0x3fff0006; u[6] = 0x10007; u[7] = 0xF0000008; u[8] = 0x200009; u[9] = 0x21000A; break; } case PA_SAMPLE_S24_32NE: case PA_SAMPLE_S24_32RE: { uint32_t *u = d; u[0] = 0x000001; u[1] = 0xFF0002; u[2] = 0x7F0003; u[3] = 0x800004; u[4] = 0x9f0005; u[5] = 0x3f0006; u[6] = 0x107; u[7] = 0xF00008; u[8] = 0x2009; u[9] = 0x210A; break; } case PA_SAMPLE_FLOAT32NE: case PA_SAMPLE_FLOAT32RE: { float *u = d; u[0] = 0.0f; u[1] = -1.0f; u[2] = 1.0f; u[3] = 4711.0f; u[4] = 0.222f; u[5] = 0.33f; u[6] = -.3f; u[7] = 99.0f; u[8] = -0.555f; u[9] = -.123f; if (ss->format == PA_SAMPLE_FLOAT32RE) for (i = 0; i < 10; i++) u[i] = PA_FLOAT32_SWAP(u[i]); break; } case PA_SAMPLE_S24NE: case PA_SAMPLE_S24RE: { uint8_t *u = d; PA_WRITE24NE(u, 0x000001); PA_WRITE24NE(u+3, 0xFF0002); PA_WRITE24NE(u+6, 0x7F0003); PA_WRITE24NE(u+9, 0x800004); PA_WRITE24NE(u+12, 0x9f0005); PA_WRITE24NE(u+15, 0x3f0006); PA_WRITE24NE(u+18, 0x107); PA_WRITE24NE(u+21, 0xF00008); PA_WRITE24NE(u+24, 0x2009); PA_WRITE24NE(u+27, 0x210A); break; } default: pa_assert_not_reached(); } pa_memblock_release(r); return r; }
static int handle_response(struct userdata *u) { pa_assert(u); switch (u->state) { case STATE_AUTH: pa_assert(u->read_length == sizeof(int32_t)); /* Process auth data */ if (!*(int32_t*) u->read_data) { pa_log("Authentication failed: %s", pa_cstrerror(errno)); return -1; } /* Request latency data */ pa_assert(!u->write_data); *(int32_t*) (u->write_data = pa_xmalloc(u->write_length = sizeof(int32_t))) = ESD_PROTO_LATENCY; u->write_index = 0; u->state = STATE_LATENCY; /* Space for next response */ pa_assert(u->read_length >= sizeof(int32_t)); u->read_index = 0; u->read_length = sizeof(int32_t); break; case STATE_LATENCY: { int32_t *p; pa_assert(u->read_length == sizeof(int32_t)); /* Process latency info */ u->latency = (pa_usec_t) ((double) (*(int32_t*) u->read_data) * 1000000 / 44100); if (u->latency > 10000000) { pa_log_warn("Invalid latency information received from server"); u->latency = 0; } /* Create stream */ pa_assert(!u->write_data); p = u->write_data = pa_xmalloc0(u->write_length = sizeof(int32_t)*3+ESD_NAME_MAX); *(p++) = ESD_PROTO_STREAM_PLAY; *(p++) = u->format; *(p++) = u->rate; pa_strlcpy((char*) p, "PulseAudio Tunnel", ESD_NAME_MAX); u->write_index = 0; u->state = STATE_PREPARE; /* Don't read any further */ pa_xfree(u->read_data); u->read_data = NULL; u->read_index = u->read_length = 0; break; } default: pa_assert_not_reached(); } 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; pa_assert(pd); pa_assert(c); pa_assert(c->state == PA_CONTEXT_AUTHORIZING || c->state == PA_CONTEXT_SETTING_NAME); pa_context_ref(c); if (command != PA_COMMAND_REPLY) { pa_context_handle_error(c, command, t, TRUE); goto finish; } switch(c->state) { case PA_CONTEXT_AUTHORIZING: { pa_tagstruct *reply; pa_bool_t shm_on_remote = FALSE; 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; } /* Starting with protocol version 13 the MSB of the version tag reflects if shm is available for this connection or not. */ if (c->version >= 13) { shm_on_remote = !!(c->version & 0x80000000U); c->version &= 0x7FFFFFFFU; } pa_log_debug("Protocol version: remote %u, local %u", c->version, PA_PROTOCOL_VERSION); /* Enable shared memory support if possible */ if (c->do_shm) if (c->version < 10 || (c->version >= 13 && !shm_on_remote)) c->do_shm = FALSE; if (c->do_shm) { /* 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)) || getuid() != creds->uid) c->do_shm = FALSE; #endif } pa_log_debug("Negotiated SHM: %s", pa_yes_no(c->do_shm)); pa_pstream_enable_shm(c->pstream, c->do_shm); reply = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag); if (c->version >= 13) { pa_init_proplist(c->proplist); pa_tagstruct_put_proplist(reply, c->proplist); } else pa_tagstruct_puts(reply, pa_proplist_gets(c->proplist, PA_PROP_APPLICATION_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 : if ((c->version >= 13 && (pa_tagstruct_getu32(t, &c->client_index) < 0 || c->client_index == PA_INVALID_INDEX)) || !pa_tagstruct_eof(t)) { pa_context_fail(c, PA_ERR_PROTOCOL); goto finish; } pa_context_set_state(c, PA_CONTEXT_READY); break; default: pa_assert_not_reached(); } finish: pa_context_unref(c); }
static void io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_io_event_flags_t events, void*userdata) { struct userdata *u = userdata; pa_assert(io); pa_assert(u); if (events & (PA_IO_EVENT_HANGUP|PA_IO_EVENT_ERROR)) { pa_log("Lost connection to evdev device."); goto fail; } if (events & PA_IO_EVENT_INPUT) { struct input_event ev; if (pa_loop_read(u->fd, &ev, sizeof(ev), &u->fd_type) <= 0) { pa_log("Failed to read from event device: %s", pa_cstrerror(errno)); goto fail; } if (ev.type == EV_KEY && (ev.value == 1 || ev.value == 2)) { enum { INVALID, UP, DOWN, MUTE_TOGGLE } volchange = INVALID; pa_log_debug("Key code=%u, value=%u", ev.code, ev.value); switch (ev.code) { case KEY_VOLUMEDOWN: volchange = DOWN; break; case KEY_VOLUMEUP: volchange = UP; break; case KEY_MUTE: volchange = MUTE_TOGGLE; break; } if (volchange != INVALID) { pa_sink *s; if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK))) pa_log("Failed to get sink '%s'", u->sink_name); else { pa_cvolume cv = *pa_sink_get_volume(s, false); switch (volchange) { case UP: pa_cvolume_inc_clamp(&cv, u->volume_step, u->volume_limit); pa_sink_set_volume(s, &cv, true, true); break; case DOWN: pa_cvolume_dec(&cv, u->volume_step); pa_sink_set_volume(s, &cv, true, true); break; case MUTE_TOGGLE: pa_sink_set_mute(s, !pa_sink_get_mute(s, false), true); break; case INVALID: pa_assert_not_reached(); } } } } } return; fail: u->module->core->mainloop->io_free(u->io); u->io = NULL; pa_module_unload_request(u->module, true); }