/* Raise the priority of the current process as much as possible that * is <= the specified nice level..*/ int pa_raise_priority(int nice_level) { #ifdef HAVE_SYS_RESOURCE_H if (setpriority(PRIO_PROCESS, 0, nice_level) < 0) { int n; for (n = nice_level+1; n < 0; n++) { if (setpriority(PRIO_PROCESS, 0, n) == 0) { pa_log_info("Successfully acquired nice level %i, which is lower than the requested %i.", n, nice_level); return 0; } } pa_log_warn("setpriority(): %s", pa_cstrerror(errno)); return -1; } pa_log_info("Successfully gained nice level %i.", nice_level); #endif #ifdef OS_IS_WIN32 if (nice_level < 0) { if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS)) { pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError()); return .-1; } else
static void the_thread(void *_q) { pa_asyncmsgq *q = _q; int quit = 0; do { int code = 0; pa_assert_se(pa_asyncmsgq_get(q, NULL, &code, NULL, NULL, NULL, 1) == 0); switch (code) { case OPERATION_A: pa_log_info("Operation A"); break; case OPERATION_B: pa_log_info("Operation B"); break; case OPERATION_C: pa_log_info("Operation C"); break; case QUIT: pa_log_info("quit"); quit = 1; break; } pa_asyncmsgq_done(q, 0); } while (!quit); }
static void main_entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata) { struct userdata *u = userdata; pa_assert(u); switch (state) { case AVAHI_ENTRY_GROUP_ESTABLISHED: pa_log_info("Successfully established main service."); break; case AVAHI_ENTRY_GROUP_COLLISION: { char *t; t = avahi_alternative_service_name(u->service_name); pa_log_info("Name collision: renaming main service %s to %s.", u->service_name, t); pa_xfree(u->service_name); u->service_name = t; publish_main_service(u); break; } case AVAHI_ENTRY_GROUP_FAILURE: { pa_log("Failed to register main service: %s", avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g)))); avahi_entry_group_free(g); u->main_entry_group = NULL; break; } case AVAHI_ENTRY_GROUP_UNCOMMITED: case AVAHI_ENTRY_GROUP_REGISTERING: break; } }
int main(int argc, char *argv[]) { pa_asyncmsgq *q; pa_thread *t; pa_assert_se(q = pa_asyncmsgq_new(0)); pa_assert_se(t = pa_thread_new("test", the_thread, q)); pa_log_info("Operation A post"); pa_asyncmsgq_post(q, NULL, OPERATION_A, NULL, 0, NULL, NULL); pa_thread_yield(); pa_log_info("Operation B post"); pa_asyncmsgq_post(q, NULL, OPERATION_B, NULL, 0, NULL, NULL); pa_thread_yield(); pa_log_info("Operation C send"); pa_asyncmsgq_send(q, NULL, OPERATION_C, NULL, 0, NULL); pa_thread_yield(); pa_log_info("Quit post"); pa_asyncmsgq_post(q, NULL, QUIT, NULL, 0, NULL, NULL); pa_thread_free(t); pa_asyncmsgq_unref(q); return 0; }
static void signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { pa_log_info(_("Got signal %s."), pa_sig2str(sig)); switch (sig) { #ifdef SIGUSR1 case SIGUSR1: pa_module_load(userdata, "module-cli", NULL); break; #endif #ifdef SIGUSR2 case SIGUSR2: pa_module_load(userdata, "module-cli-protocol-unix", NULL); break; #endif #ifdef SIGHUP case SIGHUP: { char *c = pa_full_status_string(userdata); pa_log_notice("%s", c); pa_xfree(c); return; } #endif case SIGINT: case SIGTERM: default: pa_log_info(_("Exiting.")); m->quit(m, 1); break; } }
int cmtspeech_create_source_output(struct userdata *u) { pa_source_output_new_data data; char t[256]; pa_assert(u); pa_assert(!u->source); ENTER(); if (u->source_output) { pa_log_info("Create called but output already exists"); return 1; } if (!(u->source = pa_namereg_get(u->core, u->source_name, PA_NAMEREG_SOURCE))) { pa_log_error("Couldn't find source %s", u->source_name); return 2; } if (cmtspeech_check_source_api(u->source)) return 3; pa_source_output_new_data_init(&data); data.driver = __FILE__; data.module = u->module; data.source = u->source; snprintf(t, sizeof(t), "Cellular call up link"); pa_proplist_sets(data.proplist, PA_PROP_MEDIA_NAME, t); snprintf(t, sizeof(t), "phone"); pa_proplist_sets(data.proplist, PA_PROP_MEDIA_ROLE, t); snprintf(t, sizeof(t), "cmtspeech module"); pa_proplist_sets(data.proplist, PA_PROP_APPLICATION_NAME, t); pa_source_output_new_data_set_sample_spec(&data, &u->ss); pa_source_output_new_data_set_channel_map(&data, &u->map); data.flags = PA_SOURCE_OUTPUT_DONT_MOVE|PA_SOURCE_OUTPUT_START_CORKED; pa_source_output_new(&u->source_output, u->core, &data); pa_source_output_new_data_done(&data); if (!u->source_output) { pa_log("Creating cmtspeech source output failed"); return -1; } u->source_output->push = cmtspeech_source_output_push_cb; u->source_output->kill = cmtspeech_source_output_kill_cb; u->source_output->attach = cmtspeech_source_output_attach_cb; u->source_output->detach = cmtspeech_source_output_detach_cb; u->source_output->moving = cmtspeech_source_output_moving_cb; u->source_output->state_change = cmtspeech_source_output_state_change_cb; u->source_output->may_move_to = cmtspeech_source_output_may_move_to_cb; u->source_output->userdata = u; pa_source_output_put(u->source_output); pa_log_info("cmtspeech source-output created"); return 0; }
static void source_set_mute_control(struct userdata *u) { pa_assert(u); pa_assert(u->hw_module && u->hw_module->device); if (u->hw_module->device->set_mic_mute) { pa_log_info("Using hardware mute control for %s", u->source->name); pa_source_set_get_mute_callback(u->source, source_get_mute_cb); pa_source_set_set_mute_callback(u->source, source_set_mute_cb); } else { pa_log_info("Using software mute control for %s", u->source->name); pa_source_set_get_mute_callback(u->source, NULL); pa_source_set_set_mute_callback(u->source, NULL); } }
static int unsuspend(struct userdata *u) { pa_assert(u); pa_assert(u->fd < 0); pa_log_info("Resuming..."); if (open_audio_device(u, u->sink ? &u->sink->sample_spec : &u->source->sample_spec) < 0) return -1; build_pollfd(u); pa_log_info("Device resumed."); return 0; }
void cmtspeech_delete_sink_input(struct userdata *u) { pa_assert(u); ENTER(); if (!u->sink_input) { pa_log_info("Delete called but no sink input exists"); return; } pa_sink_input_unlink(u->sink_input); pa_sink_input_unref(u->sink_input); u->sink_input = NULL; pa_log_info("cmtspeech sink-input deleted"); }
/* Called from IO context */ static int suspend(struct userdata *u) { pa_assert(u); pa_assert(u->fd >= 0); pa_log_info("Suspending..."); if (u->out_mmap_memblocks) { unsigned i; for (i = 0; i < u->out_nfrags; i++) if (u->out_mmap_memblocks[i]) { pa_memblock_unref_fixed(u->out_mmap_memblocks[i]); u->out_mmap_memblocks[i] = NULL; } } if (u->in_mmap_memblocks) { unsigned i; for (i = 0; i < u->in_nfrags; i++) if (u->in_mmap_memblocks[i]) { pa_memblock_unref_fixed(u->in_mmap_memblocks[i]); u->in_mmap_memblocks[i] = NULL; } } if (u->in_mmap && u->in_mmap != MAP_FAILED) { munmap(u->in_mmap, u->in_hwbuf_size); u->in_mmap = NULL; } if (u->out_mmap && u->out_mmap != MAP_FAILED) { munmap(u->out_mmap, u->out_hwbuf_size); u->out_mmap = NULL; } /* Let's suspend */ ioctl(u->fd, SNDCTL_DSP_SYNC, NULL); pa_close(u->fd); u->fd = -1; if (u->rtpoll_item) { pa_rtpoll_item_free(u->rtpoll_item); u->rtpoll_item = NULL; } pa_log_info("Device suspended..."); return 0; }
void pa_client_free(pa_client *c) { pa_core *core; pa_assert(c); pa_assert(c->core); core = c->core; pa_hook_fire(&core->hooks[PA_CORE_HOOK_CLIENT_UNLINK], c); pa_idxset_remove_by_data(c->core->clients, c, NULL); pa_log_info("Freed %u \"%s\"", c->index, pa_strnull(pa_proplist_gets(c->proplist, PA_PROP_APPLICATION_NAME))); pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_REMOVE, c->index); pa_assert(pa_idxset_isempty(c->sink_inputs)); pa_idxset_free(c->sink_inputs, NULL); pa_assert(pa_idxset_isempty(c->source_outputs)); pa_idxset_free(c->source_outputs, NULL); pa_proplist_free(c->proplist); pa_xfree(c->driver); pa_xfree(c); pa_core_check_idle(core); }
static pa_hook_result_t source_new_hook_callback(pa_core *c, pa_source_new_data *new_data, struct userdata *u) { char *name; struct entry *e; pa_assert(c); pa_assert(new_data); pa_assert(u); pa_assert(u->restore_port); name = pa_sprintf_malloc("source:%s", new_data->name); if ((e = read_entry(u, name))) { if (e->port_valid) { if (!new_data->active_port) { pa_log_info("Restoring port for source %s.", name); pa_source_new_data_set_port(new_data, e->port); new_data->save_port = TRUE; } else pa_log_debug("Not restoring port for source %s, because already set.", name); } pa_xfree(e); } pa_xfree(name); return PA_HOOK_OK; }
static pa_hook_result_t put_hook_callback(pa_core *c, pa_sink *sink, void* userdata) { struct userdata *u = userdata; pa_assert(c); pa_assert(sink); pa_assert(u); /* This is us detecting ourselves on load... just ignore this. */ if (u->ignore) return PA_HOOK_OK; /* There's no point in doing anything if the core is shut down anyway */ if (c->state == PA_CORE_SHUTDOWN) return PA_HOOK_OK; /* Auto-loaded null-sink not active, so ignoring newly detected sink. */ if (u->null_module == PA_INVALID_INDEX) return PA_HOOK_OK; /* This is us detecting ourselves on load in a different way... just ignore this too. */ if (sink->module && sink->module->index == u->null_module) return PA_HOOK_OK; pa_log_info("A new sink has been discovered. Unloading null-sink."); pa_module_unload_request_by_index(c, u->null_module, TRUE); u->null_module = PA_INVALID_INDEX; return PA_HOOK_OK; }
static void setup_context(pa_context *c, pa_iochannel *io) { uint8_t cookie[PA_NATIVE_COOKIE_LENGTH]; pa_tagstruct *t; uint32_t tag; pa_assert(c); pa_assert(io); pa_context_ref(c); 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_receive_packet_callback(c->pstream, pstream_packet_callback, c); pa_pstream_set_receive_memblock_callback(c->pstream, pstream_memblock_callback, c); pa_assert(!c->pdispatch); c->pdispatch = pa_pdispatch_new(c->mainloop, c->use_rtclock, command_table, PA_COMMAND_MAX); if (pa_client_conf_load_cookie(c->conf, cookie, sizeof(cookie)) < 0) pa_log_info("No cookie loaded. Attempting to connect without."); t = pa_tagstruct_command(c, PA_COMMAND_AUTH, &tag); c->do_shm = pa_mempool_is_shared(c->mempool) && c->is_local; pa_log_debug("SHM possible: %s", pa_yes_no(c->do_shm)); /* Starting with protocol version 13 we use the MSB of the version * tag for informing the other side if we could do SHM or not. * Starting from version 31, second MSB is used to flag memfd support. */ pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION | (c->do_shm ? 0x80000000U : 0) | (c->memfd_on_local ? 0x40000000 : 0)); pa_tagstruct_put_arbitrary(t, cookie, sizeof(cookie)); #ifdef HAVE_CREDS { 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(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); pa_context_unref(c); }
void pa_core_maybe_vacuum(pa_core *c) { pa_assert(c); if (pa_idxset_isempty(c->sink_inputs) && pa_idxset_isempty(c->source_outputs)) { pa_log_debug("Hmm, no streams around, trying to vacuum."); } else { pa_sink *si; pa_source *so; uint32_t idx; idx = 0; PA_IDXSET_FOREACH(si, c->sinks, idx) if (pa_sink_get_state(si) != PA_SINK_SUSPENDED) return; idx = 0; PA_IDXSET_FOREACH(so, c->sources, idx) if (pa_source_get_state(so) != PA_SOURCE_SUSPENDED) return; pa_log_info("All sinks and sources are suspended, vacuuming memory"); } pa_mempool_vacuum(c->mempool); if (c->rw_mempool) pa_mempool_vacuum(c->rw_mempool); }
/* Called from output thread context */ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) { struct userdata *u; pa_sink_input_assert_ref(i); pa_sink_input_assert_io_context(i); pa_assert_se(u = i->userdata); pa_assert(chunk); u->in_pop = TRUE; while (pa_asyncmsgq_process_one(u->asyncmsgq) > 0) ; u->in_pop = FALSE; if (pa_memblockq_peek(u->memblockq, chunk) < 0) { pa_log_info("Could not peek into queue"); return -1; } chunk->length = PA_MIN(chunk->length, nbytes); pa_memblockq_drop(u->memblockq, chunk->length); update_min_memblockq_length(u); return 0; }
static void exit_callback(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) { pa_core *c = userdata; pa_assert(c->exit_event == e); pa_log_info("We are idle, quitting..."); pa_core_exit(c, true, 0); }
static void register_profile_reply(DBusPendingCall *pending, void *userdata) { DBusMessage *r; pa_dbus_pending *p; pa_bluetooth_backend *b; char *profile; pa_assert(pending); pa_assert_se(p = userdata); pa_assert_se(b = p->context_data); pa_assert_se(profile = p->call_data); pa_assert_se(r = dbus_pending_call_steal_reply(pending)); if (dbus_message_is_error(r, BLUEZ_ERROR_NOT_SUPPORTED)) { pa_log_info("Couldn't register profile %s because it is disabled in BlueZ", profile); goto finish; } if (dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR) { pa_log_error(BLUEZ_PROFILE_MANAGER_INTERFACE ".RegisterProfile() failed: %s: %s", dbus_message_get_error_name(r), pa_dbus_get_error_message(r)); goto finish; } finish: dbus_message_unref(r); PA_LLIST_REMOVE(pa_dbus_pending, b->pending, p); pa_dbus_pending_free(p); pa_xfree(profile); }
static int jack_buffer_size(jack_nframes_t nframes, void *arg) { struct userdata *u = arg; pa_log_info("JACK buffer size changed."); pa_asyncmsgq_post(u->jack_msgq, PA_MSGOBJECT(u->sink), SINK_MESSAGE_BUFFER_SIZE, NULL, nframes, NULL, NULL); return 0; }
pa_client *pa_client_new(pa_core *core, pa_client_new_data *data) { pa_client *c; pa_core_assert_ref(core); pa_assert(data); if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_CLIENT_NEW], data) < 0) return NULL; c = pa_xnew(pa_client, 1); c->core = core; c->proplist = pa_proplist_copy(data->proplist); c->driver = pa_xstrdup(pa_path_get_filename(data->driver)); c->module = data->module; c->sink_inputs = pa_idxset_new(NULL, NULL); c->source_outputs = pa_idxset_new(NULL, NULL); c->userdata = NULL; c->kill = NULL; c->send_event = NULL; pa_assert_se(pa_idxset_put(core->clients, c, &c->index) >= 0); pa_log_info("Created %u \"%s\"", c->index, pa_strnull(pa_proplist_gets(c->proplist, PA_PROP_APPLICATION_NAME))); pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_NEW, c->index); pa_hook_fire(&core->hooks[PA_CORE_HOOK_CLIENT_PUT], c); pa_core_check_idle(core); return c; }
int pa__init (pa_module *m) { struct userdata *u; u = pa_xnew (struct userdata, 1); u->c = m->core; u->m = m; /* connect hooks */ u->sink_input_new_cb = HOOK_CONNECT(m, PA_CORE_HOOK_SINK_INPUT_NEW, PA_HOOK_EARLY, sink_input_new_callback, u); u->sink_input_fixate_cb = HOOK_CONNECT(m, PA_CORE_HOOK_SINK_INPUT_FIXATE, PA_HOOK_EARLY, sink_input_fixate_callback, u); u->sink_input_put_cb = HOOK_CONNECT(m, PA_CORE_HOOK_SINK_INPUT_PUT, PA_HOOK_EARLY, sink_input_put_callback, u); u->sink_input_state_changed_cb = HOOK_CONNECT(m, PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED, PA_HOOK_EARLY, sink_input_state_changed_callback, u); u->sink_input_unlink_cb = HOOK_CONNECT(m, PA_CORE_HOOK_SINK_INPUT_UNLINK, PA_HOOK_EARLY, sink_input_unlink_callback, u); u->sink_input_unlink_post_cb = HOOK_CONNECT(m, PA_CORE_HOOK_SINK_INPUT_UNLINK, PA_HOOK_EARLY, sink_input_unlink_post_callback, u); pa_log_info ("pa_core(%p) : pa_module(%p)\n", u->c, u->m); return 0; }
static void packet_test(unsigned npackets, size_t plength, pa_mainloop *ml, pa_pstream *p1, pa_pstream *p2) { pa_packet *packet = pa_packet_new(plength); unsigned i; unsigned psum = 0, totalsum = 0; uint8_t *pdata; size_t plen; pa_log_info("Sending %d packets of length %zd", npackets, plength); packets_received = 0; packets_checksum = 0; packets_length = plength; pa_pstream_set_receive_packet_callback(p2, packet_received, NULL); pdata = (uint8_t *) pa_packet_data(packet, &plen); for (i = 0; i < plen; i++) { pdata[i] = i; psum += pdata[i]; } for (i = 0; i < npackets; i++) { pa_pstream_send_packet(p1, packet, NULL); totalsum += psum; pa_mainloop_iterate(ml, 0, NULL); } while (packets_received < npackets) pa_mainloop_iterate(ml, 1, NULL); fail_unless(packets_checksum == totalsum); pa_log_debug("Correct checksum received (%d)", packets_checksum); pa_packet_unref(packet); }
void pa_rtclock_hrtimer_enable(void) { #ifdef PR_SET_TIMERSLACK int slack_ns; if ((slack_ns = prctl(PR_GET_TIMERSLACK, 0, 0, 0, 0)) < 0) { pa_log_info("PR_GET_TIMERSLACK/PR_SET_TIMERSLACK not supported."); return; } pa_log_debug("Timer slack is set to %i us.", (int) (slack_ns/PA_NSEC_PER_USEC)); if (slack_ns > TIMER_SLACK_NS) { slack_ns = TIMER_SLACK_NS; pa_log_debug("Setting timer slack to %i us.", (int) (slack_ns/PA_NSEC_PER_USEC)); if (prctl(PR_SET_TIMERSLACK, slack_ns, 0, 0, 0) < 0) { pa_log_warn("PR_SET_TIMERSLACK failed: %s", pa_cstrerror(errno)); return; } } #elif defined(OS_IS_WIN32) LARGE_INTEGER freq; pa_assert_se(QueryPerformanceFrequency(&freq)); counter_freq = freq.QuadPart; #endif }
static int proc_name_ours(pid_t pid, const char *procname) { #ifdef __linux__ char bn[PATH_MAX]; FILE *f; pa_snprintf(bn, sizeof(bn), "/proc/%lu/stat", (unsigned long) pid); if (!(f = pa_fopen_cloexec(bn, "r"))) { pa_log_info("Failed to open %s: %s", bn, pa_cstrerror(errno)); return -1; } else { char *expected; pa_bool_t good; char stored[64]; if (!(fgets(stored, sizeof(stored), f))) { int saved_errno = feof(f) ? EINVAL : errno; pa_log_info("Failed to read from %s: %s", bn, feof(f) ? "EOF" : pa_cstrerror(errno)); fclose(f); errno = saved_errno; return -1; } fclose(f); expected = pa_sprintf_malloc("%lu (%s)", (unsigned long) pid, procname); good = pa_startswith(stored, expected); pa_xfree(expected); /*#if !defined(__OPTIMIZE__)*/ if (!good) { /* libtool likes to rename our binary names ... */ expected = pa_sprintf_malloc("%lu (lt-%s)", (unsigned long) pid, procname); good = pa_startswith(stored, expected); pa_xfree(expected); } /*#endif*/ return !!good; } #else return 1; #endif }
/* Called from main context */ static void adjust_rates(struct userdata *u) { size_t buffer, fs; uint32_t old_rate, base_rate, new_rate; pa_usec_t buffer_latency; pa_assert(u); pa_assert_ctl_context(); pa_asyncmsgq_send(u->source_output->source->asyncmsgq, PA_MSGOBJECT(u->source_output), SOURCE_OUTPUT_MESSAGE_LATENCY_SNAPSHOT, NULL, 0, NULL); pa_asyncmsgq_send(u->sink_input->sink->asyncmsgq, PA_MSGOBJECT(u->sink_input), SINK_INPUT_MESSAGE_LATENCY_SNAPSHOT, NULL, 0, NULL); buffer = u->latency_snapshot.sink_input_buffer + u->latency_snapshot.source_output_buffer; if (u->latency_snapshot.recv_counter <= u->latency_snapshot.send_counter) buffer += (size_t) (u->latency_snapshot.send_counter - u->latency_snapshot.recv_counter); else buffer += PA_CLIP_SUB(buffer, (size_t) (u->latency_snapshot.recv_counter - u->latency_snapshot.send_counter)); buffer_latency = pa_bytes_to_usec(buffer, &u->sink_input->sample_spec); pa_log_info("Loopback overall latency is %0.2f ms + %0.2f ms + %0.2f ms = %0.2f ms", (double) u->latency_snapshot.sink_latency / PA_USEC_PER_MSEC, (double) buffer_latency / PA_USEC_PER_MSEC, (double) u->latency_snapshot.source_latency / PA_USEC_PER_MSEC, ((double) u->latency_snapshot.sink_latency + buffer_latency + u->latency_snapshot.source_latency) / PA_USEC_PER_MSEC); pa_log_info("Should buffer %zu bytes, buffered at minimum %zu bytes", u->latency_snapshot.max_request*2, u->latency_snapshot.min_memblockq_length); fs = pa_frame_size(&u->sink_input->sample_spec); old_rate = u->sink_input->sample_spec.rate; base_rate = u->source_output->sample_spec.rate; if (u->latency_snapshot.min_memblockq_length < u->latency_snapshot.max_request*2) new_rate = base_rate - (((u->latency_snapshot.max_request*2 - u->latency_snapshot.min_memblockq_length) / fs) *PA_USEC_PER_SEC)/u->adjust_time; else new_rate = base_rate + (((u->latency_snapshot.min_memblockq_length - u->latency_snapshot.max_request*2) / fs) *PA_USEC_PER_SEC)/u->adjust_time; pa_log_info("Old rate %lu Hz, new rate %lu Hz", (unsigned long) old_rate, (unsigned long) new_rate); pa_sink_input_set_rate(u->sink_input, new_rate); pa_core_rttime_restart(u->core, u->time_event, pa_rtclock_now() + u->adjust_time); }
static void thread_func(void *data) { pa_tls_set(tls, data); pa_log_info("thread_func() for %s starting...", (char*) pa_tls_get(tls)); pa_mutex_lock(mutex); for (;;) { int k, n; pa_log_info("%s waiting ...", (char*) pa_tls_get(tls)); for (;;) { if (magic_number < 0) goto quit; if (magic_number != 0) break; pa_cond_wait(cond1, mutex); } k = magic_number; magic_number = 0; pa_mutex_unlock(mutex); pa_run_once(&once, once_func); pa_cond_signal(cond2, 0); pa_log_info("%s got number %i", (char*) pa_tls_get(tls), k); /* Spin! */ for (n = 0; n < k; n++) pa_thread_yield(); pa_mutex_lock(mutex); } quit: pa_mutex_unlock(mutex); pa_log_info("thread_func() for %s done...", (char*) pa_tls_get(tls)); }
static int bluez5_sco_acquire_cb(pa_bluetooth_transport *t, bool optional, size_t *imtu, size_t *omtu) { pa_bluetooth_device *d = t->device; struct sockaddr_sco addr; int err, i; int sock; bdaddr_t src; bdaddr_t dst; const char *src_addr, *dst_addr; src_addr = d->adapter->address; dst_addr = d->address; /* don't use ba2str to avoid -lbluetooth */ for (i = 5; i >= 0; i--, src_addr += 3) src.b[i] = strtol(src_addr, NULL, 16); for (i = 5; i >= 0; i--, dst_addr += 3) dst.b[i] = strtol(dst_addr, NULL, 16); sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO); if (sock < 0) { pa_log_error("socket(SEQPACKET, SCO) %s", pa_cstrerror(errno)); return -1; } memset(&addr, 0, sizeof(addr)); addr.sco_family = AF_BLUETOOTH; bacpy(&addr.sco_bdaddr, &src); if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { pa_log_error("bind(): %s", pa_cstrerror(errno)); goto fail_close; } memset(&addr, 0, sizeof(addr)); addr.sco_family = AF_BLUETOOTH; bacpy(&addr.sco_bdaddr, &dst); pa_log_info ("doing connect\n"); err = connect(sock, (struct sockaddr *) &addr, sizeof(addr)); if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) { pa_log_error("connect(): %s", pa_cstrerror(errno)); goto fail_close; } /* The "48" below is hardcoded until we get meaningful MTU values exposed * by the kernel */ if (imtu) *imtu = 48; if (omtu) *omtu = 48; return sock; fail_close: close(sock); return -1; }
/* Called from main context */ static void adjust_rates(struct userdata *u) { size_t buffer, fs; uint32_t old_rate, base_rate, new_rate; pa_usec_t buffer_latency; pa_assert(u); pa_assert_ctl_context(); pa_asyncmsgq_send(u->source_output->source->asyncmsgq, PA_MSGOBJECT(u->source_output), SOURCE_OUTPUT_MESSAGE_LATENCY_SNAPSHOT, NULL, 0, NULL); pa_asyncmsgq_send(u->sink_input->sink->asyncmsgq, PA_MSGOBJECT(u->sink_input), SINK_INPUT_MESSAGE_LATENCY_SNAPSHOT, NULL, 0, NULL); buffer = u->latency_snapshot.sink_input_buffer + u->latency_snapshot.source_output_buffer; if (u->latency_snapshot.recv_counter <= u->latency_snapshot.send_counter) buffer += (size_t) (u->latency_snapshot.send_counter - u->latency_snapshot.recv_counter); else buffer += PA_CLIP_SUB(buffer, (size_t) (u->latency_snapshot.recv_counter - u->latency_snapshot.send_counter)); buffer_latency = pa_bytes_to_usec(buffer, &u->sink_input->sample_spec); pa_log_debug("Loopback overall latency is %0.2f ms + %0.2f ms + %0.2f ms = %0.2f ms", (double) u->latency_snapshot.sink_latency / PA_USEC_PER_MSEC, (double) buffer_latency / PA_USEC_PER_MSEC, (double) u->latency_snapshot.source_latency / PA_USEC_PER_MSEC, ((double) u->latency_snapshot.sink_latency + buffer_latency + u->latency_snapshot.source_latency) / PA_USEC_PER_MSEC); pa_log_debug("Should buffer %zu bytes, buffered at minimum %zu bytes", u->latency_snapshot.max_request*2, u->latency_snapshot.min_memblockq_length); fs = pa_frame_size(&u->sink_input->sample_spec); old_rate = u->sink_input->sample_spec.rate; base_rate = u->source_output->sample_spec.rate; if (u->latency_snapshot.min_memblockq_length < u->latency_snapshot.max_request*2) new_rate = base_rate - (((u->latency_snapshot.max_request*2 - u->latency_snapshot.min_memblockq_length) / fs) *PA_USEC_PER_SEC)/u->adjust_time; else new_rate = base_rate + (((u->latency_snapshot.min_memblockq_length - u->latency_snapshot.max_request*2) / fs) *PA_USEC_PER_SEC)/u->adjust_time; if (new_rate < (uint32_t) (base_rate*0.8) || new_rate > (uint32_t) (base_rate*1.25)) { pa_log_warn("Sample rates too different, not adjusting (%u vs. %u).", base_rate, new_rate); new_rate = base_rate; } else { if (base_rate < new_rate + 20 && new_rate < base_rate + 20) new_rate = base_rate; /* Do the adjustment in small steps; 2‰ can be considered inaudible */ if (new_rate < (uint32_t) (old_rate*0.998) || new_rate > (uint32_t) (old_rate*1.002)) { pa_log_info("New rate of %u Hz not within 2‰ of %u Hz, forcing smaller adjustment", new_rate, old_rate); new_rate = PA_CLAMP(new_rate, (uint32_t) (old_rate*0.998), (uint32_t) (old_rate*1.002)); } } pa_sink_input_set_rate(u->sink_input, new_rate); pa_log_debug("[%s] Updated sampling rate to %lu Hz.", u->sink_input->sink->name, (unsigned long) new_rate); pa_core_rttime_restart(u->core, u->time_event, pa_rtclock_now() + u->adjust_time); }
void pa_cpu_init_arm (void) { #if defined (__arm__) #if defined (__linux__) char *cpuinfo, *line; int arch; pa_cpu_arm_flag_t flags = 0; /* We need to read the CPU flags from /proc/cpuinfo because there is no user * space support to get the CPU features. This only works on linux AFAIK. */ if (!(cpuinfo = get_cpuinfo ())) { pa_log ("Can't read cpuinfo"); return; } /* get the CPU architecture */ if ((line = get_cpuinfo_line (cpuinfo, "CPU architecture"))) { arch = strtoul (line, NULL, 0); if (arch >= 6) flags |= PA_CPU_ARM_V6; if (arch >= 7) flags |= PA_CPU_ARM_V7; pa_xfree(line); } /* get the CPU features */ if ((line = get_cpuinfo_line (cpuinfo, "Features"))) { const char *state = NULL; char *current; while ((current = pa_split_spaces (line, &state))) { if (!strcmp (current, "vfp")) flags |= PA_CPU_ARM_VFP; else if (!strcmp (current, "edsp")) flags |= PA_CPU_ARM_EDSP; else if (!strcmp (current, "neon")) flags |= PA_CPU_ARM_NEON; else if (!strcmp (current, "vfpv3")) flags |= PA_CPU_ARM_VFPV3; pa_xfree(current); } } pa_xfree(cpuinfo); pa_log_info ("CPU flags: %s%s%s%s%s%s", (flags & PA_CPU_ARM_V6) ? "V6 " : "", (flags & PA_CPU_ARM_V7) ? "V7 " : "", (flags & PA_CPU_ARM_VFP) ? "VFP " : "", (flags & PA_CPU_ARM_EDSP) ? "EDSP " : "", (flags & PA_CPU_ARM_NEON) ? "NEON " : "", (flags & PA_CPU_ARM_VFPV3) ? "VFPV3 " : ""); #else /* defined (__linux__) */ pa_log ("ARM cpu features not yet supported on this OS"); #endif /* defined (__linux__) */ if (flags & PA_CPU_ARM_V6) pa_volume_func_init_arm (flags); #endif /* defined (__arm__) */ }
static void jack_init(void *arg) { struct userdata *u = arg; pa_log_info("JACK thread starting up."); if (u->core->realtime_scheduling) pa_make_realtime(u->core->realtime_priority+4); }