bool pa_speex_ec_init(pa_core *c, pa_echo_canceller *ec, pa_sample_spec *rec_ss, pa_channel_map *rec_map, pa_sample_spec *play_ss, pa_channel_map *play_map, pa_sample_spec *out_ss, pa_channel_map *out_map, uint32_t *nframes, const char *args) { int rate; uint32_t frame_size_ms, filter_size_ms; pa_modargs *ma; if (!(ma = pa_modargs_new(args, valid_modargs))) { pa_log("Failed to parse submodule arguments."); goto fail; } filter_size_ms = DEFAULT_FILTER_SIZE_MS; if (pa_modargs_get_value_u32(ma, "filter_size_ms", &filter_size_ms) < 0 || filter_size_ms < 1 || filter_size_ms > 2000) { pa_log("Invalid filter_size_ms specification"); goto fail; } frame_size_ms = DEFAULT_FRAME_SIZE_MS; if (pa_modargs_get_value_u32(ma, "frame_size_ms", &frame_size_ms) < 0 || frame_size_ms < 1 || frame_size_ms > 200) { pa_log("Invalid frame_size_ms specification"); goto fail; } pa_speex_ec_fixate_spec(rec_ss, rec_map, play_ss, play_map, out_ss, out_map); rate = out_ss->rate; *nframes = pa_echo_canceller_blocksize_power2(rate, frame_size_ms); pa_log_debug ("Using nframes %d, channels %d, rate %d", *nframes, out_ss->channels, out_ss->rate); ec->params.priv.speex.state = speex_echo_state_init_mc(*nframes, (rate * filter_size_ms) / 1000, out_ss->channels, out_ss->channels); if (!ec->params.priv.speex.state) goto fail; speex_echo_ctl(ec->params.priv.speex.state, SPEEX_ECHO_SET_SAMPLING_RATE, &rate); if (!pa_speex_ec_preprocessor_init(ec, out_ss, *nframes, ma)) goto fail; pa_modargs_free(ma); return true; fail: if (ma) pa_modargs_free(ma); if (ec->params.priv.speex.pp_state) { speex_preprocess_state_destroy(ec->params.priv.speex.pp_state); ec->params.priv.speex.pp_state = NULL; } if (ec->params.priv.speex.state) { speex_echo_state_destroy(ec->params.priv.speex.state); ec->params.priv.speex.state = NULL; } return false; }
int pa__init(pa_module*m) { pa_modargs *ma = NULL; struct userdata *u; pa_volume_t volume_limit = PA_CLAMP_VOLUME(PA_VOLUME_NORM*3/2); pa_volume_t volume_step = PA_VOLUME_NORM/20; pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments"); goto fail; } if (pa_modargs_get_value_u32(ma, "volume_limit", &volume_limit) < 0) { pa_log("Failed to parse volume limit"); goto fail; } if (pa_modargs_get_value_u32(ma, "volume_step", &volume_step) < 0) { pa_log("Failed to parse volume step"); goto fail; } m->userdata = u = pa_xnew(struct userdata, 1); u->module = m; u->io = NULL; u->config = NULL; u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); u->lirc_fd = -1; u->mute_toggle_save = 0; u->volume_limit = PA_CLAMP_VOLUME(volume_limit); u->volume_step = PA_CLAMP_VOLUME(volume_step); if ((u->lirc_fd = lirc_init((char*) pa_modargs_get_value(ma, "appname", "pulseaudio"), 1)) < 0) { pa_log("lirc_init() failed."); goto fail; } if (lirc_readconfig((char*) pa_modargs_get_value(ma, "config", NULL), &u->config, NULL) < 0) { pa_log("lirc_readconfig() failed."); goto fail; } u->io = m->core->mainloop->io_new(m->core->mainloop, u->lirc_fd, PA_IO_EVENT_INPUT|PA_IO_EVENT_HANGUP, io_callback, u); pa_modargs_free(ma); return 0; fail: if (ma) pa_modargs_free(ma); pa__done(m); return -1; }
pa_bool_t pa_speex_ec_init(pa_core *c, pa_echo_canceller *ec, pa_sample_spec *source_ss, pa_channel_map *source_map, pa_sample_spec *sink_ss, pa_channel_map *sink_map, uint32_t *blocksize, const char *args) { int framelen, y, rate; uint32_t frame_size_ms, filter_size_ms; pa_modargs *ma; if (!(ma = pa_modargs_new(args, valid_modargs))) { pa_log("Failed to parse submodule arguments."); goto fail; } filter_size_ms = DEFAULT_FILTER_SIZE_MS; if (pa_modargs_get_value_u32(ma, "filter_size_ms", &filter_size_ms) < 0 || filter_size_ms < 1 || filter_size_ms > 2000) { pa_log("Invalid filter_size_ms specification"); goto fail; } frame_size_ms = DEFAULT_FRAME_SIZE_MS; if (pa_modargs_get_value_u32(ma, "frame_size_ms", &frame_size_ms) < 0 || frame_size_ms < 1 || frame_size_ms > 200) { pa_log("Invalid frame_size_ms specification"); goto fail; } pa_speex_ec_fixate_spec(source_ss, source_map, sink_ss, sink_map); rate = source_ss->rate; framelen = (rate * frame_size_ms) / 1000; /* framelen should be a power of 2, round down to nearest power of two */ y = 1 << ((8 * sizeof (int)) - 2); while (y > framelen) y >>= 1; framelen = y; *blocksize = framelen * pa_frame_size (source_ss); pa_log_debug ("Using framelen %d, blocksize %u, channels %d, rate %d", framelen, *blocksize, source_ss->channels, source_ss->rate); ec->params.priv.speex.state = speex_echo_state_init_mc (framelen, (rate * filter_size_ms) / 1000, source_ss->channels, source_ss->channels); if (!ec->params.priv.speex.state) goto fail; speex_echo_ctl(ec->params.priv.speex.state, SPEEX_ECHO_SET_SAMPLING_RATE, &rate); pa_modargs_free(ma); return TRUE; fail: if (ma) pa_modargs_free(ma); return FALSE; }
int pa__init(pa_module*m) { pa_modargs *ma = NULL; int ret = -1; uint32_t pid = 0; pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs)) || pa_modargs_get_value_u32(ma, "pid", &pid) < 0 || !pid) { pa_log("Failed to parse module arguments"); goto finish; } if (kill((pid_t) pid, SIGUSR1) < 0) pa_log_warn("kill(%u) failed: %s", pid, pa_cstrerror(errno)); pa_module_unload_request(m, true); ret = 0; finish: if (ma) pa_modargs_free(ma); return ret; }
int pa__init(pa_module*m) { pa_modargs *ma = NULL; struct userdata *u; uint32_t timeout = 5; uint32_t idx; pa_sink *sink; pa_source *source; pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments."); goto fail; } if (pa_modargs_get_value_u32(ma, "timeout", &timeout) < 0) { pa_log("Failed to parse timeout value."); goto fail; } m->userdata = u = pa_xnew(struct userdata, 1); u->core = m->core; u->timeout = timeout; u->device_infos = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); PA_IDXSET_FOREACH(sink, m->core->sinks, idx) device_new_hook_cb(m->core, PA_OBJECT(sink), u); PA_IDXSET_FOREACH(source, m->core->sources, idx) device_new_hook_cb(m->core, PA_OBJECT(source), u); u->sink_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_NORMAL, (pa_hook_cb_t) device_new_hook_cb, u); u->source_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_NORMAL, (pa_hook_cb_t) device_new_hook_cb, u); u->sink_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK_POST], PA_HOOK_NORMAL, (pa_hook_cb_t) device_unlink_hook_cb, u); u->source_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK_POST], PA_HOOK_NORMAL, (pa_hook_cb_t) device_unlink_hook_cb, u); u->sink_state_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) device_state_changed_hook_cb, u); u->source_state_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) device_state_changed_hook_cb, u); u->sink_input_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_FIXATE], PA_HOOK_NORMAL, (pa_hook_cb_t) sink_input_fixate_hook_cb, u); u->source_output_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_FIXATE], PA_HOOK_NORMAL, (pa_hook_cb_t) source_output_fixate_hook_cb, u); u->sink_input_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK_POST], PA_HOOK_NORMAL, (pa_hook_cb_t) sink_input_unlink_hook_cb, u); u->source_output_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK_POST], PA_HOOK_NORMAL, (pa_hook_cb_t) source_output_unlink_hook_cb, u); u->sink_input_move_start_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_START], PA_HOOK_NORMAL, (pa_hook_cb_t) sink_input_move_start_hook_cb, u); u->source_output_move_start_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_START], PA_HOOK_NORMAL, (pa_hook_cb_t) source_output_move_start_hook_cb, u); u->sink_input_move_finish_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_MOVE_FINISH], PA_HOOK_NORMAL, (pa_hook_cb_t) sink_input_move_finish_hook_cb, u); u->source_output_move_finish_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FINISH], PA_HOOK_NORMAL, (pa_hook_cb_t) source_output_move_finish_hook_cb, u); u->sink_input_state_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) sink_input_state_changed_hook_cb, u); u->source_output_state_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_STATE_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) source_output_state_changed_hook_cb, u); pa_modargs_free(ma); return 0; fail: if (ma) pa_modargs_free(ma); return -1; }
pa_bool_t pa_adrian_ec_init(pa_core *c, pa_echo_canceller *ec, pa_sample_spec *rec_ss, pa_channel_map *rec_map, pa_sample_spec *play_ss, pa_channel_map *play_map, pa_sample_spec *out_ss, pa_channel_map *out_map, uint32_t *nframes, const char *args) { int rate, have_vector = 0; uint32_t frame_size_ms; pa_modargs *ma; if (!(ma = pa_modargs_new(args, valid_modargs))) { pa_log("Failed to parse submodule arguments."); goto fail; } frame_size_ms = DEFAULT_FRAME_SIZE_MS; if (pa_modargs_get_value_u32(ma, "frame_size_ms", &frame_size_ms) < 0 || frame_size_ms < 1 || frame_size_ms > 200) { pa_log("Invalid frame_size_ms specification"); goto fail; } pa_adrian_ec_fixate_spec(rec_ss, rec_map, play_ss, play_map, out_ss, out_map); rate = out_ss->rate; *nframes = (rate * frame_size_ms) / 1000; ec->params.priv.adrian.blocksize = (*nframes) * pa_frame_size(out_ss); pa_log_debug ("Using nframes %d, blocksize %u, channels %d, rate %d", *nframes, ec->params.priv.adrian.blocksize, out_ss->channels, out_ss->rate); /* For now we only support SSE */ if (c->cpu_info.cpu_type == PA_CPU_X86 && (c->cpu_info.flags.x86 & PA_CPU_X86_SSE)) have_vector = 1; ec->params.priv.adrian.aec = AEC_init(rate, have_vector); if (!ec->params.priv.adrian.aec) goto fail; pa_modargs_free(ma); return TRUE; fail: if (ma) pa_modargs_free(ma); return FALSE; }
int pa__init(pa_module*m) { struct userdata *u; pa_modargs *ma; pa_source_new_data data; uint32_t frequency; pa_sample_spec ss; pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("failed to parse module arguments."); goto fail; } ss.format = PA_SAMPLE_FLOAT32; ss.channels = 1; ss.rate = 44100; if (pa_modargs_get_value_u32(ma, "rate", &ss.rate) < 0 || ss.rate <= 1) { pa_log("Invalid rate specification"); goto fail; } frequency = 440; if (pa_modargs_get_value_u32(ma, "frequency", &frequency) < 0 || frequency < 1 || frequency > ss.rate/2) { pa_log("Invalid frequency specification"); goto fail; } m->userdata = u = pa_xnew0(struct userdata, 1); u->core = m->core; u->module = m; u->rtpoll = pa_rtpoll_new(); pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll); u->peek_index = 0; pa_memchunk_sine(&u->memchunk, m->core->mempool, ss.rate, frequency); pa_source_new_data_init(&data); data.driver = __FILE__; data.module = m; pa_source_new_data_set_name(&data, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME)); pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Sine source at %u Hz", (unsigned) frequency); pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, "abstract"); pa_proplist_setf(data.proplist, "sine.hz", "%u", frequency); pa_source_new_data_set_sample_spec(&data, &ss); if (pa_modargs_get_proplist(ma, "source_properties", data.proplist, PA_UPDATE_REPLACE) < 0) { pa_log("Invalid properties"); pa_source_new_data_done(&data); goto fail; } u->source = pa_source_new(m->core, &data, PA_SOURCE_LATENCY); pa_source_new_data_done(&data); if (!u->source) { pa_log("Failed to create source."); goto fail; } u->source->parent.process_msg = source_process_msg; u->source->update_requested_latency = source_update_requested_latency_cb; u->source->userdata = u; u->block_usec = BLOCK_USEC; pa_source_set_asyncmsgq(u->source, u->thread_mq.inq); pa_source_set_rtpoll(u->source, u->rtpoll); pa_source_set_fixed_latency(u->source, u->block_usec); if (!(u->thread = pa_thread_new("sine-source", thread_func, u))) { pa_log("Failed to create thread."); goto fail; } pa_source_put(u->source); pa_modargs_free(ma); return 0; fail: if (ma) pa_modargs_free(ma); pa__done(m); return -1; }
int pa__init(pa_module*m) { struct userdata *u = NULL; pa_sample_spec ss; pa_channel_map map; pa_modargs *ma = NULL; jack_status_t status; const char *server_name, *client_name; uint32_t channels = 0; pa_bool_t do_connect = TRUE; unsigned i; const char **ports = NULL, **p; pa_sink_new_data data; pa_assert(m); jack_set_error_function(jack_error_func); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments."); goto fail; } if (pa_modargs_get_value_boolean(ma, "connect", &do_connect) < 0) { pa_log("Failed to parse connect= argument."); goto fail; } server_name = pa_modargs_get_value(ma, "server_name", NULL); client_name = pa_modargs_get_value(ma, "client_name", "PulseAudio JACK Sink"); m->userdata = u = pa_xnew0(struct userdata, 1); u->core = m->core; u->module = m; u->saved_frame_time_valid = FALSE; u->rtpoll = pa_rtpoll_new(); pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll); /* The queue linking the JACK thread and our RT thread */ u->jack_msgq = pa_asyncmsgq_new(0); /* The msgq from the JACK RT thread should have an even higher * priority than the normal message queues, to match the guarantee * all other drivers make: supplying the audio device with data is * the top priority -- and as long as that is possible we don't do * anything else */ u->rtpoll_item = pa_rtpoll_item_new_asyncmsgq_read(u->rtpoll, PA_RTPOLL_EARLY-1, u->jack_msgq); if (!(u->client = jack_client_open(client_name, server_name ? JackServerName : JackNullOption, &status, server_name))) { pa_log("jack_client_open() failed."); goto fail; } ports = jack_get_ports(u->client, NULL, JACK_DEFAULT_AUDIO_TYPE, JackPortIsPhysical|JackPortIsInput); channels = 0; for (p = ports; *p; p++) channels++; if (!channels) channels = m->core->default_sample_spec.channels; if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 || channels <= 0 || channels > PA_CHANNELS_MAX) { pa_log("Failed to parse channels= argument."); goto fail; } if (channels == m->core->default_channel_map.channels) map = m->core->default_channel_map; else pa_channel_map_init_extend(&map, channels, PA_CHANNEL_MAP_ALSA); if (pa_modargs_get_channel_map(ma, NULL, &map) < 0 || map.channels != channels) { pa_log("Failed to parse channel_map= argument."); goto fail; } pa_log_info("Successfully connected as '%s'", jack_get_client_name(u->client)); u->channels = ss.channels = (uint8_t) channels; ss.rate = jack_get_sample_rate(u->client); ss.format = PA_SAMPLE_FLOAT32NE; pa_assert(pa_sample_spec_valid(&ss)); for (i = 0; i < ss.channels; i++) { if (!(u->port[i] = jack_port_register(u->client, pa_channel_position_to_string(map.map[i]), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput|JackPortIsTerminal, 0))) { pa_log("jack_port_register() failed."); goto fail; } } pa_sink_new_data_init(&data); data.driver = __FILE__; data.module = m; pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME)); pa_sink_new_data_set_sample_spec(&data, &ss); pa_sink_new_data_set_channel_map(&data, &map); pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "jack"); if (server_name) pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, server_name); pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Jack sink (%s)", jack_get_client_name(u->client)); pa_proplist_sets(data.proplist, "jack.client_name", jack_get_client_name(u->client)); if (pa_modargs_get_proplist(ma, "sink_properties", data.proplist, PA_UPDATE_REPLACE) < 0) { pa_log("Invalid properties"); pa_sink_new_data_done(&data); goto fail; } u->sink = pa_sink_new(m->core, &data, PA_SINK_LATENCY); pa_sink_new_data_done(&data); if (!u->sink) { pa_log("Failed to create sink."); goto fail; } u->sink->parent.process_msg = sink_process_msg; u->sink->userdata = u; pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); pa_sink_set_rtpoll(u->sink, u->rtpoll); pa_sink_set_max_request(u->sink, jack_get_buffer_size(u->client) * pa_frame_size(&u->sink->sample_spec)); jack_set_process_callback(u->client, jack_process, u); jack_on_shutdown(u->client, jack_shutdown, u); jack_set_thread_init_callback(u->client, jack_init, u); jack_set_buffer_size_callback(u->client, jack_buffer_size, u); if (!(u->thread = pa_thread_new(thread_func, u))) { pa_log("Failed to create thread."); goto fail; } if (jack_activate(u->client)) { pa_log("jack_activate() failed"); goto fail; } if (do_connect) { for (i = 0, p = ports; i < ss.channels; i++, p++) { if (!*p) { pa_log("Not enough physical output ports, leaving unconnected."); break; } pa_log_info("Connecting %s to %s", jack_port_name(u->port[i]), *p); if (jack_connect(u->client, jack_port_name(u->port[i]), *p)) { pa_log("Failed to connect %s to %s, leaving unconnected.", jack_port_name(u->port[i]), *p); break; } } } pa_sink_put(u->sink); free(ports); pa_modargs_free(ma); return 0; fail: if (ma) pa_modargs_free(ma); free(ports); pa__done(m); return -1; }
int pa__init(pa_module*m) { struct userdata *u; pa_modargs *ma = NULL; const char *dst_addr; const char *src_addr; uint32_t port = DEFAULT_PORT, mtu; uint32_t ttl = DEFAULT_TTL; sa_family_t af; int fd = -1, sap_fd = -1; pa_source *s; pa_sample_spec ss; pa_channel_map cm; struct sockaddr_in dst_sa4, dst_sap_sa4, src_sa4, src_sap_sa4; #ifdef HAVE_IPV6 struct sockaddr_in6 dst_sa6, dst_sap_sa6, src_sa6, src_sap_sa6; #endif struct sockaddr_storage sa_dst; pa_source_output *o = NULL; uint8_t payload; char *p; int r, j; socklen_t k; char hn[128], *n; bool loop = false; enum inhibit_auto_suspend inhibit_auto_suspend = INHIBIT_AUTO_SUSPEND_ONLY_WITH_NON_MONITOR_SOURCES; const char *inhibit_auto_suspend_str; pa_source_output_new_data data; pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments"); goto fail; } if (!(s = pa_namereg_get(m->core, pa_modargs_get_value(ma, "source", NULL), PA_NAMEREG_SOURCE))) { pa_log("Source does not exist."); goto fail; } if (pa_modargs_get_value_boolean(ma, "loop", &loop) < 0) { pa_log("Failed to parse \"loop\" parameter."); goto fail; } if ((inhibit_auto_suspend_str = pa_modargs_get_value(ma, "inhibit_auto_suspend", NULL))) { if (pa_streq(inhibit_auto_suspend_str, "always")) inhibit_auto_suspend = INHIBIT_AUTO_SUSPEND_ALWAYS; else if (pa_streq(inhibit_auto_suspend_str, "never")) inhibit_auto_suspend = INHIBIT_AUTO_SUSPEND_NEVER; else if (pa_streq(inhibit_auto_suspend_str, "only_with_non_monitor_sources")) inhibit_auto_suspend = INHIBIT_AUTO_SUSPEND_ONLY_WITH_NON_MONITOR_SOURCES; else { pa_log("Failed to parse the \"inhibit_auto_suspend\" parameter."); goto fail; } } ss = s->sample_spec; pa_rtp_sample_spec_fixup(&ss); cm = s->channel_map; if (pa_modargs_get_sample_spec(ma, &ss) < 0) { pa_log("Failed to parse sample specification"); goto fail; } if (!pa_rtp_sample_spec_valid(&ss)) { pa_log("Specified sample type not compatible with RTP"); goto fail; } if (ss.channels != cm.channels) pa_channel_map_init_auto(&cm, ss.channels, PA_CHANNEL_MAP_AIFF); payload = pa_rtp_payload_from_sample_spec(&ss); mtu = (uint32_t) pa_frame_align(DEFAULT_MTU, &ss); if (pa_modargs_get_value_u32(ma, "mtu", &mtu) < 0 || mtu < 1 || mtu % pa_frame_size(&ss) != 0) { pa_log("Invalid MTU."); goto fail; } port = DEFAULT_PORT + ((uint32_t) (rand() % 512) << 1); if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port < 1 || port > 0xFFFF) { pa_log("port= expects a numerical argument between 1 and 65535."); goto fail; } if (port & 1) pa_log_warn("Port number not even as suggested in RFC3550!"); if (pa_modargs_get_value_u32(ma, "ttl", &ttl) < 0 || ttl < 1 || ttl > 0xFF) { pa_log("ttl= expects a numerical argument between 1 and 255."); goto fail; } src_addr = pa_modargs_get_value(ma, "source_ip", DEFAULT_SOURCE_IP); if (inet_pton(AF_INET, src_addr, &src_sa4.sin_addr) > 0) { src_sa4.sin_family = af = AF_INET; src_sa4.sin_port = htons(0); memset(&src_sa4.sin_zero, 0, sizeof(src_sa4.sin_zero)); src_sap_sa4 = src_sa4; #ifdef HAVE_IPV6 } else if (inet_pton(AF_INET6, src_addr, &src_sa6.sin6_addr) > 0) { src_sa6.sin6_family = af = AF_INET6; src_sa6.sin6_port = htons(0); src_sa6.sin6_flowinfo = 0; src_sa6.sin6_scope_id = 0; src_sap_sa6 = src_sa6; #endif } else { pa_log("Invalid source address '%s'", src_addr); goto fail; } dst_addr = pa_modargs_get_value(ma, "destination", NULL); if (dst_addr == NULL) dst_addr = pa_modargs_get_value(ma, "destination_ip", DEFAULT_DESTINATION_IP); if (inet_pton(AF_INET, dst_addr, &dst_sa4.sin_addr) > 0) { dst_sa4.sin_family = af = AF_INET; dst_sa4.sin_port = htons((uint16_t) port); memset(&dst_sa4.sin_zero, 0, sizeof(dst_sa4.sin_zero)); dst_sap_sa4 = dst_sa4; dst_sap_sa4.sin_port = htons(SAP_PORT); #ifdef HAVE_IPV6 } else if (inet_pton(AF_INET6, dst_addr, &dst_sa6.sin6_addr) > 0) { dst_sa6.sin6_family = af = AF_INET6; dst_sa6.sin6_port = htons((uint16_t) port); dst_sa6.sin6_flowinfo = 0; dst_sa6.sin6_scope_id = 0; dst_sap_sa6 = dst_sa6; dst_sap_sa6.sin6_port = htons(SAP_PORT); #endif } else { pa_log("Invalid destination '%s'", dst_addr); goto fail; } if ((fd = pa_socket_cloexec(af, SOCK_DGRAM, 0)) < 0) { pa_log("socket() failed: %s", pa_cstrerror(errno)); goto fail; } if (af == AF_INET && bind(fd, (struct sockaddr*) &src_sa4, sizeof(src_sa4)) < 0) { pa_log("bind() failed: %s", pa_cstrerror(errno)); goto fail; #ifdef HAVE_IPV6 } else if (af == AF_INET6 && bind(fd, (struct sockaddr*) &src_sa6, sizeof(src_sa6)) < 0) { pa_log("bind() failed: %s", pa_cstrerror(errno)); goto fail; #endif } if (af == AF_INET && connect(fd, (struct sockaddr*) &dst_sa4, sizeof(dst_sa4)) < 0) { pa_log("connect() failed: %s", pa_cstrerror(errno)); goto fail; #ifdef HAVE_IPV6 } else if (af == AF_INET6 && connect(fd, (struct sockaddr*) &dst_sa6, sizeof(dst_sa6)) < 0) { pa_log("connect() failed: %s", pa_cstrerror(errno)); goto fail; #endif } if ((sap_fd = pa_socket_cloexec(af, SOCK_DGRAM, 0)) < 0) { pa_log("socket() failed: %s", pa_cstrerror(errno)); goto fail; } if (af == AF_INET && bind(sap_fd, (struct sockaddr*) &src_sap_sa4, sizeof(src_sap_sa4)) < 0) { pa_log("bind() failed: %s", pa_cstrerror(errno)); goto fail; #ifdef HAVE_IPV6 } else if (af == AF_INET6 && bind(sap_fd, (struct sockaddr*) &src_sap_sa6, sizeof(src_sap_sa6)) < 0) { pa_log("bind() failed: %s", pa_cstrerror(errno)); goto fail; #endif } if (af == AF_INET && connect(sap_fd, (struct sockaddr*) &dst_sap_sa4, sizeof(dst_sap_sa4)) < 0) { pa_log("connect() failed: %s", pa_cstrerror(errno)); goto fail; #ifdef HAVE_IPV6 } else if (af == AF_INET6 && connect(sap_fd, (struct sockaddr*) &dst_sap_sa6, sizeof(dst_sap_sa6)) < 0) { pa_log("connect() failed: %s", pa_cstrerror(errno)); goto fail; #endif } j = loop; if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &j, sizeof(j)) < 0 || setsockopt(sap_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &j, sizeof(j)) < 0) { pa_log("IP_MULTICAST_LOOP failed: %s", pa_cstrerror(errno)); goto fail; } if (ttl != DEFAULT_TTL) { int _ttl = (int) ttl; if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &_ttl, sizeof(_ttl)) < 0) { pa_log("IP_MULTICAST_TTL failed: %s", pa_cstrerror(errno)); goto fail; } if (setsockopt(sap_fd, IPPROTO_IP, IP_MULTICAST_TTL, &_ttl, sizeof(_ttl)) < 0) { pa_log("IP_MULTICAST_TTL (sap) failed: %s", pa_cstrerror(errno)); goto fail; } } /* If the socket queue is full, let's drop packets */ pa_make_fd_nonblock(fd); pa_make_udp_socket_low_delay(fd); pa_source_output_new_data_init(&data); pa_proplist_sets(data.proplist, PA_PROP_MEDIA_NAME, "RTP Monitor Stream"); pa_proplist_sets(data.proplist, "rtp.source", src_addr); pa_proplist_sets(data.proplist, "rtp.destination", dst_addr); pa_proplist_setf(data.proplist, "rtp.mtu", "%lu", (unsigned long) mtu); pa_proplist_setf(data.proplist, "rtp.port", "%lu", (unsigned long) port); pa_proplist_setf(data.proplist, "rtp.ttl", "%lu", (unsigned long) ttl); data.driver = __FILE__; data.module = m; pa_source_output_new_data_set_source(&data, s, false, true); pa_source_output_new_data_set_sample_spec(&data, &ss); pa_source_output_new_data_set_channel_map(&data, &cm); data.flags |= get_dont_inhibit_auto_suspend_flag(s, inhibit_auto_suspend); pa_source_output_new(&o, m->core, &data); pa_source_output_new_data_done(&data); if (!o) { pa_log("failed to create source output."); goto fail; } o->parent.process_msg = source_output_process_msg; o->push = source_output_push_cb; o->moving = source_output_moving_cb; o->kill = source_output_kill_cb; pa_log_info("Configured source latency of %llu ms.", (unsigned long long) pa_source_output_set_requested_latency(o, pa_bytes_to_usec(mtu, &o->sample_spec)) / PA_USEC_PER_MSEC); m->userdata = o->userdata = u = pa_xnew(struct userdata, 1); u->module = m; u->source_output = o; u->memblockq = pa_memblockq_new( "module-rtp-send memblockq", 0, MEMBLOCKQ_MAXLENGTH, MEMBLOCKQ_MAXLENGTH, &ss, 1, 0, 0, NULL); u->mtu = mtu; k = sizeof(sa_dst); pa_assert_se((r = getsockname(fd, (struct sockaddr*) &sa_dst, &k)) >= 0); n = pa_xstrdup(pa_modargs_get_value(ma, "stream_name", NULL)); if (n == NULL) n = pa_sprintf_malloc("PulseAudio RTP Stream on %s", pa_get_fqdn(hn, sizeof(hn))); if (af == AF_INET) { p = pa_sdp_build(af, (void*) &((struct sockaddr_in*) &sa_dst)->sin_addr, (void*) &dst_sa4.sin_addr, n, (uint16_t) port, payload, &ss); #ifdef HAVE_IPV6 } else { p = pa_sdp_build(af, (void*) &((struct sockaddr_in6*) &sa_dst)->sin6_addr, (void*) &dst_sa6.sin6_addr, n, (uint16_t) port, payload, &ss); #endif } pa_xfree(n); pa_rtp_context_init_send(&u->rtp_context, fd, m->core->cookie, payload, pa_frame_size(&ss)); pa_sap_context_init_send(&u->sap_context, sap_fd, p); pa_log_info("RTP stream initialized with mtu %u on %s:%u from %s ttl=%u, SSRC=0x%08x, payload=%u, initial sequence #%u", mtu, dst_addr, port, src_addr, ttl, u->rtp_context.ssrc, payload, u->rtp_context.sequence); pa_log_info("SDP-Data:\n%s\nEOF", p); pa_sap_send(&u->sap_context, 0); u->sap_event = pa_core_rttime_new(m->core, pa_rtclock_now() + SAP_INTERVAL, sap_event_cb, u); u->inhibit_auto_suspend = inhibit_auto_suspend; pa_source_output_put(u->source_output); pa_modargs_free(ma); return 0; fail: if (ma) pa_modargs_free(ma); if (fd >= 0) pa_close(fd); if (sap_fd >= 0) pa_close(sap_fd); return -1; }
int pa__init(pa_module*m) { pa_modargs *ma = NULL; struct userdata *u; int version; struct input_id input_id; char name[256]; uint8_t evtype_bitmask[EV_MAX/8 + 1]; pa_volume_t volume_limit = PA_VOLUME_NORM*3/2; pa_volume_t volume_step = PA_VOLUME_NORM/20; pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments"); goto fail; } if (pa_modargs_get_value_u32(ma, "volume_limit", &volume_limit) < 0) { pa_log("Failed to parse volume limit"); goto fail; } if (pa_modargs_get_value_u32(ma, "volume_step", &volume_step) < 0) { pa_log("Failed to parse volume step"); goto fail; } m->userdata = u = pa_xnew(struct userdata, 1); u->module = m; u->io = NULL; u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL)); u->fd = -1; u->fd_type = 0; u->volume_limit = PA_CLAMP_VOLUME(volume_limit); u->volume_step = PA_CLAMP_VOLUME(volume_step); if ((u->fd = pa_open_cloexec(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), O_RDONLY, 0)) < 0) { pa_log("Failed to open evdev device: %s", pa_cstrerror(errno)); goto fail; } if (ioctl(u->fd, EVIOCGVERSION, &version) < 0) { pa_log("EVIOCGVERSION failed: %s", pa_cstrerror(errno)); goto fail; } pa_log_info("evdev driver version %i.%i.%i", version >> 16, (version >> 8) & 0xff, version & 0xff); if (ioctl(u->fd, EVIOCGID, &input_id)) { pa_log("EVIOCGID failed: %s", pa_cstrerror(errno)); goto fail; } pa_log_info("evdev vendor 0x%04hx product 0x%04hx version 0x%04hx bustype %u", input_id.vendor, input_id.product, input_id.version, input_id.bustype); memset(name, 0, sizeof(name)); if (ioctl(u->fd, EVIOCGNAME(sizeof(name)), name) < 0) { pa_log("EVIOCGNAME failed: %s", pa_cstrerror(errno)); goto fail; } pa_log_info("evdev device name: %s", name); memset(evtype_bitmask, 0, sizeof(evtype_bitmask)); if (ioctl(u->fd, EVIOCGBIT(0, EV_MAX), evtype_bitmask) < 0) { pa_log("EVIOCGBIT failed: %s", pa_cstrerror(errno)); goto fail; } if (!test_bit(EV_KEY, evtype_bitmask)) { pa_log("Device has no keys."); goto fail; } u->io = m->core->mainloop->io_new(m->core->mainloop, u->fd, PA_IO_EVENT_INPUT|PA_IO_EVENT_HANGUP, io_callback, u); pa_modargs_free(ma); return 0; fail: if (ma) pa_modargs_free(ma); pa__done(m); return -1; }
int pa__init(pa_module*m) { pa_modargs *ma = NULL; struct userdata *u; pa_sink *sink; pa_sample_spec ss; uint32_t frequency; pa_sink_input_new_data data; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments"); goto fail; } if (!(sink = pa_namereg_get(m->core, pa_modargs_get_value(ma, "sink", NULL), PA_NAMEREG_SINK))) { pa_log("No such sink."); goto fail; } ss.format = PA_SAMPLE_FLOAT32; ss.rate = sink->sample_spec.rate; ss.channels = 1; frequency = 440; if (pa_modargs_get_value_u32(ma, "frequency", &frequency) < 0 || frequency < 1 || frequency > ss.rate/2) { pa_log("Invalid frequency specification"); goto fail; } m->userdata = u = pa_xnew0(struct userdata, 1); u->core = m->core; u->module = m; u->sink_input = NULL; u->peek_index = 0; pa_memchunk_sine(&u->memchunk, m->core->mempool, ss.rate, frequency); pa_sink_input_new_data_init(&data); data.driver = __FILE__; data.module = m; pa_sink_input_new_data_set_sink(&data, sink, false); pa_proplist_setf(data.proplist, PA_PROP_MEDIA_NAME, "%u Hz Sine", frequency); pa_proplist_sets(data.proplist, PA_PROP_MEDIA_ROLE, "abstract"); pa_proplist_setf(data.proplist, "sine.hz", "%u", frequency); pa_sink_input_new_data_set_sample_spec(&data, &ss); pa_sink_input_new(&u->sink_input, m->core, &data); pa_sink_input_new_data_done(&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->kill = sink_input_kill_cb; u->sink_input->state_change = sink_input_state_change_cb; u->sink_input->userdata = u; pa_sink_input_put(u->sink_input); pa_modargs_free(ma); return 0; fail: if (ma) pa_modargs_free(ma); pa__done(m); return -1; }
pa_source *pa_droid_source_new(pa_module *m, pa_modargs *ma, const char *driver, pa_droid_card_data *card_data, pa_droid_mapping *am, pa_card *card) { struct userdata *u = NULL; char *thread_name = NULL; pa_source_new_data data; const char *module_id = NULL; /* const char *tmp; */ uint32_t sample_rate; uint32_t alternate_sample_rate; audio_devices_t dev_in; pa_sample_spec sample_spec; pa_channel_map channel_map; bool namereg_fail = false; pa_droid_config_audio *config = NULL; /* Only used when source is created without card */ uint32_t source_buffer = 0; char audio_source[32]; int ret; audio_format_t hal_audio_format = 0; audio_channel_mask_t hal_channel_mask = 0; pa_assert(m); pa_assert(ma); pa_assert(driver); /* When running under card use hw module name for source by default. */ if (card && ma) module_id = am->input->module->name; else module_id = pa_modargs_get_value(ma, "module_id", DEFAULT_MODULE_ID); sample_spec = m->core->default_sample_spec; channel_map = m->core->default_channel_map; if (pa_modargs_get_sample_spec_and_channel_map(ma, &sample_spec, &channel_map, PA_CHANNEL_MAP_AIFF) < 0) { pa_log("Failed to parse sample specification and channel map."); goto fail; } alternate_sample_rate = m->core->alternate_sample_rate; if (pa_modargs_get_alternate_sample_rate(ma, &alternate_sample_rate) < 0) { pa_log("Failed to parse alternate sample rate."); goto fail; } if (pa_modargs_get_value_u32(ma, "source_buffer", &source_buffer) < 0) { pa_log("Failed to parse source_buffer. Needs to be integer >= 0."); goto fail; } u = pa_xnew0(struct userdata, 1); u->core = m->core; u->module = m; u->card = card; u->rtpoll = pa_rtpoll_new(); pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll); /* Enabled routing changes by default. */ u->routing_changes_enabled = true; if (card_data) { pa_assert(card); u->card_data = card_data; pa_assert_se((u->hw_module = pa_droid_hw_module_get(u->core, NULL, card_data->module_id))); } else { /* Stand-alone source */ if (!(config = pa_droid_config_load(ma))) goto fail; /* Ownership of config transfers to hw_module if opening of hw module succeeds. */ if (!(u->hw_module = pa_droid_hw_module_get(u->core, config, module_id))) goto fail; } if (!pa_convert_format(sample_spec.format, CONV_FROM_PA, &hal_audio_format)) { pa_log("Sample spec format %u not supported.", sample_spec.format); goto fail; } for (int i = 0; i < channel_map.channels; i++) { audio_channel_mask_t c; if (!pa_convert_input_channel(channel_map.map[i], CONV_FROM_PA, &c)) { pa_log("Failed to convert channel map."); goto fail; } hal_channel_mask |= c; } struct audio_config config_in = { .sample_rate = sample_spec.rate, .channel_mask = hal_channel_mask, .format = hal_audio_format }; /* Default routing */ /* FIXME So while setting routing through stream with HALv2 API fails, creation of stream * requires HALv2 style device to work properly. So until that oddity is resolved we always * set AUDIO_DEVICE_IN_BUILTIN_MIC as initial device here. */ #if 0 pa_assert_se(pa_string_convert_input_device_str_to_num("AUDIO_DEVICE_IN_BUILTIN_MIC", &dev_in)); if ((tmp = pa_modargs_get_value(ma, "input_devices", NULL))) { audio_devices_t tmp_dev; if (parse_device_list(tmp, &tmp_dev) && tmp_dev) dev_in = tmp_dev; pa_log_debug("Set initial devices %s", tmp); } #else pa_log_info("FIXME: Setting AUDIO_DEVICE_IN_BUILTIN_MIC as initial device."); dev_in = AUDIO_DEVICE_IN_BUILTIN_MIC; #endif pa_droid_hw_module_lock(u->hw_module); ret = u->hw_module->device->open_input_stream(u->hw_module->device, u->hw_module->stream_in_id, dev_in, &config_in, &u->stream); /* On some devices the first call will fail if the config parameters are * not supported, but it'll automatically set the right ones, expecting * the caller to call it again, so let's try at least one more time */ if (!u->stream) ret = u->hw_module->device->open_input_stream(u->hw_module->device, u->hw_module->stream_in_id, dev_in, &config_in, &u->stream); u->hw_module->stream_in_id++; pa_droid_hw_module_unlock(u->hw_module); if (ret < 0) { pa_log("Failed to open input stream."); goto fail; } if ((sample_rate = u->stream->common.get_sample_rate(&u->stream->common)) != sample_spec.rate) { pa_log_warn("Requested sample rate %u but got %u instead.", sample_spec.rate, sample_rate); sample_spec.rate = sample_rate; } u->buffer_size = u->stream->common.get_buffer_size(&u->stream->common); if (source_buffer) { if (source_buffer < u->buffer_size) pa_log_warn("Requested buffer size %u less than HAL reported buffer size (%u).", source_buffer, u->buffer_size); else if (source_buffer % u->buffer_size) { uint32_t trunc = (source_buffer / u->buffer_size) * u->buffer_size; pa_log_warn("Requested buffer size %u not multiple of HAL buffer size (%u). Using buffer size %u", source_buffer, u->buffer_size, trunc); u->buffer_size = trunc; } else { pa_log_info("Using requested buffer size %u.", source_buffer); u->buffer_size = source_buffer; } } pa_log_info("Created Android stream with device: %u sample rate: %u channel mask: %u format: %u buffer size: %u", dev_in, sample_rate, config_in.channel_mask, config_in.format, u->buffer_size); /* Setting audio source to MIC by default */ pa_snprintf(audio_source, sizeof(audio_source), "%s=%u", AUDIO_PARAMETER_STREAM_INPUT_SOURCE, AUDIO_SOURCE_MIC); u->stream->common.set_parameters(&u->stream->common, audio_source); pa_log_debug("Setting audio source to AUDIO_SOURCE_MIC by default"); pa_source_new_data_init(&data); data.driver = driver; data.module = m; data.card = card; source_set_name(ma, &data, module_id); /* We need to give pa_modargs_get_value_boolean() a pointer to a local * variable instead of using &data.namereg_fail directly, because * data.namereg_fail is a bitfield and taking the address of a bitfield * variable is impossible. */ namereg_fail = data.namereg_fail; if (pa_modargs_get_value_boolean(ma, "namereg_fail", &namereg_fail) < 0) { pa_log("Failed to parse namereg_fail argument."); pa_source_new_data_done(&data); goto fail; } data.namereg_fail = namereg_fail; pa_source_new_data_set_sample_spec(&data, &sample_spec); pa_source_new_data_set_channel_map(&data, &channel_map); pa_source_new_data_set_alternate_sample_rate(&data, alternate_sample_rate); if (am) pa_droid_add_ports(data.ports, am, card); u->source = pa_source_new(m->core, &data, PA_SOURCE_HARDWARE); pa_source_new_data_done(&data); if (!u->source) { pa_log("Failed to create source."); goto fail; } u->source->userdata = u; u->source->parent.process_msg = source_process_msg; source_set_mute_control(u); u->source->set_port = source_set_port_cb; pa_source_set_asyncmsgq(u->source, u->thread_mq.inq); pa_source_set_rtpoll(u->source, u->rtpoll); /* Disable rewind for droid source */ pa_source_set_max_rewind(u->source, 0); thread_name = pa_sprintf_malloc("droid-source-%s", module_id); if (!(u->thread = pa_thread_new(thread_name, thread_func, u))) { pa_log("Failed to create thread."); goto fail; } pa_xfree(thread_name); thread_name = NULL; pa_source_set_fixed_latency(u->source, pa_bytes_to_usec(u->buffer_size, &sample_spec)); pa_log_debug("Set fixed latency %" PRIu64 " usec", pa_bytes_to_usec(u->buffer_size, &sample_spec)); if (u->source->active_port) source_set_port_cb(u->source, u->source->active_port); pa_source_put(u->source); return u->source; fail: pa_xfree(thread_name); if (config) pa_xfree(config); if (u) userdata_free(u); return NULL; } void pa_droid_source_free(pa_source *s) { struct userdata *u; pa_source_assert_ref(s); pa_assert_se(u = s->userdata); userdata_free(u); } static void userdata_free(struct userdata *u) { if (u->source) pa_source_unlink(u->source); if (u->thread) { pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL); pa_thread_free(u->thread); } pa_thread_mq_done(&u->thread_mq); if (u->source) pa_source_unref(u->source); if (u->memchunk.memblock) pa_memblock_unref(u->memchunk.memblock); if (u->hw_module && u->stream) { pa_droid_hw_module_lock(u->hw_module); u->hw_module->device->close_input_stream(u->hw_module->device, u->stream); pa_droid_hw_module_unlock(u->hw_module); } // Stand alone source if (u->hw_module) pa_droid_hw_module_unref(u->hw_module); pa_xfree(u); }
int pa__init(pa_module*m) { struct userdata *u = NULL; pa_sample_spec ss; pa_channel_map map; pa_modargs *ma = NULL; pa_source_new_data data; uint32_t latency_time = DEFAULT_LATENCY_TIME; pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments."); goto fail; } ss = m->core->default_sample_spec; map = m->core->default_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; } m->userdata = u = pa_xnew0(struct userdata, 1); u->core = m->core; u->module = m; u->rtpoll = pa_rtpoll_new(); pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll); pa_source_new_data_init(&data); data.driver = __FILE__; data.module = m; pa_source_new_data_set_name(&data, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME)); pa_source_new_data_set_sample_spec(&data, &ss); pa_source_new_data_set_channel_map(&data, &map); pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, pa_modargs_get_value(ma, "description", "Null Input")); pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, "abstract"); u->source = pa_source_new(m->core, &data, PA_SOURCE_LATENCY | PA_SOURCE_DYNAMIC_LATENCY); pa_source_new_data_done(&data); if (!u->source) { pa_log("Failed to create source object."); goto fail; } u->latency_time = DEFAULT_LATENCY_TIME; if (pa_modargs_get_value_u32(ma, "latency_time", &latency_time) < 0) { pa_log("Failed to parse latency_time value."); goto fail; } u->latency_time = latency_time; u->source->parent.process_msg = source_process_msg; u->source->update_requested_latency = source_update_requested_latency_cb; u->source->userdata = u; pa_source_set_asyncmsgq(u->source, u->thread_mq.inq); pa_source_set_rtpoll(u->source, u->rtpoll); pa_source_set_latency_range(u->source, 0, MAX_LATENCY_USEC); u->block_usec = u->source->thread_info.max_latency; u->source->thread_info.max_rewind = pa_usec_to_bytes(u->block_usec, &u->source->sample_spec); if (!(u->thread = pa_thread_new("null-source", thread_func, u))) { pa_log("Failed to create thread."); goto fail; } pa_source_put(u->source); pa_modargs_free(ma); return 0; fail: if (ma) pa_modargs_free(ma); pa__done(m); return -1; }
int pa__init(pa_module*m) { pa_modargs *ma = NULL; struct userdata *u = NULL; #if defined(USE_TCP_SOCKETS) uint32_t port = IPV4_PORT; pa_bool_t port_fallback = TRUE; const char *listen_on; #else int r; #endif #if defined(USE_PROTOCOL_NATIVE) || defined(USE_PROTOCOL_HTTP) char t[256]; #endif pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments"); goto fail; } m->userdata = u = pa_xnew0(struct userdata, 1); u->module = m; #if defined(USE_PROTOCOL_SIMPLE) u->simple_protocol = pa_simple_protocol_get(m->core); u->simple_options = pa_simple_options_new(); if (pa_simple_options_parse(u->simple_options, m->core, ma) < 0) goto fail; u->simple_options->module = m; #elif defined(USE_PROTOCOL_CLI) u->cli_protocol = pa_cli_protocol_get(m->core); #elif defined(USE_PROTOCOL_HTTP) u->http_protocol = pa_http_protocol_get(m->core); #elif defined(USE_PROTOCOL_NATIVE) u->native_protocol = pa_native_protocol_get(m->core); u->native_options = pa_native_options_new(); if (pa_native_options_parse(u->native_options, m->core, ma) < 0) goto fail; u->native_options->module = m; #else u->esound_protocol = pa_esound_protocol_get(m->core); u->esound_options = pa_esound_options_new(); if (pa_esound_options_parse(u->esound_options, m->core, ma) < 0) goto fail; u->esound_options->module = m; #endif #if defined(USE_TCP_SOCKETS) if (pa_in_system_mode() || pa_modargs_get_value(ma, "port", NULL)) port_fallback = FALSE; if (pa_modargs_get_value_u32(ma, "port", &port) < 0 || port < 1 || port > 0xFFFF) { pa_log("port= expects a numerical argument between 1 and 65535."); goto fail; } listen_on = pa_modargs_get_value(ma, "listen", NULL); if (listen_on) { # ifdef HAVE_IPV6 u->socket_server_ipv6 = pa_socket_server_new_ipv6_string(m->core->mainloop, listen_on, (uint16_t) port, port_fallback, TCPWRAP_SERVICE); # endif u->socket_server_ipv4 = pa_socket_server_new_ipv4_string(m->core->mainloop, listen_on, (uint16_t) port, port_fallback, TCPWRAP_SERVICE); } else { # ifdef HAVE_IPV6 u->socket_server_ipv6 = pa_socket_server_new_ipv6_any(m->core->mainloop, (uint16_t) port, port_fallback, TCPWRAP_SERVICE); # endif u->socket_server_ipv4 = pa_socket_server_new_ipv4_any(m->core->mainloop, (uint16_t) port, port_fallback, TCPWRAP_SERVICE); } # ifdef HAVE_IPV6 if (!u->socket_server_ipv4 && !u->socket_server_ipv6) # else if (!u->socket_server_ipv4) # endif goto fail; if (u->socket_server_ipv4) pa_socket_server_set_callback(u->socket_server_ipv4, socket_server_on_connection_cb, u); # ifdef HAVE_IPV6 if (u->socket_server_ipv6) pa_socket_server_set_callback(u->socket_server_ipv6, socket_server_on_connection_cb, u); # endif #else # if defined(USE_PROTOCOL_ESOUND) # if defined(USE_PER_USER_ESOUND_SOCKET) u->socket_path = pa_sprintf_malloc("/tmp/.esd-%lu/socket", (unsigned long) getuid()); # else u->socket_path = pa_xstrdup("/tmp/.esd/socket"); # endif /* This socket doesn't reside in our own runtime dir but in * /tmp/.esd/, hence we have to create the dir first */ if (pa_make_secure_parent_dir(u->socket_path, pa_in_system_mode() ? 0755U : 0700U, (uid_t)-1, (gid_t)-1) < 0) { pa_log("Failed to create socket directory '%s': %s\n", u->socket_path, pa_cstrerror(errno)); goto fail; } # else if (!(u->socket_path = pa_runtime_path(pa_modargs_get_value(ma, "socket", UNIX_SOCKET)))) { pa_log("Failed to generate socket path."); goto fail; } # endif if ((r = pa_unix_socket_remove_stale(u->socket_path)) < 0) { pa_log("Failed to remove stale UNIX socket '%s': %s", u->socket_path, pa_cstrerror(errno)); goto fail; } else if (r > 0) pa_log_info("Removed stale UNIX socket '%s'.", u->socket_path); if (!(u->socket_server_unix = pa_socket_server_new_unix(m->core->mainloop, u->socket_path))) goto fail; pa_socket_server_set_callback(u->socket_server_unix, socket_server_on_connection_cb, u); #endif #if defined(USE_PROTOCOL_NATIVE) # if defined(USE_TCP_SOCKETS) if (u->socket_server_ipv4) if (pa_socket_server_get_address(u->socket_server_ipv4, t, sizeof(t))) pa_native_protocol_add_server_string(u->native_protocol, t); # ifdef HAVE_IPV6 if (u->socket_server_ipv6) if (pa_socket_server_get_address(u->socket_server_ipv6, t, sizeof(t))) pa_native_protocol_add_server_string(u->native_protocol, t); # endif # else if (pa_socket_server_get_address(u->socket_server_unix, t, sizeof(t))) pa_native_protocol_add_server_string(u->native_protocol, t); # endif #endif #if defined(USE_PROTOCOL_HTTP) #if defined(USE_TCP_SOCKETS) if (u->socket_server_ipv4) if (pa_socket_server_get_address(u->socket_server_ipv4, t, sizeof(t))) pa_http_protocol_add_server_string(u->http_protocol, t); #ifdef HAVE_IPV6 if (u->socket_server_ipv6) if (pa_socket_server_get_address(u->socket_server_ipv6, t, sizeof(t))) pa_http_protocol_add_server_string(u->http_protocol, t); #endif /* HAVE_IPV6 */ #else /* USE_TCP_SOCKETS */ if (pa_socket_server_get_address(u->socket_server_unix, t, sizeof(t))) pa_http_protocol_add_server_string(u->http_protocol, t); #endif /* USE_TCP_SOCKETS */ #endif /* USE_PROTOCOL_HTTP */ if (ma) pa_modargs_free(ma); return 0; fail: if (ma) pa_modargs_free(ma); pa__done(m); return -1; }
int pa__init(pa_module *m) { struct userdata *u = NULL; bool record = true, playback = true; pa_sample_spec ss; pa_channel_map map; pa_modargs *ma = NULL; uint32_t buffer_length_msec; int fd = -1; pa_sink_new_data sink_new_data; pa_source_new_data source_new_data; char const *name; char *name_buf; bool namereg_fail; pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("failed to parse module arguments."); goto fail; } if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) { pa_log("record= and playback= expect a boolean argument."); goto fail; } if (!playback && !record) { pa_log("neither playback nor record enabled for device."); goto fail; } u = pa_xnew0(struct userdata, 1); if (!(u->smoother = pa_smoother_new(PA_USEC_PER_SEC, PA_USEC_PER_SEC * 2, true, true, 10, pa_rtclock_now(), true))) goto fail; /* * For a process (or several processes) to use the same audio device for both * record and playback at the same time, the device's mixer must be enabled. * See mixerctl(1). It may be turned off for playback only or record only. */ u->mode = (playback && record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0)); ss = m->core->default_sample_spec; if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) { pa_log("failed to parse sample specification"); goto fail; } u->frame_size = pa_frame_size(&ss); u->minimum_request = pa_usec_to_bytes(PA_USEC_PER_SEC / MAX_RENDER_HZ, &ss); buffer_length_msec = 100; if (pa_modargs_get_value_u32(ma, "buffer_length", &buffer_length_msec) < 0) { pa_log("failed to parse buffer_length argument"); goto fail; } u->buffer_size = pa_usec_to_bytes(1000 * buffer_length_msec, &ss); if (u->buffer_size < 2 * u->minimum_request) { pa_log("buffer_length argument cannot be smaller than %u", (unsigned)(pa_bytes_to_usec(2 * u->minimum_request, &ss) / 1000)); goto fail; } if (u->buffer_size > MAX_BUFFER_SIZE) { pa_log("buffer_length argument cannot be greater than %u", (unsigned)(pa_bytes_to_usec(MAX_BUFFER_SIZE, &ss) / 1000)); goto fail; } u->device_name = pa_xstrdup(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE)); if ((fd = open_audio_device(u, &ss)) < 0) goto fail; u->core = m->core; u->module = m; m->userdata = u; pa_memchunk_reset(&u->memchunk); u->rtpoll = pa_rtpoll_new(); pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll); u->rtpoll_item = NULL; build_pollfd(u); if (u->mode != O_WRONLY) { name_buf = NULL; namereg_fail = true; if (!(name = pa_modargs_get_value(ma, "source_name", NULL))) { name = name_buf = pa_sprintf_malloc("solaris_input.%s", pa_path_get_filename(u->device_name)); namereg_fail = false; } pa_source_new_data_init(&source_new_data); source_new_data.driver = __FILE__; source_new_data.module = m; pa_source_new_data_set_name(&source_new_data, name); source_new_data.namereg_fail = namereg_fail; pa_source_new_data_set_sample_spec(&source_new_data, &ss); pa_source_new_data_set_channel_map(&source_new_data, &map); pa_proplist_sets(source_new_data.proplist, PA_PROP_DEVICE_STRING, u->device_name); pa_proplist_sets(source_new_data.proplist, PA_PROP_DEVICE_API, "solaris"); pa_proplist_sets(source_new_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Solaris PCM source"); pa_proplist_sets(source_new_data.proplist, PA_PROP_DEVICE_ACCESS_MODE, "serial"); pa_proplist_setf(source_new_data.proplist, PA_PROP_DEVICE_BUFFERING_BUFFER_SIZE, "%lu", (unsigned long) u->buffer_size); if (pa_modargs_get_proplist(ma, "source_properties", source_new_data.proplist, PA_UPDATE_REPLACE) < 0) { pa_log("Invalid properties"); pa_source_new_data_done(&source_new_data); goto fail; } u->source = pa_source_new(m->core, &source_new_data, PA_SOURCE_HARDWARE|PA_SOURCE_LATENCY); pa_source_new_data_done(&source_new_data); pa_xfree(name_buf); if (!u->source) { pa_log("Failed to create source object"); goto fail; } u->source->userdata = u; u->source->parent.process_msg = source_process_msg; pa_source_set_asyncmsgq(u->source, u->thread_mq.inq); pa_source_set_rtpoll(u->source, u->rtpoll); pa_source_set_fixed_latency(u->source, pa_bytes_to_usec(u->buffer_size, &u->source->sample_spec)); pa_source_set_get_volume_callback(u->source, source_get_volume); pa_source_set_set_volume_callback(u->source, source_set_volume); u->source->refresh_volume = true; } else u->source = NULL; if (u->mode != O_RDONLY) { name_buf = NULL; namereg_fail = true; if (!(name = pa_modargs_get_value(ma, "sink_name", NULL))) { name = name_buf = pa_sprintf_malloc("solaris_output.%s", pa_path_get_filename(u->device_name)); namereg_fail = false; } pa_sink_new_data_init(&sink_new_data); sink_new_data.driver = __FILE__; sink_new_data.module = m; pa_sink_new_data_set_name(&sink_new_data, name); sink_new_data.namereg_fail = namereg_fail; pa_sink_new_data_set_sample_spec(&sink_new_data, &ss); pa_sink_new_data_set_channel_map(&sink_new_data, &map); pa_proplist_sets(sink_new_data.proplist, PA_PROP_DEVICE_STRING, u->device_name); pa_proplist_sets(sink_new_data.proplist, PA_PROP_DEVICE_API, "solaris"); pa_proplist_sets(sink_new_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Solaris PCM sink"); pa_proplist_sets(sink_new_data.proplist, PA_PROP_DEVICE_ACCESS_MODE, "serial"); if (pa_modargs_get_proplist(ma, "sink_properties", sink_new_data.proplist, PA_UPDATE_REPLACE) < 0) { pa_log("Invalid properties"); pa_sink_new_data_done(&sink_new_data); goto fail; } u->sink = pa_sink_new(m->core, &sink_new_data, PA_SINK_HARDWARE|PA_SINK_LATENCY); pa_sink_new_data_done(&sink_new_data); pa_assert(u->sink); u->sink->userdata = u; u->sink->parent.process_msg = sink_process_msg; pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); pa_sink_set_rtpoll(u->sink, u->rtpoll); pa_sink_set_fixed_latency(u->sink, pa_bytes_to_usec(u->buffer_size, &u->sink->sample_spec)); pa_sink_set_max_request(u->sink, u->buffer_size); pa_sink_set_max_rewind(u->sink, u->buffer_size); pa_sink_set_get_volume_callback(u->sink, sink_get_volume); pa_sink_set_set_volume_callback(u->sink, sink_set_volume); pa_sink_set_get_mute_callback(u->sink, sink_get_mute); pa_sink_set_set_mute_callback(u->sink, sink_set_mute); u->sink->refresh_volume = u->sink->refresh_muted = true; } else u->sink = NULL; pa_assert(u->source || u->sink); u->sig = pa_signal_new(SIGPOLL, sig_callback, u); if (u->sig) ioctl(u->fd, I_SETSIG, S_MSG); else pa_log_warn("Could not register SIGPOLL handler"); if (!(u->thread = pa_thread_new("solaris", thread_func, u))) { pa_log("Failed to create thread."); goto fail; } /* Read mixer settings */ if (u->sink) { if (sink_new_data.volume_is_set) u->sink->set_volume(u->sink); else u->sink->get_volume(u->sink); if (sink_new_data.muted_is_set) u->sink->set_mute(u->sink); else u->sink->get_mute(u->sink); pa_sink_put(u->sink); } if (u->source) { if (source_new_data.volume_is_set) u->source->set_volume(u->source); else u->source->get_volume(u->source); pa_source_put(u->source); } pa_modargs_free(ma); return 0; fail: if (u) pa__done(m); else if (fd >= 0) close(fd); if (ma) pa_modargs_free(ma); return -1; }
int pa__init(pa_module*m) { struct userdata *u = NULL; pa_sample_spec ss; pa_channel_map map; pa_modargs *ma = NULL; pa_sink_new_data data; size_t nbytes; pa_assert(m); pa_web_debug_func_t func = pa_get_user_data(PA_USER_WEB_FUNC); if (!func) { pa_log_error("Failed to get user web func from user data"); goto fail; } ma = pa_modargs_new(m->argument, valid_modargs); if (!ma) { pa_log("Failed to parse module arguments."); goto fail; } ss = m->core->default_sample_spec; map = m->core->default_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; } pa_modargs_get_value_u32(ma, "fixed_rate", &ss.rate); uint32_t c = 0; pa_modargs_get_value_u32(ma, "fixed_channels", &c); if (c) ss.channels = c; const char* fixed_fmt = pa_modargs_get_value(ma, "fixed_format", NULL); if (fixed_fmt) ss.format = pa_parse_sample_format(fixed_fmt); if (ss.channels != map.channels) { pa_log_error("sample_spec channels[%d] != channel_map channels[%d]", ss.channels, map.channels); pa_channel_map_init_extend(&map, ss.channels, PA_CHANNEL_MAP_DEFAULT); pa_log_debug("after init extend mmap.channels=%d", map.channels); } m->userdata = u = pa_xnew0(struct userdata, 1); u->core = m->core; u->module = m; u->rtpoll = pa_rtpoll_new(); u->data_func = web_data_func; pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll); pa_sink_new_data_init(&data); data.driver = __FILE__; data.module = m; pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME)); pa_sink_new_data_set_sample_spec(&data, &ss); pa_sink_new_data_set_channel_map(&data, &map); pa_proplist_sets(data.proplist, PA_PROP_DEVICE_DESCRIPTION, _("Remote Output")); pa_proplist_sets(data.proplist, PA_PROP_DEVICE_CLASS, "abstract"); if (pa_modargs_get_proplist(ma, "sink_properties", data.proplist, PA_UPDATE_REPLACE) < 0) { pa_log("Invalid properties"); pa_sink_new_data_done(&data); goto fail; } u->sink = pa_sink_new(m->core, &data, PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY); pa_sink_new_data_done(&data); if (!u->sink) { pa_log("Failed to create sink object."); goto fail; } u->sink->parent.process_msg = sink_process_msg; u->sink->update_requested_latency = sink_update_requested_latency_cb; u->sink->userdata = u; pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); pa_sink_set_rtpoll(u->sink, u->rtpoll); u->block_usec = BLOCK_USEC; nbytes = pa_usec_to_bytes(u->block_usec, &u->sink->sample_spec); pa_sink_set_max_rewind(u->sink, nbytes); pa_sink_set_max_request(u->sink, nbytes); // call websocket to start func(1, NULL, ss.rate, ss.format); u->thread = pa_thread_new("remote-sink", thread_func, u); if (!u->thread) { pa_log("Failed to create thread."); goto fail; } pa_sink_set_latency_range(u->sink, 0, BLOCK_USEC); pa_sink_put(u->sink); pa_modargs_free(ma); return 0; fail: if (ma) pa_modargs_free(ma); pa__done(m); return -1; }
int pa__init(pa_module *m) { pa_modargs *ma = NULL; struct userdata *u; pa_sink *sink = NULL; pa_sink_input_new_data sink_input_data; pa_bool_t sink_dont_move; pa_source *source = NULL; pa_source_output_new_data source_output_data; pa_bool_t source_dont_move; uint32_t latency_msec; pa_sample_spec ss; pa_channel_map map; bool format_set = false; bool rate_set = false; bool channels_set = false; pa_memchunk silence; uint32_t adjust_time_sec; const char *n; pa_bool_t remix = TRUE; pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments"); goto fail; } n = pa_modargs_get_value(ma, "source", NULL); if (n && !(source = pa_namereg_get(m->core, n, PA_NAMEREG_SOURCE))) { pa_log("No such source."); goto fail; } n = pa_modargs_get_value(ma, "sink", NULL); if (n && !(sink = pa_namereg_get(m->core, n, PA_NAMEREG_SINK))) { pa_log("No such sink."); goto fail; } if (pa_modargs_get_value_boolean(ma, "remix", &remix) < 0) { pa_log("Invalid boolean remix parameter"); goto fail; } if (sink) { ss = sink->sample_spec; map = sink->channel_map; format_set = true; rate_set = true; channels_set = true; } else if (source) { ss = source->sample_spec; map = source->channel_map; format_set = true; rate_set = true; channels_set = true; } else { /* FIXME: Dummy stream format, needed because pa_sink_input_new() * requires valid sample spec and channel map even when all the FIX_* * stream flags are specified. pa_sink_input_new() should be changed * to ignore the sample spec and channel map when the FIX_* flags are * present. */ ss.format = PA_SAMPLE_U8; ss.rate = 8000; ss.channels = 1; map.channels = 1; map.map[0] = PA_CHANNEL_POSITION_MONO; } 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 (pa_modargs_get_value(ma, "format", NULL)) format_set = true; if (pa_modargs_get_value(ma, "rate", NULL)) rate_set = true; if (pa_modargs_get_value(ma, "channels", NULL) || pa_modargs_get_value(ma, "channel_map", NULL)) channels_set = true; latency_msec = DEFAULT_LATENCY_MSEC; if (pa_modargs_get_value_u32(ma, "latency_msec", &latency_msec) < 0 || latency_msec < 1 || latency_msec > 2000) { pa_log("Invalid latency specification"); goto fail; } m->userdata = u = pa_xnew0(struct userdata, 1); u->core = m->core; u->module = m; u->latency = (pa_usec_t) latency_msec * PA_USEC_PER_MSEC; adjust_time_sec = DEFAULT_ADJUST_TIME_USEC / PA_USEC_PER_SEC; if (pa_modargs_get_value_u32(ma, "adjust_time", &adjust_time_sec) < 0) { pa_log("Failed to parse adjust_time value"); goto fail; } if (adjust_time_sec != DEFAULT_ADJUST_TIME_USEC / PA_USEC_PER_SEC) u->adjust_time = adjust_time_sec * PA_USEC_PER_SEC; else u->adjust_time = DEFAULT_ADJUST_TIME_USEC; pa_sink_input_new_data_init(&sink_input_data); sink_input_data.driver = __FILE__; sink_input_data.module = m; if (sink) pa_sink_input_new_data_set_sink(&sink_input_data, sink, FALSE); if (pa_modargs_get_proplist(ma, "sink_input_properties", sink_input_data.proplist, PA_UPDATE_REPLACE) < 0) { pa_log("Failed to parse the sink_input_properties value."); pa_sink_input_new_data_done(&sink_input_data); goto fail; } if (!pa_proplist_contains(sink_input_data.proplist, PA_PROP_MEDIA_ROLE)) pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "abstract"); pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss); pa_sink_input_new_data_set_channel_map(&sink_input_data, &map); sink_input_data.flags = PA_SINK_INPUT_VARIABLE_RATE | PA_SINK_INPUT_START_CORKED; if (!remix) sink_input_data.flags |= PA_SINK_INPUT_NO_REMIX; if (!format_set) sink_input_data.flags |= PA_SINK_INPUT_FIX_FORMAT; if (!rate_set) sink_input_data.flags |= PA_SINK_INPUT_FIX_RATE; if (!channels_set) sink_input_data.flags |= PA_SINK_INPUT_FIX_CHANNELS; sink_dont_move = FALSE; if (pa_modargs_get_value_boolean(ma, "sink_dont_move", &sink_dont_move) < 0) { pa_log("sink_dont_move= expects a boolean argument."); goto fail; } if (sink_dont_move) sink_input_data.flags |= PA_SINK_INPUT_DONT_MOVE; 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; /* If format, rate or channels were originally unset, they are set now * after the pa_sink_input_new() call. */ ss = u->sink_input->sample_spec; map = u->sink_input->channel_map; u->sink_input->parent.process_msg = sink_input_process_msg_cb; u->sink_input->pop = sink_input_pop_cb; u->sink_input->process_rewind = sink_input_process_rewind_cb; u->sink_input->kill = sink_input_kill_cb; u->sink_input->state_change = sink_input_state_change_cb; u->sink_input->attach = sink_input_attach_cb; u->sink_input->detach = sink_input_detach_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->may_move_to = sink_input_may_move_to_cb; u->sink_input->moving = sink_input_moving_cb; u->sink_input->suspend = sink_input_suspend_cb; u->sink_input->userdata = u; pa_sink_input_set_requested_latency(u->sink_input, u->latency/3); pa_source_output_new_data_init(&source_output_data); source_output_data.driver = __FILE__; source_output_data.module = m; if (source) pa_source_output_new_data_set_source(&source_output_data, source, FALSE); if (pa_modargs_get_proplist(ma, "source_output_properties", source_output_data.proplist, PA_UPDATE_REPLACE) < 0) { pa_log("Failed to parse the source_output_properties value."); pa_source_output_new_data_done(&source_output_data); goto fail; } if (!pa_proplist_contains(source_output_data.proplist, PA_PROP_MEDIA_ROLE)) pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_ROLE, "abstract"); pa_source_output_new_data_set_sample_spec(&source_output_data, &ss); pa_source_output_new_data_set_channel_map(&source_output_data, &map); source_output_data.flags = PA_SOURCE_OUTPUT_START_CORKED; if (!remix) source_output_data.flags |= PA_SOURCE_OUTPUT_NO_REMIX; source_dont_move = FALSE; if (pa_modargs_get_value_boolean(ma, "source_dont_move", &source_dont_move) < 0) { pa_log("source_dont_move= expects a boolean argument."); goto fail; } if (source_dont_move) source_output_data.flags |= PA_SOURCE_OUTPUT_DONT_MOVE; pa_source_output_new(&u->source_output, m->core, &source_output_data); pa_source_output_new_data_done(&source_output_data); if (!u->source_output) goto fail; u->source_output->parent.process_msg = source_output_process_msg_cb; u->source_output->push = source_output_push_cb; u->source_output->process_rewind = source_output_process_rewind_cb; u->source_output->kill = source_output_kill_cb; u->source_output->attach = source_output_attach_cb; u->source_output->detach = source_output_detach_cb; u->source_output->state_change = source_output_state_change_cb; u->source_output->may_move_to = source_output_may_move_to_cb; u->source_output->moving = source_output_moving_cb; u->source_output->suspend = source_output_suspend_cb; u->source_output->userdata = u; pa_source_output_set_requested_latency(u->source_output, u->latency/3); pa_sink_input_get_silence(u->sink_input, &silence); u->memblockq = pa_memblockq_new( "module-loopback memblockq", 0, /* idx */ MEMBLOCKQ_MAXLENGTH, /* maxlength */ MEMBLOCKQ_MAXLENGTH, /* tlength */ &ss, /* sample_spec */ 0, /* prebuf */ 0, /* minreq */ 0, /* maxrewind */ &silence); /* silence frame */ pa_memblock_unref(silence.memblock); u->asyncmsgq = pa_asyncmsgq_new(0); if (!pa_proplist_contains(u->source_output->proplist, PA_PROP_MEDIA_NAME)) pa_proplist_setf(u->source_output->proplist, PA_PROP_MEDIA_NAME, "Loopback to %s", pa_strnull(pa_proplist_gets(u->sink_input->sink->proplist, PA_PROP_DEVICE_DESCRIPTION))); if (!pa_proplist_contains(u->source_output->proplist, PA_PROP_MEDIA_ICON_NAME) && (n = pa_proplist_gets(u->sink_input->sink->proplist, PA_PROP_DEVICE_ICON_NAME))) pa_proplist_sets(u->source_output->proplist, PA_PROP_MEDIA_ICON_NAME, n); if (!pa_proplist_contains(u->sink_input->proplist, PA_PROP_MEDIA_NAME)) pa_proplist_setf(u->sink_input->proplist, PA_PROP_MEDIA_NAME, "Loopback from %s", pa_strnull(pa_proplist_gets(u->source_output->source->proplist, PA_PROP_DEVICE_DESCRIPTION))); if (source && !pa_proplist_contains(u->sink_input->proplist, PA_PROP_MEDIA_ICON_NAME) && (n = pa_proplist_gets(u->source_output->source->proplist, PA_PROP_DEVICE_ICON_NAME))) pa_proplist_sets(u->sink_input->proplist, PA_PROP_MEDIA_ICON_NAME, n); pa_sink_input_put(u->sink_input); pa_source_output_put(u->source_output); if (pa_source_get_state(u->source_output->source) != PA_SOURCE_SUSPENDED) pa_sink_input_cork(u->sink_input, FALSE); if (pa_sink_get_state(u->sink_input->sink) != PA_SINK_SUSPENDED) pa_source_output_cork(u->source_output, FALSE); update_adjust_timer(u); pa_modargs_free(ma); return 0; fail: if (ma) pa_modargs_free(ma); pa__done(m); return -1; }
int pa__init(pa_module *m) { struct userdata *u = NULL; pa_modargs *ma; struct udev_enumerate *enumerate = NULL; struct udev_list_entry *item = NULL, *first = NULL; int fd; bool use_tsched = true, fixed_latency_range = false, ignore_dB = false, deferred_volume = m->core->deferred_volume; bool use_ucm = true; pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments"); goto fail; } m->userdata = u = pa_xnew0(struct userdata, 1); u->core = m->core; u->devices = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL, (pa_free_cb_t) device_free); u->inotify_fd = -1; if (pa_modargs_get_value_boolean(ma, "tsched", &use_tsched) < 0) { pa_log("Failed to parse tsched= argument."); goto fail; } u->use_tsched = use_tsched; if (pa_modargs_get_value(ma, "tsched_buffer_size", NULL)) { if (pa_modargs_get_value_u32(ma, "tsched_buffer_size", &u->tsched_buffer_size) < 0) { pa_log("Failed to parse tsched_buffer_size= argument."); goto fail; } u->tsched_buffer_size_valid = true; } if (pa_modargs_get_value_boolean(ma, "fixed_latency_range", &fixed_latency_range) < 0) { pa_log("Failed to parse fixed_latency_range= argument."); goto fail; } u->fixed_latency_range = fixed_latency_range; if (pa_modargs_get_value_boolean(ma, "ignore_dB", &ignore_dB) < 0) { pa_log("Failed to parse ignore_dB= argument."); goto fail; } u->ignore_dB = ignore_dB; if (pa_modargs_get_value_boolean(ma, "deferred_volume", &deferred_volume) < 0) { pa_log("Failed to parse deferred_volume= argument."); goto fail; } u->deferred_volume = deferred_volume; if (pa_modargs_get_value_boolean(ma, "use_ucm", &use_ucm) < 0) { pa_log("Failed to parse use_ucm= argument."); goto fail; } u->use_ucm = use_ucm; if (!(u->udev = udev_new())) { pa_log("Failed to initialize udev library."); goto fail; } if (setup_inotify(u) < 0) goto fail; if (!(u->monitor = udev_monitor_new_from_netlink(u->udev, "udev"))) { pa_log("Failed to initialize monitor."); goto fail; } if (udev_monitor_filter_add_match_subsystem_devtype(u->monitor, "sound", NULL) < 0) { pa_log("Failed to subscribe to sound devices."); goto fail; } errno = 0; if (udev_monitor_enable_receiving(u->monitor) < 0) { pa_log("Failed to enable monitor: %s", pa_cstrerror(errno)); if (errno == EPERM) pa_log_info("Most likely your kernel is simply too old and " "allows only privileged processes to listen to device events. " "Please upgrade your kernel to at least 2.6.30."); goto fail; } if ((fd = udev_monitor_get_fd(u->monitor)) < 0) { pa_log("Failed to get udev monitor fd."); goto fail; } pa_assert_se(u->udev_io = u->core->mainloop->io_new(u->core->mainloop, fd, PA_IO_EVENT_INPUT, monitor_cb, u)); if (!(enumerate = udev_enumerate_new(u->udev))) { pa_log("Failed to initialize udev enumerator."); goto fail; } if (udev_enumerate_add_match_subsystem(enumerate, "sound") < 0) { pa_log("Failed to match to subsystem."); goto fail; } if (udev_enumerate_scan_devices(enumerate) < 0) { pa_log("Failed to scan for devices."); goto fail; } first = udev_enumerate_get_list_entry(enumerate); udev_list_entry_foreach(item, first) process_path(u, udev_list_entry_get_name(item)); udev_enumerate_unref(enumerate); pa_log_info("Found %u cards.", pa_hashmap_size(u->devices)); pa_modargs_free(ma); return 0; fail: if (enumerate) udev_enumerate_unref(enumerate); if (ma) pa_modargs_free(ma); pa__done(m); return -1; }
pa_bool_t pa_speex_ec_init(pa_core *c, pa_echo_canceller *ec, pa_sample_spec *source_ss, pa_channel_map *source_map, pa_sample_spec *sink_ss, pa_channel_map *sink_map, uint32_t *nframes, const char *args) { int rate; uint32_t y, frame_size_ms, filter_size_ms; pa_modargs *ma; if (!(ma = pa_modargs_new(args, valid_modargs))) { pa_log("Failed to parse submodule arguments."); goto fail; } filter_size_ms = DEFAULT_FILTER_SIZE_MS; if (pa_modargs_get_value_u32(ma, "filter_size_ms", &filter_size_ms) < 0 || filter_size_ms < 1 || filter_size_ms > 2000) { pa_log("Invalid filter_size_ms specification"); goto fail; } frame_size_ms = DEFAULT_FRAME_SIZE_MS; if (pa_modargs_get_value_u32(ma, "frame_size_ms", &frame_size_ms) < 0 || frame_size_ms < 1 || frame_size_ms > 200) { pa_log("Invalid frame_size_ms specification"); goto fail; } pa_speex_ec_fixate_spec(source_ss, source_map, sink_ss, sink_map); rate = source_ss->rate; *nframes = (rate * frame_size_ms) / 1000; /* nframes should be a power of 2, round down to nearest power of two */ y = 1 << ((8 * sizeof (uint32_t)) - 2); while (y > *nframes) y >>= 1; *nframes = y; pa_log_debug ("Using nframes %d, channels %d, rate %d", *nframes, source_ss->channels, source_ss->rate); ec->params.priv.speex.state = speex_echo_state_init_mc (*nframes, (rate * filter_size_ms) / 1000, source_ss->channels, source_ss->channels); if (!ec->params.priv.speex.state) goto fail; speex_echo_ctl(ec->params.priv.speex.state, SPEEX_ECHO_SET_SAMPLING_RATE, &rate); if (!pa_speex_ec_preprocessor_init(ec, source_ss, *nframes, ma)) goto fail; pa_modargs_free(ma); return TRUE; fail: if (ma) pa_modargs_free(ma); if (ec->params.priv.speex.pp_state) { speex_preprocess_state_destroy(ec->params.priv.speex.pp_state); ec->params.priv.speex.pp_state = NULL; } if (ec->params.priv.speex.state) { speex_echo_state_destroy(ec->params.priv.speex.state); ec->params.priv.speex.state = NULL; } return FALSE; }
int pa__init(pa_module *m) { pa_modargs *ma = NULL; struct userdata *u; pa_sink *sink; pa_sink_input_new_data sink_input_data; pa_source *source; pa_source_output_new_data source_output_data; uint32_t latency_msec; pa_sample_spec ss; pa_channel_map map; pa_memchunk silence; uint32_t adjust_time_sec; const char *n; pa_assert(m); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments"); goto fail; } if (!(source = pa_namereg_get(m->core, pa_modargs_get_value(ma, "source", NULL), PA_NAMEREG_SOURCE))) { pa_log("No such source."); goto fail; } if (!(sink = pa_namereg_get(m->core, pa_modargs_get_value(ma, "sink", NULL), PA_NAMEREG_SINK))) { pa_log("No such sink."); goto fail; } ss = sink->sample_spec; map = sink->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; } latency_msec = DEFAULT_LATENCY_MSEC; if (pa_modargs_get_value_u32(ma, "latency_msec", &latency_msec) < 0 || latency_msec < 1 || latency_msec > 2000) { pa_log("Invalid latency specification"); goto fail; } m->userdata = u = pa_xnew0(struct userdata, 1); u->core = m->core; u->module = m; u->latency = (pa_usec_t) latency_msec * PA_USEC_PER_MSEC; adjust_time_sec = DEFAULT_ADJUST_TIME_USEC / PA_USEC_PER_SEC; if (pa_modargs_get_value_u32(ma, "adjust_time", &adjust_time_sec) < 0) { pa_log("Failed to parse adjust_time value"); goto fail; } if (adjust_time_sec != DEFAULT_ADJUST_TIME_USEC / PA_USEC_PER_SEC) u->adjust_time = adjust_time_sec * PA_USEC_PER_SEC; else u->adjust_time = DEFAULT_ADJUST_TIME_USEC; pa_sink_input_new_data_init(&sink_input_data); sink_input_data.driver = __FILE__; sink_input_data.module = m; sink_input_data.sink = sink; if ((n = pa_modargs_get_value(ma, "sink_input_name", NULL))) pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, n); else pa_proplist_setf(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Loopback from %s", pa_strnull(pa_proplist_gets(source->proplist, PA_PROP_DEVICE_DESCRIPTION))); if ((n = pa_modargs_get_value(ma, "sink_input_role", NULL))) pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, n); else pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "abstract"); if ((n = pa_proplist_gets(source->proplist, PA_PROP_DEVICE_ICON_NAME))) pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ICON_NAME, n); pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss); pa_sink_input_new_data_set_channel_map(&sink_input_data, &map); sink_input_data.flags = PA_SINK_INPUT_VARIABLE_RATE; 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->parent.process_msg = sink_input_process_msg_cb; u->sink_input->pop = sink_input_pop_cb; u->sink_input->process_rewind = sink_input_process_rewind_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->update_max_rewind = sink_input_update_max_rewind_cb; u->sink_input->update_max_request = sink_input_update_max_request_cb; u->sink_input->may_move_to = sink_input_may_move_to_cb; u->sink_input->moving = sink_input_moving_cb; u->sink_input->userdata = u; pa_sink_input_set_requested_latency(u->sink_input, u->latency/3); pa_source_output_new_data_init(&source_output_data); source_output_data.driver = __FILE__; source_output_data.module = m; source_output_data.source = source; if ((n = pa_modargs_get_value(ma, "source_output_name", NULL))) pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_NAME, n); else pa_proplist_setf(source_output_data.proplist, PA_PROP_MEDIA_NAME, "Loopback to %s", pa_strnull(pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_DESCRIPTION))); if ((n = pa_modargs_get_value(ma, "source_output_role", NULL))) pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_ROLE, n); else pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_ROLE, "abstract"); if ((n = pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_ICON_NAME))) pa_proplist_sets(source_output_data.proplist, PA_PROP_MEDIA_ICON_NAME, n); pa_source_output_new_data_set_sample_spec(&source_output_data, &ss); pa_sink_input_new_data_set_channel_map(&sink_input_data, &map); pa_source_output_new(&u->source_output, m->core, &source_output_data); pa_source_output_new_data_done(&source_output_data); if (!u->source_output) goto fail; u->source_output->parent.process_msg = source_output_process_msg_cb; u->source_output->push = source_output_push_cb; u->source_output->process_rewind = source_output_process_rewind_cb; u->source_output->kill = source_output_kill_cb; u->source_output->attach = source_output_attach_cb; u->source_output->detach = source_output_detach_cb; u->source_output->state_change = source_output_state_change_cb; u->source_output->may_move_to = source_output_may_move_to_cb; u->source_output->moving = source_output_moving_cb; u->source_output->userdata = u; pa_source_output_set_requested_latency(u->source_output, u->latency/3); pa_sink_input_get_silence(u->sink_input, &silence); u->memblockq = pa_memblockq_new( 0, /* idx */ MEMBLOCKQ_MAXLENGTH, /* maxlength */ MEMBLOCKQ_MAXLENGTH, /* tlength */ pa_frame_size(&ss), /* base */ 0, /* prebuf */ 0, /* minreq */ 0, /* maxrewind */ &silence); /* silence frame */ pa_memblock_unref(silence.memblock); u->asyncmsgq = pa_asyncmsgq_new(0); pa_sink_input_put(u->sink_input); pa_source_output_put(u->source_output); if (u->adjust_time > 0) u->time_event = pa_core_rttime_new(m->core, pa_rtclock_now() + u->adjust_time, time_callback, u); pa_modargs_free(ma); return 0; fail: if (ma) pa_modargs_free(ma); pa__done(m); return -1; }