/* 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(); }
pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *name, pa_proplist *p) { pa_context *c; pa_assert(mainloop); if (pa_detect_fork()) return NULL; pa_init_i18n(); c = pa_xnew0(pa_context, 1); PA_REFCNT_INIT(c); c->proplist = p ? pa_proplist_copy(p) : pa_proplist_new(); if (name) pa_proplist_sets(c->proplist, PA_PROP_APPLICATION_NAME, name); #ifdef HAVE_DBUS c->system_bus = c->session_bus = NULL; #endif c->mainloop = mainloop; c->playback_streams = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); c->record_streams = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); c->client_index = PA_INVALID_INDEX; c->use_rtclock = pa_mainloop_is_our_api(mainloop); 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; reset_callbacks(c); #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, true, true); c->srb_template.readfd = -1; c->srb_template.writefd = -1; if (!(c->mempool = pa_mempool_new(!c->conf->disable_shm, c->conf->shm_size))) { if (!c->conf->disable_shm) c->mempool = pa_mempool_new(false, c->conf->shm_size); if (!c->mempool) { context_free(c); return NULL; } } return c; }
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; }
void SinkInput::sink_input_cb(pa_context *, const pa_sink_input_info *i, int eol, void *userdata) { cout << "SinkInput::sink_cb" << endl; SinkInput *p = reinterpret_cast<SinkInput *>(userdata); SinkInput::Private *dd = p->d; if (eol) return; if (!i) { cout << "Sink callback failure" << endl; return; } if ( dd->valid ) assert ( i->index == dd->index ); //p->mSinkInfo = *i; dd->name = QString(i->name); dd->sampleSpec = i->sample_spec; dd->channelMap = i->channel_map; dd->owner = i->owner_module; dd->volume = i->volume; dd->muted = i->mute; dd->driver = QString(i->driver); dd->valid = true; if(dd->proplist != 0) pa_proplist_free(dd->proplist); dd->proplist = pa_proplist_copy(i->proplist); //std::cout << pa_proplist_to_string(dd->proplist) << std::endl; emit p->updated(); }
pa_format_info* pa_format_info_copy(const pa_format_info *src) { pa_format_info *dest; pa_assert(src); dest = pa_xnew(pa_format_info, 1); dest->encoding = src->encoding; if (src->plist) dest->plist = pa_proplist_copy(src->plist); else dest->plist = NULL; return dest; }
void Source::source_cb(pa_context *, const pa_source_info *i, int eol, void *userdata) { cout << "Source::source_cb" << endl; Source *p = reinterpret_cast<Source *>(userdata); Device::Private *dd = p->Device::d; if (eol) return; if (!i) { cout << "Source callback failure" << endl; return; } if ( dd->valid ) assert ( i->index == dd->index ); //p->mSourceInfo = *i; cout << i->name << " " << i->description << endl; dd->name = QString(i->name); dd->description = QString(i->description); dd->sampleSpec = i->sample_spec; dd->channelMap = i->channel_map; dd->owner = i->owner_module; dd->volume = i->volume; dd->muted = i->mute; dd->monitor= i->monitor_of_sink; dd->monitorName = QString(i->monitor_of_sink_name); dd->latency = i->latency; dd->driver = QString(i->driver); dd->baseVolume = i->base_volume; dd->card = i->card; dd->configuredLatency = i->configured_latency; dd->valid = true; if(dd->proplist != 0) pa_proplist_free(dd->proplist); dd->proplist = pa_proplist_copy(i->proplist); emit p->updated(); }
/* Called from main context */ pa_source* pa_source_new( pa_core *core, pa_source_new_data *data, pa_source_flags_t flags) { pa_source *s; const char *name; char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; char *pt; pa_assert(core); pa_assert(data); pa_assert(data->name); pa_assert_ctl_context(); s = pa_msgobject_new(pa_source); if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_SOURCE, s, data->namereg_fail))) { pa_log_debug("Failed to register name %s.", data->name); pa_xfree(s); return NULL; } pa_source_new_data_set_name(data, name); if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_NEW], data) < 0) { pa_xfree(s); pa_namereg_unregister(core, name); return NULL; } /* FIXME, need to free s here on failure */ pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver)); pa_return_null_if_fail(data->name && pa_utf8_valid(data->name) && data->name[0]); pa_return_null_if_fail(data->sample_spec_is_set && pa_sample_spec_valid(&data->sample_spec)); if (!data->channel_map_is_set) pa_return_null_if_fail(pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT)); pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map)); pa_return_null_if_fail(data->channel_map.channels == data->sample_spec.channels); if (!data->volume_is_set) pa_cvolume_reset(&data->volume, data->sample_spec.channels); pa_return_null_if_fail(pa_cvolume_valid(&data->volume)); pa_return_null_if_fail(pa_cvolume_compatible(&data->volume, &data->sample_spec)); if (!data->muted_is_set) data->muted = FALSE; if (data->card) pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->card->proplist); pa_device_init_description(data->proplist); pa_device_init_icon(data->proplist, FALSE); pa_device_init_intended_roles(data->proplist); if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_FIXATE], data) < 0) { pa_xfree(s); pa_namereg_unregister(core, name); return NULL; } s->parent.parent.free = source_free; s->parent.process_msg = pa_source_process_msg; s->core = core; s->state = PA_SOURCE_INIT; s->flags = flags; s->priority = 0; s->suspend_cause = 0; s->name = pa_xstrdup(name); s->proplist = pa_proplist_copy(data->proplist); s->driver = pa_xstrdup(pa_path_get_filename(data->driver)); s->module = data->module; s->card = data->card; s->priority = pa_device_init_priority(s->proplist); s->sample_spec = data->sample_spec; s->channel_map = data->channel_map; s->outputs = pa_idxset_new(NULL, NULL); s->n_corked = 0; s->monitor_of = NULL; s->output_from_master = NULL; s->volume = data->volume; pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels); s->base_volume = PA_VOLUME_NORM; s->n_volume_steps = PA_VOLUME_NORM+1; s->muted = data->muted; s->refresh_volume = s->refresh_muted = FALSE; reset_callbacks(s); s->userdata = NULL; s->asyncmsgq = NULL; /* As a minor optimization we just steal the list instead of * copying it here */ s->ports = data->ports; data->ports = NULL; s->active_port = NULL; s->save_port = FALSE; if (data->active_port && s->ports) if ((s->active_port = pa_hashmap_get(s->ports, data->active_port))) s->save_port = data->save_port; if (!s->active_port && s->ports) { void *state; pa_device_port *p; PA_HASHMAP_FOREACH(p, s->ports, state) if (!s->active_port || p->priority > s->active_port->priority) s->active_port = p; }
pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *name, pa_proplist *p) { pa_context *c; pa_mem_type_t type; pa_assert(mainloop); if (pa_detect_fork()) return NULL; pa_init_i18n(); c = pa_xnew0(pa_context, 1); PA_REFCNT_INIT(c); c->proplist = p ? pa_proplist_copy(p) : pa_proplist_new(); if (name) pa_proplist_sets(c->proplist, PA_PROP_APPLICATION_NAME, name); #ifdef HAVE_DBUS c->system_bus = c->session_bus = NULL; #endif c->mainloop = mainloop; c->playback_streams = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); c->record_streams = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); c->client_index = PA_INVALID_INDEX; c->use_rtclock = pa_mainloop_is_our_api(mainloop); 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; reset_callbacks(c); #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, true, true); c->srb_template.readfd = -1; c->srb_template.writefd = -1; c->memfd_on_local = (!c->conf->disable_memfd && pa_memfd_is_locally_supported()); type = (c->conf->disable_shm) ? PA_MEM_TYPE_PRIVATE : ((!c->memfd_on_local) ? PA_MEM_TYPE_SHARED_POSIX : PA_MEM_TYPE_SHARED_MEMFD); if (!(c->mempool = pa_mempool_new(type, c->conf->shm_size, true))) { if (!c->conf->disable_shm) { pa_log_warn("Failed to allocate shared memory pool. Falling back to a normal private one."); c->mempool = pa_mempool_new(PA_MEM_TYPE_PRIVATE, c->conf->shm_size, true); } if (!c->mempool) { context_free(c); return NULL; } } return c; }
/* Called from main context */ int pa_source_output_new( pa_source_output**_o, pa_core *core, pa_source_output_new_data *data) { pa_source_output *o; pa_resampler *resampler = NULL; char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; int r; char *pt; pa_assert(_o); pa_assert(core); pa_assert(data); pa_assert_ctl_context(); if (data->client) pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->client->proplist); if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_NEW], data)) < 0) return r; pa_return_val_if_fail(!data->driver || pa_utf8_valid(data->driver), -PA_ERR_INVALID); if (!data->source) { data->source = pa_namereg_get(core, NULL, PA_NAMEREG_SOURCE); data->save_source = FALSE; } pa_return_val_if_fail(data->source, -PA_ERR_NOENTITY); pa_return_val_if_fail(PA_SOURCE_IS_LINKED(pa_source_get_state(data->source)), -PA_ERR_BADSTATE); pa_return_val_if_fail(!data->direct_on_input || data->direct_on_input->sink == data->source->monitor_of, -PA_ERR_INVALID); if (!data->sample_spec_is_set) data->sample_spec = data->source->sample_spec; pa_return_val_if_fail(pa_sample_spec_valid(&data->sample_spec), -PA_ERR_INVALID); if (!data->channel_map_is_set) { if (pa_channel_map_compatible(&data->source->channel_map, &data->sample_spec)) data->channel_map = data->source->channel_map; else pa_channel_map_init_extend(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT); } pa_return_val_if_fail(pa_channel_map_valid(&data->channel_map), -PA_ERR_INVALID); pa_return_val_if_fail(pa_channel_map_compatible(&data->channel_map, &data->sample_spec), -PA_ERR_INVALID); if (data->flags & PA_SOURCE_OUTPUT_FIX_FORMAT) data->sample_spec.format = data->source->sample_spec.format; if (data->flags & PA_SOURCE_OUTPUT_FIX_RATE) data->sample_spec.rate = data->source->sample_spec.rate; if (data->flags & PA_SOURCE_OUTPUT_FIX_CHANNELS) { data->sample_spec.channels = data->source->sample_spec.channels; data->channel_map = data->source->channel_map; } pa_assert(pa_sample_spec_valid(&data->sample_spec)); pa_assert(pa_channel_map_valid(&data->channel_map)); if (data->resample_method == PA_RESAMPLER_INVALID) data->resample_method = core->resample_method; pa_return_val_if_fail(data->resample_method < PA_RESAMPLER_MAX, -PA_ERR_INVALID); if ((r = pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_FIXATE], data)) < 0) return r; if ((data->flags & PA_SOURCE_OUTPUT_NO_CREATE_ON_SUSPEND) && pa_source_get_state(data->source) == PA_SOURCE_SUSPENDED) { pa_log("Failed to create source output: source is suspended."); return -PA_ERR_BADSTATE; } if (pa_idxset_size(data->source->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) { pa_log("Failed to create source output: too many outputs per source."); return -PA_ERR_TOOLARGE; } if ((data->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) || !pa_sample_spec_equal(&data->sample_spec, &data->source->sample_spec) || !pa_channel_map_equal(&data->channel_map, &data->source->channel_map)) { if (!(resampler = pa_resampler_new( core->mempool, &data->source->sample_spec, &data->source->channel_map, &data->sample_spec, &data->channel_map, data->resample_method, ((data->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) | ((data->flags & PA_SOURCE_OUTPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) | (core->disable_remixing || (data->flags & PA_SOURCE_OUTPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) | (core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0)))) { pa_log_warn("Unsupported resampling operation."); return -PA_ERR_NOTSUPPORTED; } } o = pa_msgobject_new(pa_source_output); o->parent.parent.free = source_output_free; o->parent.process_msg = pa_source_output_process_msg; o->core = core; o->state = PA_SOURCE_OUTPUT_INIT; o->flags = data->flags; o->proplist = pa_proplist_copy(data->proplist); o->driver = pa_xstrdup(pa_path_get_filename(data->driver)); o->module = data->module; o->source = data->source; o->destination_source = data->destination_source; o->client = data->client; o->actual_resample_method = resampler ? pa_resampler_get_method(resampler) : PA_RESAMPLER_INVALID; o->requested_resample_method = data->resample_method; o->sample_spec = data->sample_spec; o->channel_map = data->channel_map; o->direct_on_input = data->direct_on_input; o->save_source = data->save_source; reset_callbacks(o); o->userdata = NULL; o->thread_info.state = o->state; o->thread_info.attached = FALSE; o->thread_info.sample_spec = o->sample_spec; o->thread_info.resampler = resampler; o->thread_info.requested_source_latency = (pa_usec_t) -1; o->thread_info.direct_on_input = o->direct_on_input; o->thread_info.delay_memblockq = pa_memblockq_new( 0, MEMBLOCKQ_MAXLENGTH, 0, pa_frame_size(&o->source->sample_spec), 0, 1, 0, &o->source->silence); pa_assert_se(pa_idxset_put(core->source_outputs, o, &o->index) == 0); pa_assert_se(pa_idxset_put(o->source->outputs, pa_source_output_ref(o), NULL) == 0); if (o->client) pa_assert_se(pa_idxset_put(o->client->source_outputs, o, NULL) >= 0); if (o->direct_on_input) pa_assert_se(pa_idxset_put(o->direct_on_input->direct_outputs, o, NULL) == 0); pt = pa_proplist_to_string_sep(o->proplist, "\n "); pa_log_info("Created output %u \"%s\" on %s with sample spec %s and channel map %s\n %s", o->index, pa_strnull(pa_proplist_gets(o->proplist, PA_PROP_MEDIA_NAME)), o->source->name, pa_sample_spec_snprint(st, sizeof(st), &o->sample_spec), pa_channel_map_snprint(cm, sizeof(cm), &o->channel_map), pt); pa_xfree(pt); /* Don't forget to call pa_source_output_put! */ *_o = o; return 0; }