char *pa_module_list_to_string(pa_core *c) { pa_strbuf *s; pa_module *m; uint32_t idx = PA_IDXSET_INVALID; pa_assert(c); s = pa_strbuf_new(); pa_strbuf_printf(s, "%u module(s) loaded.\n", pa_idxset_size(c->modules)); for (m = pa_idxset_first(c->modules, &idx); m; m = pa_idxset_next(c->modules, &idx)) { char *t; pa_strbuf_printf(s, " index: %u\n" "\tname: <%s>\n" "\targument: <%s>\n" "\tused: %i\n" "\tload once: %s\n", m->index, m->name, pa_strempty(m->argument), pa_module_get_n_used(m), pa_yes_no(m->load_once)); t = pa_proplist_to_string_sep(m->proplist, "\n\t\t"); pa_strbuf_printf(s, "\tproperties:\n\t\t%s\n", t); pa_xfree(t); } return pa_strbuf_tostring_free(s); }
char *pa_source_output_list_to_string(pa_core *c) { pa_strbuf *s; pa_source_output *o; uint32_t idx = PA_IDXSET_INVALID; static const char* const state_table[] = { [PA_SOURCE_OUTPUT_RUNNING] = "RUNNING", [PA_SOURCE_OUTPUT_CORKED] = "CORKED", [PA_SOURCE_OUTPUT_UNLINKED] = "UNLINKED" }; pa_assert(c); s = pa_strbuf_new(); pa_strbuf_printf(s, "%u source outputs(s) available.\n", pa_idxset_size(c->source_outputs)); for (o = pa_idxset_first(c->source_outputs, &idx); o; o = pa_idxset_next(c->source_outputs, &idx)) { char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; pa_assert(o->source); pa_strbuf_printf( s, " index: %u\n" "\tname: '%s'\n" "\tdriver: <%s>\n" "\tflags: %s%s%s%s%s%s%s\n" "\tstate: %s\n" "\tsource: <%u> '%s'\n" "\tlatency: <%0.0f usec>\n" "\tsample spec: <%s>\n" "\tchannel map: <%s>\n" "\tresample method: %s\n", o->index, o->name, o->driver, o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE ? "VARIABLE_RATE " : "", o->flags & PA_SOURCE_OUTPUT_DONT_MOVE ? "DONT_MOVE " : "", o->flags & PA_SOURCE_OUTPUT_NO_REMAP ? "NO_REMAP " : "", o->flags & PA_SOURCE_OUTPUT_NO_REMIX ? "NO_REMIX " : "", o->flags & PA_SOURCE_OUTPUT_FIX_FORMAT ? "FIX_FORMAT " : "", o->flags & PA_SOURCE_OUTPUT_FIX_RATE ? "FIX_RATE " : "", o->flags & PA_SOURCE_OUTPUT_FIX_CHANNELS ? "FIX_CHANNELS " : "", state_table[pa_source_output_get_state(o)], o->source->index, o->source->name, (double) pa_source_output_get_latency(o), pa_sample_spec_snprint(ss, sizeof(ss), &o->sample_spec), pa_channel_map_snprint(cm, sizeof(cm), &o->channel_map), pa_resample_method_to_string(pa_source_output_get_resample_method(o))); if (o->module) pa_strbuf_printf(s, "\towner module: <%u>\n", o->module->index); if (o->client) pa_strbuf_printf(s, "\tclient: <%u> '%s'\n", o->client->index, o->client->name); } return pa_strbuf_tostring_free(s); }
static int rtsp_exec(pa_rtsp_client* c, const char* cmd, const char* content_type, const char* content, int expect_response, pa_headerlist* headers) { pa_strbuf* buf; char* hdrs; pa_assert(c); pa_assert(c->url); pa_assert(cmd); pa_assert(c->ioline); pa_log_debug("Sending command: %s", cmd); buf = pa_strbuf_new(); pa_strbuf_printf(buf, "%s %s RTSP/1.0\r\nCSeq: %d\r\n", cmd, c->url, ++c->cseq); if (c->session) pa_strbuf_printf(buf, "Session: %s\r\n", c->session); /* Add the headers */ if (headers) { hdrs = pa_headerlist_to_string(headers); pa_strbuf_puts(buf, hdrs); pa_xfree(hdrs); } if (content_type && content) { pa_strbuf_printf(buf, "Content-Type: %s\r\nContent-Length: %d\r\n", content_type, (int)strlen(content)); } pa_strbuf_printf(buf, "User-Agent: %s\r\n", c->useragent); if (c->headers) { hdrs = pa_headerlist_to_string(c->headers); pa_strbuf_puts(buf, hdrs); pa_xfree(hdrs); } pa_strbuf_puts(buf, "\r\n"); if (content_type && content) { pa_strbuf_puts(buf, content); } /* Our packet is created... now we can send it :) */ hdrs = pa_strbuf_tostring_free(buf); /*pa_log_debug("Submitting request:"); pa_log_debug(hdrs);*/ pa_ioline_puts(c->ioline, hdrs); pa_xfree(hdrs); return 0; }
char *pa_scache_list_to_string(pa_core *c) { pa_strbuf *s; pa_assert(c); s = pa_strbuf_new(); pa_strbuf_printf(s, "%u cache entries available.\n", c->scache ? pa_idxset_size(c->scache) : 0); if (c->scache) { pa_scache_entry *e; uint32_t idx = PA_IDXSET_INVALID; for (e = pa_idxset_first(c->scache, &idx); e; e = pa_idxset_next(c->scache, &idx)) { double l = 0; char ss[PA_SAMPLE_SPEC_SNPRINT_MAX] = "n/a", cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX] = "n/a"; if (e->memchunk.memblock) { pa_sample_spec_snprint(ss, sizeof(ss), &e->sample_spec); pa_channel_map_snprint(cm, sizeof(cm), &e->channel_map); l = (double) e->memchunk.length / pa_bytes_per_second(&e->sample_spec); } pa_strbuf_printf( s, " name: <%s>\n" "\tindex: <%u>\n" "\tsample spec: <%s>\n" "\tchannel map: <%s>\n" "\tlength: <%lu>\n" "\tduration: <%0.1fs>\n" "\tvolume: <%s>\n" "\tlazy: %s\n" "\tfilename: %s\n", e->name, e->index, ss, cm, (long unsigned)(e->memchunk.memblock ? e->memchunk.length : 0), l, pa_cvolume_snprint(cv, sizeof(cv), &e->volume), e->lazy ? "yes" : "no", e->filename ? e->filename : "n/a"); } } return pa_strbuf_tostring_free(s); }
char *pa_client_list_to_string(pa_core *c) { pa_strbuf *s; pa_client *client; uint32_t idx = PA_IDXSET_INVALID; pa_assert(c); s = pa_strbuf_new(); pa_strbuf_printf(s, "%u client(s) logged in.\n", pa_idxset_size(c->clients)); for (client = pa_idxset_first(c->clients, &idx); client; client = pa_idxset_next(c->clients, &idx)) { pa_strbuf_printf(s, " index: %u\n\tname: <%s>\n\tdriver: <%s>\n", client->index, client->name, client->driver); if (client->owner) pa_strbuf_printf(s, "\towner module: <%u>\n", client->owner->index); } return pa_strbuf_tostring_free(s); }
char *pa_full_status_string(pa_core *c) { pa_strbuf *s; int i; s = pa_strbuf_new(); for (i = 0; i < 8; i++) { char *t = NULL; switch (i) { case 0: t = pa_sink_list_to_string(c); break; case 1: t = pa_source_list_to_string(c); break; case 2: t = pa_sink_input_list_to_string(c); break; case 3: t = pa_source_output_list_to_string(c); break; case 4: t = pa_client_list_to_string(c); break; case 5: t = pa_module_list_to_string(c); break; case 6: t = pa_scache_list_to_string(c); break; case 7: t = pa_autoload_list_to_string(c); break; } pa_strbuf_puts(s, t); pa_xfree(t); } return pa_strbuf_tostring_free(s); }
char *pa_module_list_to_string(pa_core *c) { pa_strbuf *s; pa_module *m; uint32_t idx = PA_IDXSET_INVALID; pa_assert(c); s = pa_strbuf_new(); pa_strbuf_printf(s, "%u module(s) loaded.\n", pa_idxset_size(c->modules)); for (m = pa_idxset_first(c->modules, &idx); m; m = pa_idxset_next(c->modules, &idx)) { pa_strbuf_printf(s, " index: %u\n" "\tname: <%s>\n" "\targument: <%s>\n" "\tused: %i\n" "\tauto unload: %s\n", m->index, m->name, m->argument ? m->argument : "", m->n_used, m->auto_unload ? "yes" : "no"); } return pa_strbuf_tostring_free(s); }
static void line_callback(pa_ioline *line, const char *s, void *userdata) { pa_strbuf *buf; pa_cli *c = userdata; char *p; pa_assert(line); pa_assert(c); if (!s) { pa_log_debug("CLI got EOF from user."); if (c->eof_callback) c->eof_callback(c, c->userdata); return; } /* Magic command, like they had in AT Hayes Modems! Those were the good days! */ if (pa_streq(s, "/")) s = c->last_line; else if (s[0]) { pa_xfree(c->last_line); c->last_line = pa_xstrdup(s); } pa_assert_se(buf = pa_strbuf_new()); c->defer_kill++; pa_cli_command_execute_line(c->core, s, buf, &c->fail); c->defer_kill--; pa_ioline_puts(line, p = pa_strbuf_tostring_free(buf)); pa_xfree(p); if (c->kill_requested) { if (c->eof_callback) c->eof_callback(c, c->userdata); } else pa_ioline_puts(line, PROMPT); }
char *pa_sink_input_list_to_string(pa_core *c) { pa_strbuf *s; pa_sink_input *i; uint32_t idx = PA_IDXSET_INVALID; static const char* const state_table[] = { [PA_SINK_INPUT_RUNNING] = "RUNNING", [PA_SINK_INPUT_DRAINED] = "DRAINED", [PA_SINK_INPUT_CORKED] = "CORKED", [PA_SINK_INPUT_UNLINKED] = "UNLINKED" }; pa_assert(c); s = pa_strbuf_new(); pa_strbuf_printf(s, "%u sink input(s) available.\n", pa_idxset_size(c->sink_inputs)); for (i = pa_idxset_first(c->sink_inputs, &idx); i; i = pa_idxset_next(c->sink_inputs, &idx)) { char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX]; pa_assert(i->sink); pa_strbuf_printf( s, " index: %u\n" "\tname: <%s>\n" "\tdriver: <%s>\n" "\tflags: %s%s%s%s%s%s%s\n" "\tstate: %s\n" "\tsink: <%u> '%s'\n" "\tvolume: <%s>\n" "\tmute: <%i>\n" "\tlatency: <%0.0f usec>\n" "\tsample spec: <%s>\n" "\tchannel map: <%s>\n" "\tresample method: %s\n", i->index, i->name, i->driver, i->flags & PA_SINK_INPUT_VARIABLE_RATE ? "VARIABLE_RATE " : "", i->flags & PA_SINK_INPUT_DONT_MOVE ? "DONT_MOVE " : "", i->flags & PA_SINK_INPUT_NO_REMAP ? "NO_REMAP " : "", i->flags & PA_SINK_INPUT_NO_REMIX ? "NO_REMIX " : "", i->flags & PA_SINK_INPUT_FIX_FORMAT ? "FIX_FORMAT " : "", i->flags & PA_SINK_INPUT_FIX_RATE ? "FIX_RATE " : "", i->flags & PA_SINK_INPUT_FIX_CHANNELS ? "FIX_CHANNELS " : "", state_table[pa_sink_input_get_state(i)], i->sink->index, i->sink->name, pa_cvolume_snprint(cv, sizeof(cv), pa_sink_input_get_volume(i)), !!pa_sink_input_get_mute(i), (double) pa_sink_input_get_latency(i), pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec), pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), pa_resample_method_to_string(pa_sink_input_get_resample_method(i))); if (i->module) pa_strbuf_printf(s, "\tmodule: <%u>\n", i->module->index); if (i->client) pa_strbuf_printf(s, "\tclient: <%u> '%s'\n", i->client->index, i->client->name); } return pa_strbuf_tostring_free(s); }
char *pa_card_list_to_string(pa_core *c) { pa_strbuf *s; pa_card *card; uint32_t idx = PA_IDXSET_INVALID; pa_assert(c); s = pa_strbuf_new(); pa_strbuf_printf(s, "%u card(s) available.\n", pa_idxset_size(c->cards)); for (card = pa_idxset_first(c->cards, &idx); card; card = pa_idxset_next(c->cards, &idx)) { char *t; pa_sink *sink; pa_source *source; uint32_t sidx; pa_strbuf_printf( s, " index: %u\n" "\tname: <%s>\n" "\tdriver: <%s>\n", card->index, card->name, card->driver); if (card->module) pa_strbuf_printf(s, "\towner module: %u\n", card->module->index); t = pa_proplist_to_string_sep(card->proplist, "\n\t\t"); pa_strbuf_printf(s, "\tproperties:\n\t\t%s\n", t); pa_xfree(t); if (card->profiles) { pa_card_profile *p; void *state; pa_strbuf_puts(s, "\tprofiles:\n"); PA_HASHMAP_FOREACH(p, card->profiles, state) pa_strbuf_printf(s, "\t\t%s: %s (priority %u)\n", p->name, p->description, p->priority); } if (card->active_profile) pa_strbuf_printf( s, "\tactive profile: <%s>\n", card->active_profile->name); if (!pa_idxset_isempty(card->sinks)) { pa_strbuf_puts(s, "\tsinks:\n"); for (sink = pa_idxset_first(card->sinks, &sidx); sink; sink = pa_idxset_next(card->sinks, &sidx)) pa_strbuf_printf(s, "\t\t%s/#%u: %s\n", sink->name, sink->index, pa_strna(pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_DESCRIPTION))); } if (!pa_idxset_isempty(card->sources)) { pa_strbuf_puts(s, "\tsources:\n"); for (source = pa_idxset_first(card->sources, &sidx); source; source = pa_idxset_next(card->sources, &sidx)) pa_strbuf_printf(s, "\t\t%s/#%u: %s\n", source->name, source->index, pa_strna(pa_proplist_gets(source->proplist, PA_PROP_DEVICE_DESCRIPTION))); } append_port_list(s, card->ports); } return pa_strbuf_tostring_free(s); }
static void card_changed(struct userdata *u, struct udev_device *dev) { struct device *d; const char *path; const char *t; char *n; pa_strbuf *args_buf; pa_assert(u); pa_assert(dev); /* Maybe /dev/snd is now available? */ setup_inotify(u); path = udev_device_get_devpath(dev); if ((d = pa_hashmap_get(u->devices, path))) { verify_access(u, d); return; } d = pa_xnew0(struct device, 1); d->path = pa_xstrdup(path); d->module = PA_INVALID_INDEX; PA_INIT_RATELIMIT(d->ratelimit, 10*PA_USEC_PER_SEC, 5); if (!(t = udev_device_get_property_value(dev, "PULSE_NAME"))) if (!(t = udev_device_get_property_value(dev, "ID_ID"))) if (!(t = udev_device_get_property_value(dev, "ID_PATH"))) t = path_get_card_id(path); n = pa_namereg_make_valid_name(t); d->card_name = pa_sprintf_malloc("alsa_card.%s", n); args_buf = pa_strbuf_new(); pa_strbuf_printf(args_buf, "device_id=\"%s\" " "name=\"%s\" " "card_name=\"%s\" " "namereg_fail=false " "tsched=%s " "fixed_latency_range=%s " "ignore_dB=%s " "deferred_volume=%s " "use_ucm=%s " "card_properties=\"module-udev-detect.discovered=1\"", path_get_card_id(path), n, d->card_name, pa_yes_no(u->use_tsched), pa_yes_no(u->fixed_latency_range), pa_yes_no(u->ignore_dB), pa_yes_no(u->deferred_volume), pa_yes_no(u->use_ucm)); pa_xfree(n); if (u->tsched_buffer_size_valid) pa_strbuf_printf(args_buf, " tsched_buffer_size=%" PRIu32, u->tsched_buffer_size); d->args = pa_strbuf_tostring_free(args_buf); pa_hashmap_put(u->devices, d->path, d); verify_access(u, d); }
int main(int argc, char *argv[]) { pa_core *c = NULL; pa_strbuf *buf = NULL; pa_daemon_conf *conf = NULL; pa_mainloop *mainloop = NULL; char *s; char *configured_address; int r = 0, retval = 1, d = 0; pa_bool_t valid_pid_file = FALSE; pa_bool_t ltdl_init = FALSE; int passed_fd = -1; const char *e; #ifdef HAVE_FORK int daemon_pipe[2] = { -1, -1 }; int daemon_pipe2[2] = { -1, -1 }; #endif #ifdef OS_IS_WIN32 pa_time_event *win32_timer; struct timeval win32_tv; #endif int autospawn_fd = -1; pa_bool_t autospawn_locked = FALSE; #ifdef HAVE_DBUS pa_dbusobj_server_lookup *server_lookup = NULL; /* /org/pulseaudio/server_lookup */ pa_dbus_connection *lookup_service_bus = NULL; /* Always the user bus. */ pa_dbus_connection *server_bus = NULL; /* The bus where we reserve org.pulseaudio.Server, either the user or the system bus. */ pa_bool_t start_server; #endif pa_log_set_ident("pulseaudio"); pa_log_set_level(PA_LOG_NOTICE); pa_log_set_flags(PA_LOG_COLORS|PA_LOG_PRINT_FILE|PA_LOG_PRINT_LEVEL, PA_LOG_RESET); #if defined(__linux__) && defined(__OPTIMIZE__) /* Disable lazy relocations to make usage of external libraries more deterministic for our RT threads. We abuse __OPTIMIZE__ as a check whether we are a debug build or not. This all is admittedly a bit snake-oilish. */ if (!getenv("LD_BIND_NOW")) { char *rp; char *canonical_rp; /* We have to execute ourselves, because the libc caches the * value of $LD_BIND_NOW on initialization. */ pa_set_env("LD_BIND_NOW", "1"); if ((canonical_rp = pa_realpath(PA_BINARY))) { if ((rp = pa_readlink("/proc/self/exe"))) { if (pa_streq(rp, canonical_rp)) pa_assert_se(execv(rp, argv) == 0); else pa_log_warn("/proc/self/exe does not point to %s, cannot self execute. Are you playing games?", canonical_rp); pa_xfree(rp); } else pa_log_warn("Couldn't read /proc/self/exe, cannot self execute. Running in a chroot()?"); pa_xfree(canonical_rp); } else pa_log_warn("Couldn't canonicalize binary path, cannot self execute."); } #endif if ((e = getenv("PULSE_PASSED_FD"))) { passed_fd = atoi(e); if (passed_fd <= 2) passed_fd = -1; } /* We might be autospawned, in which case have no idea in which * context we have been started. Let's cleanup our execution * context as good as possible */ pa_reset_personality(); pa_drop_root(); pa_close_all(passed_fd, -1); pa_reset_sigs(-1); pa_unblock_sigs(-1); pa_reset_priority(); setlocale(LC_ALL, ""); pa_init_i18n(); conf = pa_daemon_conf_new(); if (pa_daemon_conf_load(conf, NULL) < 0) goto finish; if (pa_daemon_conf_env(conf) < 0) goto finish; if (pa_cmdline_parse(conf, argc, argv, &d) < 0) { pa_log(_("Failed to parse command line.")); goto finish; } pa_log_set_level(conf->log_level); pa_log_set_target(conf->auto_log_target ? PA_LOG_STDERR : conf->log_target); if (conf->log_meta) pa_log_set_flags(PA_LOG_PRINT_META, PA_LOG_SET); if (conf->log_time) pa_log_set_flags(PA_LOG_PRINT_TIME, PA_LOG_SET); pa_log_set_show_backtrace(conf->log_backtrace); #ifdef HAVE_DBUS /* conf->system_instance and conf->local_server_type control almost the * same thing; make them agree about what is requested. */ switch (conf->local_server_type) { case PA_SERVER_TYPE_UNSET: conf->local_server_type = conf->system_instance ? PA_SERVER_TYPE_SYSTEM : PA_SERVER_TYPE_USER; break; case PA_SERVER_TYPE_USER: case PA_SERVER_TYPE_NONE: conf->system_instance = FALSE; break; case PA_SERVER_TYPE_SYSTEM: conf->system_instance = TRUE; break; default: pa_assert_not_reached(); } start_server = conf->local_server_type == PA_SERVER_TYPE_USER || (getuid() == 0 && conf->local_server_type == PA_SERVER_TYPE_SYSTEM); if (!start_server && conf->local_server_type == PA_SERVER_TYPE_SYSTEM) { pa_log_notice(_("System mode refused for non-root user. Only starting the D-Bus server lookup service.")); conf->system_instance = FALSE; } #endif LTDL_SET_PRELOADED_SYMBOLS(); pa_ltdl_init(); ltdl_init = TRUE; if (conf->dl_search_path) lt_dlsetsearchpath(conf->dl_search_path); #ifdef OS_IS_WIN32 { WSADATA data; WSAStartup(MAKEWORD(2, 0), &data); } #endif pa_random_seed(); switch (conf->cmd) { case PA_CMD_DUMP_MODULES: pa_dump_modules(conf, argc-d, argv+d); retval = 0; goto finish; case PA_CMD_DUMP_CONF: { if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } s = pa_daemon_conf_dump(conf); fputs(s, stdout); pa_xfree(s); retval = 0; goto finish; } case PA_CMD_DUMP_RESAMPLE_METHODS: { int i; if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } for (i = 0; i < PA_RESAMPLER_MAX; i++) if (pa_resample_method_supported(i)) printf("%s\n", pa_resample_method_to_string(i)); retval = 0; goto finish; } case PA_CMD_HELP : pa_cmdline_help(argv[0]); retval = 0; goto finish; case PA_CMD_VERSION : if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } printf(PACKAGE_NAME" "PACKAGE_VERSION"\n"); retval = 0; goto finish; case PA_CMD_CHECK: { pid_t pid; if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } if (pa_pid_file_check_running(&pid, "pulseaudio") < 0) pa_log_info(_("Daemon not running")); else { pa_log_info(_("Daemon running as PID %u"), pid); retval = 0; } goto finish; } case PA_CMD_KILL: if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } if (pa_pid_file_kill(SIGINT, NULL, "pulseaudio") < 0) pa_log(_("Failed to kill daemon: %s"), pa_cstrerror(errno)); else retval = 0; goto finish; case PA_CMD_CLEANUP_SHM: if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } if (pa_shm_cleanup() >= 0) retval = 0; goto finish; default: pa_assert(conf->cmd == PA_CMD_DAEMON || conf->cmd == PA_CMD_START); } if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } #ifdef HAVE_GETUID if (getuid() == 0 && !conf->system_instance) pa_log_warn(_("This program is not intended to be run as root (unless --system is specified).")); #ifndef HAVE_DBUS /* A similar, only a notice worthy check was done earlier, if D-Bus is enabled. */ else if (getuid() != 0 && conf->system_instance) { pa_log(_("Root privileges required.")); goto finish; } #endif #endif /* HAVE_GETUID */ if (conf->cmd == PA_CMD_START && conf->system_instance) { pa_log(_("--start not supported for system instances.")); goto finish; } if (conf->cmd == PA_CMD_START && (configured_address = check_configured_address())) { /* There is an server address in our config, but where did it come from? * By default a standard X11 login will load module-x11-publish which will * inject PULSE_SERVER X11 property. If the PA daemon crashes, we will end * up hitting this code path. So we have to check to see if our configured_address * is the same as the value that would go into this property so that we can * recover (i.e. autospawn) from a crash. */ char *ufn; pa_bool_t start_anyway = FALSE; if ((ufn = pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET))) { char *id; if ((id = pa_machine_id())) { pa_strlist *server_list; char formatted_ufn[256]; pa_snprintf(formatted_ufn, sizeof(formatted_ufn), "{%s}unix:%s", id, ufn); pa_xfree(id); if ((server_list = pa_strlist_parse(configured_address))) { char *u = NULL; /* We only need to check the first server */ server_list = pa_strlist_pop(server_list, &u); pa_strlist_free(server_list); start_anyway = (u && pa_streq(formatted_ufn, u)); pa_xfree(u); } } pa_xfree(ufn); } if (!start_anyway) { pa_log_notice(_("User-configured server at %s, refusing to start/autospawn."), configured_address); pa_xfree(configured_address); retval = 0; goto finish; } pa_log_notice(_("User-configured server at %s, which appears to be local. Probing deeper."), configured_address); pa_xfree(configured_address); } if (conf->system_instance && !conf->disallow_exit) pa_log_warn(_("Running in system mode, but --disallow-exit not set!")); if (conf->system_instance && !conf->disallow_module_loading) pa_log_warn(_("Running in system mode, but --disallow-module-loading not set!")); if (conf->system_instance && !conf->disable_shm) { pa_log_notice(_("Running in system mode, forcibly disabling SHM mode!")); conf->disable_shm = TRUE; } if (conf->system_instance && conf->exit_idle_time >= 0) { pa_log_notice(_("Running in system mode, forcibly disabling exit idle time!")); conf->exit_idle_time = -1; } if (conf->cmd == PA_CMD_START) { /* If we shall start PA only when it is not running yet, we * first take the autospawn lock to make things * synchronous. */ if ((autospawn_fd = pa_autospawn_lock_init()) < 0) { pa_log("Failed to initialize autospawn lock"); goto finish; } if ((pa_autospawn_lock_acquire(TRUE) < 0)) { pa_log("Failed to acquire autospawn lock"); goto finish; } autospawn_locked = TRUE; } if (conf->daemonize) { #ifdef HAVE_FORK pid_t child; #endif if (pa_stdio_acquire() < 0) { pa_log(_("Failed to acquire stdio.")); goto finish; } #ifdef HAVE_FORK if (pipe(daemon_pipe) < 0) { pa_log(_("pipe() failed: %s"), pa_cstrerror(errno)); goto finish; } if ((child = fork()) < 0) { pa_log(_("fork() failed: %s"), pa_cstrerror(errno)); pa_close_pipe(daemon_pipe); goto finish; } if (child != 0) { ssize_t n; /* Father */ pa_assert_se(pa_close(daemon_pipe[1]) == 0); daemon_pipe[1] = -1; if ((n = pa_loop_read(daemon_pipe[0], &retval, sizeof(retval), NULL)) != sizeof(retval)) { if (n < 0) pa_log(_("read() failed: %s"), pa_cstrerror(errno)); retval = 1; } if (retval) pa_log(_("Daemon startup failed.")); else pa_log_info(_("Daemon startup successful.")); goto finish; } if (autospawn_fd >= 0) { /* The lock file is unlocked from the parent, so we need * to close it in the child */ pa_autospawn_lock_release(); pa_autospawn_lock_done(TRUE); autospawn_locked = FALSE; autospawn_fd = -1; } pa_assert_se(pa_close(daemon_pipe[0]) == 0); daemon_pipe[0] = -1; #endif if (conf->auto_log_target) pa_log_set_target(PA_LOG_SYSLOG); #ifdef HAVE_SETSID if (setsid() < 0) { pa_log(_("setsid() failed: %s"), pa_cstrerror(errno)); goto finish; } #endif #ifdef HAVE_FORK /* We now are a session and process group leader. Let's fork * again and let the father die, so that we'll become a * process that can never acquire a TTY again, in a session and * process group without leader */ if (pipe(daemon_pipe2) < 0) { pa_log(_("pipe() failed: %s"), pa_cstrerror(errno)); goto finish; } if ((child = fork()) < 0) { pa_log(_("fork() failed: %s"), pa_cstrerror(errno)); pa_close_pipe(daemon_pipe2); goto finish; } if (child != 0) { ssize_t n; /* Father */ pa_assert_se(pa_close(daemon_pipe2[1]) == 0); daemon_pipe2[1] = -1; if ((n = pa_loop_read(daemon_pipe2[0], &retval, sizeof(retval), NULL)) != sizeof(retval)) { if (n < 0) pa_log(_("read() failed: %s"), pa_cstrerror(errno)); retval = 1; } /* We now have to take care of signalling the first fork with * the return value we've received from this fork... */ pa_assert(daemon_pipe[1] >= 0); pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL); pa_close(daemon_pipe[1]); daemon_pipe[1] = -1; goto finish; } pa_assert_se(pa_close(daemon_pipe2[0]) == 0); daemon_pipe2[0] = -1; /* We no longer need the (first) daemon_pipe as it's handled in our child above */ pa_close_pipe(daemon_pipe); #endif #ifdef SIGTTOU signal(SIGTTOU, SIG_IGN); #endif #ifdef SIGTTIN signal(SIGTTIN, SIG_IGN); #endif #ifdef SIGTSTP signal(SIGTSTP, SIG_IGN); #endif pa_nullify_stdfds(); } pa_set_env_and_record("PULSE_INTERNAL", "1"); pa_assert_se(chdir("/") == 0); umask(0022); #ifdef HAVE_SYS_RESOURCE_H set_all_rlimits(conf); #endif pa_rtclock_hrtimer_enable(); pa_raise_priority(conf->nice_level); if (conf->system_instance) if (change_user() < 0) goto finish; pa_set_env_and_record("PULSE_SYSTEM", conf->system_instance ? "1" : "0"); pa_log_info(_("This is PulseAudio %s"), PACKAGE_VERSION); pa_log_debug(_("Compilation host: %s"), CANONICAL_HOST); pa_log_debug(_("Compilation CFLAGS: %s"), PA_CFLAGS); s = pa_uname_string(); pa_log_debug(_("Running on host: %s"), s); pa_xfree(s); pa_log_debug(_("Found %u CPUs."), pa_ncpus()); pa_log_info(_("Page size is %lu bytes"), (unsigned long) PA_PAGE_SIZE); #ifdef HAVE_VALGRIND_MEMCHECK_H pa_log_debug(_("Compiled with Valgrind support: yes")); #else pa_log_debug(_("Compiled with Valgrind support: no")); #endif pa_log_debug(_("Running in valgrind mode: %s"), pa_yes_no(pa_in_valgrind())); pa_log_debug(_("Running in VM: %s"), pa_yes_no(pa_running_in_vm())); #ifdef __OPTIMIZE__ pa_log_debug(_("Optimized build: yes")); #else pa_log_debug(_("Optimized build: no")); #endif #ifdef NDEBUG pa_log_debug(_("NDEBUG defined, all asserts disabled.")); #elif defined(FASTPATH) pa_log_debug(_("FASTPATH defined, only fast path asserts disabled.")); #else pa_log_debug(_("All asserts enabled.")); #endif if (!(s = pa_machine_id())) { pa_log(_("Failed to get machine ID")); goto finish; } pa_log_info(_("Machine ID is %s."), s); pa_xfree(s); if ((s = pa_session_id())) { pa_log_info(_("Session ID is %s."), s); pa_xfree(s); } if (!(s = pa_get_runtime_dir())) goto finish; pa_log_info(_("Using runtime directory %s."), s); pa_xfree(s); if (!(s = pa_get_state_dir())) goto finish; pa_log_info(_("Using state directory %s."), s); pa_xfree(s); pa_log_info(_("Using modules directory %s."), conf->dl_search_path); pa_log_info(_("Running in system mode: %s"), pa_yes_no(pa_in_system_mode())); if (pa_in_system_mode()) pa_log_warn(_("OK, so you are running PA in system mode. Please note that you most likely shouldn't be doing that.\n" "If you do it nonetheless then it's your own fault if things don't work as expected.\n" "Please read http://pulseaudio.org/wiki/WhatIsWrongWithSystemMode for an explanation why system mode is usually a bad idea.")); if (conf->use_pid_file) { int z; if ((z = pa_pid_file_create("pulseaudio")) != 0) { if (conf->cmd == PA_CMD_START && z > 0) { /* If we are already running and with are run in * --start mode, then let's return this as success. */ retval = 0; goto finish; } pa_log(_("pa_pid_file_create() failed.")); goto finish; } valid_pid_file = TRUE; } pa_disable_sigpipe(); if (pa_rtclock_hrtimer()) pa_log_info(_("Fresh high-resolution timers available! Bon appetit!")); else pa_log_info(_("Dude, your kernel stinks! The chef's recommendation today is Linux with high-resolution timers enabled!")); if (conf->lock_memory) { #ifdef HAVE_SYS_MMAN_H if (mlockall(MCL_FUTURE) < 0) pa_log_warn("mlockall() failed: %s", pa_cstrerror(errno)); else pa_log_info("Successfully locked process into memory."); #else pa_log_warn("Memory locking requested but not supported on platform."); #endif } pa_memtrap_install(); pa_assert_se(mainloop = pa_mainloop_new()); if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm, conf->shm_size))) { pa_log(_("pa_core_new() failed.")); goto finish; } c->default_sample_spec = conf->default_sample_spec; c->alternate_sample_rate = conf->alternate_sample_rate; c->default_channel_map = conf->default_channel_map; c->default_n_fragments = conf->default_n_fragments; c->default_fragment_size_msec = conf->default_fragment_size_msec; c->deferred_volume_safety_margin_usec = conf->deferred_volume_safety_margin_usec; c->deferred_volume_extra_delay_usec = conf->deferred_volume_extra_delay_usec; c->exit_idle_time = conf->exit_idle_time; c->scache_idle_time = conf->scache_idle_time; c->resample_method = conf->resample_method; c->realtime_priority = conf->realtime_priority; c->realtime_scheduling = !!conf->realtime_scheduling; c->disable_remixing = !!conf->disable_remixing; c->disable_lfe_remixing = !!conf->disable_lfe_remixing; c->deferred_volume = !!conf->deferred_volume; c->running_as_daemon = !!conf->daemonize; c->disallow_exit = conf->disallow_exit; c->flat_volumes = conf->flat_volumes; #ifdef HAVE_DBUS c->server_type = conf->local_server_type; #endif c->cpu_info.cpu_type = PA_CPU_UNDEFINED; if (!getenv("PULSE_NO_SIMD")) { if (pa_cpu_init_x86(&(c->cpu_info.flags.x86))) c->cpu_info.cpu_type = PA_CPU_X86; if (pa_cpu_init_arm(&(c->cpu_info.flags.arm))) c->cpu_info.cpu_type = PA_CPU_ARM; pa_cpu_init_orc(c->cpu_info); } pa_assert_se(pa_signal_init(pa_mainloop_get_api(mainloop)) == 0); pa_signal_new(SIGINT, signal_callback, c); pa_signal_new(SIGTERM, signal_callback, c); #ifdef SIGUSR1 pa_signal_new(SIGUSR1, signal_callback, c); #endif #ifdef SIGUSR2 pa_signal_new(SIGUSR2, signal_callback, c); #endif #ifdef SIGHUP pa_signal_new(SIGHUP, signal_callback, c); #endif #ifdef OS_IS_WIN32 win32_timer = pa_mainloop_get_api(mainloop)->time_new(pa_mainloop_get_api(mainloop), pa_gettimeofday(&win32_tv), message_cb, NULL); #endif if (!conf->no_cpu_limit) pa_assert_se(pa_cpu_limit_init(pa_mainloop_get_api(mainloop)) == 0); buf = pa_strbuf_new(); #ifdef HAVE_DBUS pa_assert_se(dbus_threads_init_default()); if (start_server) { #endif if (conf->load_default_script_file) { FILE *f; if ((f = pa_daemon_conf_open_default_script_file(conf))) { r = pa_cli_command_execute_file_stream(c, f, buf, &conf->fail); fclose(f); } } if (r >= 0) r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail); pa_log_error("%s", s = pa_strbuf_tostring_free(buf)); pa_xfree(s); if (r < 0 && conf->fail) { pa_log(_("Failed to initialize daemon.")); goto finish; } if (!c->modules || pa_idxset_size(c->modules) == 0) { pa_log(_("Daemon startup without any loaded modules, refusing to work.")); goto finish; } #ifdef HAVE_DBUS } else { /* When we just provide the D-Bus server lookup service, we don't want * any modules to be loaded. We haven't loaded any so far, so one might * think there's no way to contact the server, but receiving certain * signals could still cause modules to load. */ conf->disallow_module_loading = TRUE; } #endif /* We completed the initial module loading, so let's disable it * from now on, if requested */ c->disallow_module_loading = !!conf->disallow_module_loading; #ifdef HAVE_DBUS if (!conf->system_instance) { if ((server_lookup = pa_dbusobj_server_lookup_new(c))) { if (!(lookup_service_bus = register_dbus_name(c, DBUS_BUS_SESSION, "org.PulseAudio1"))) goto finish; } } if (start_server) server_bus = register_dbus_name(c, conf->system_instance ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION, "org.pulseaudio.Server"); #endif #ifdef HAVE_FORK if (daemon_pipe2[1] >= 0) { int ok = 0; pa_loop_write(daemon_pipe2[1], &ok, sizeof(ok), NULL); pa_close(daemon_pipe2[1]); daemon_pipe2[1] = -1; } #endif pa_log_info(_("Daemon startup complete.")); retval = 0; if (pa_mainloop_run(mainloop, &retval) < 0) goto finish; pa_log_info(_("Daemon shutdown initiated.")); finish: #ifdef HAVE_DBUS if (server_bus) pa_dbus_connection_unref(server_bus); if (lookup_service_bus) pa_dbus_connection_unref(lookup_service_bus); if (server_lookup) pa_dbusobj_server_lookup_free(server_lookup); #endif if (autospawn_fd >= 0) { if (autospawn_locked) pa_autospawn_lock_release(); pa_autospawn_lock_done(FALSE); } #ifdef OS_IS_WIN32 if (mainloop && win32_timer) pa_mainloop_get_api(mainloop)->time_free(win32_timer); #endif if (c) { /* Ensure all the modules/samples are unloaded when the core is still ref'ed, * as unlink callback hooks in modules may need the core to be ref'ed */ pa_module_unload_all(c); pa_scache_free_all(c); pa_core_unref(c); pa_log_info(_("Daemon terminated.")); } if (!conf->no_cpu_limit) pa_cpu_limit_done(); pa_signal_done(); #ifdef HAVE_FORK /* If we have daemon_pipe[1] still open, this means we've failed after * the first fork, but before the second. Therefore just write to it. */ if (daemon_pipe[1] >= 0) pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL); else if (daemon_pipe2[1] >= 0) pa_loop_write(daemon_pipe2[1], &retval, sizeof(retval), NULL); pa_close_pipe(daemon_pipe2); pa_close_pipe(daemon_pipe); #endif if (mainloop) pa_mainloop_free(mainloop); if (conf) pa_daemon_conf_free(conf); if (valid_pid_file) pa_pid_file_remove(); /* This has no real purpose except making things valgrind-clean */ pa_unset_env_recorded(); #ifdef OS_IS_WIN32 WSACleanup(); #endif if (ltdl_init) pa_ltdl_done(); #ifdef HAVE_DBUS dbus_shutdown(); #endif return retval; }
char *pa_sink_input_list_to_string(pa_core *c) { pa_strbuf *s; pa_sink_input *i; uint32_t idx = PA_IDXSET_INVALID; static const char* const state_table[] = { [PA_SINK_INPUT_INIT] = "INIT", [PA_SINK_INPUT_RUNNING] = "RUNNING", [PA_SINK_INPUT_DRAINED] = "DRAINED", [PA_SINK_INPUT_CORKED] = "CORKED", [PA_SINK_INPUT_UNLINKED] = "UNLINKED" }; pa_assert(c); s = pa_strbuf_new(); pa_strbuf_printf(s, "%u sink input(s) available.\n", pa_idxset_size(c->sink_inputs)); for (i = pa_idxset_first(c->sink_inputs, &idx); i; i = pa_idxset_next(c->sink_inputs, &idx)) { char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cvdb[PA_SW_CVOLUME_SNPRINT_DB_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t, clt[28]; pa_usec_t cl; const char *cmn; pa_cvolume v; char *volume_str = NULL; cmn = pa_channel_map_to_pretty_name(&i->channel_map); if ((cl = pa_sink_input_get_requested_latency(i)) == (pa_usec_t) -1) pa_snprintf(clt, sizeof(clt), "n/a"); else pa_snprintf(clt, sizeof(clt), "%0.2f ms", (double) cl / PA_USEC_PER_MSEC); pa_assert(i->sink); if (pa_sink_input_is_volume_readable(i)) { pa_sink_input_get_volume(i, &v, TRUE); volume_str = pa_sprintf_malloc("%s\n\t %s\n\t balance %0.2f", pa_cvolume_snprint(cv, sizeof(cv), &v), pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), &v), pa_cvolume_get_balance(&v, &i->channel_map)); } else volume_str = pa_xstrdup("n/a"); pa_strbuf_printf( s, " index: %u\n" "\tdriver: <%s>\n" "\tflags: %s%s%s%s%s%s%s%s%s%s%s\n" "\tstate: %s\n" "\tsink: %u <%s>\n" "\tvolume: %s\n" "\tmuted: %s\n" "\tcurrent latency: %0.2f ms\n" "\trequested latency: %s\n" "\tsample spec: %s\n" "\tchannel map: %s%s%s\n" "\tresample method: %s\n", i->index, i->driver, i->flags & PA_SINK_INPUT_VARIABLE_RATE ? "VARIABLE_RATE " : "", i->flags & PA_SINK_INPUT_DONT_MOVE ? "DONT_MOVE " : "", i->flags & PA_SINK_INPUT_START_CORKED ? "START_CORKED " : "", i->flags & PA_SINK_INPUT_NO_REMAP ? "NO_REMAP " : "", i->flags & PA_SINK_INPUT_NO_REMIX ? "NO_REMIX " : "", i->flags & PA_SINK_INPUT_FIX_FORMAT ? "FIX_FORMAT " : "", i->flags & PA_SINK_INPUT_FIX_RATE ? "FIX_RATE " : "", i->flags & PA_SINK_INPUT_FIX_CHANNELS ? "FIX_CHANNELS " : "", i->flags & PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND ? "DONT_INHIBIT_AUTO_SUSPEND " : "", i->flags & PA_SINK_INPUT_NO_CREATE_ON_SUSPEND ? "NO_CREATE_SUSPEND " : "", i->flags & PA_SINK_INPUT_KILL_ON_SUSPEND ? "KILL_ON_SUSPEND " : "", state_table[pa_sink_input_get_state(i)], i->sink->index, i->sink->name, volume_str, pa_yes_no(pa_sink_input_get_mute(i)), (double) pa_sink_input_get_latency(i, NULL) / PA_USEC_PER_MSEC, clt, pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec), pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map), cmn ? "\n\t " : "", cmn ? cmn : "", pa_resample_method_to_string(pa_sink_input_get_resample_method(i))); pa_xfree(volume_str); if (i->module) pa_strbuf_printf(s, "\tmodule: %u\n", i->module->index); if (i->client) pa_strbuf_printf(s, "\tclient: %u <%s>\n", i->client->index, pa_strnull(pa_proplist_gets(i->client->proplist, PA_PROP_APPLICATION_NAME))); t = pa_proplist_to_string_sep(i->proplist, "\n\t\t"); pa_strbuf_printf(s, "\tproperties:\n\t\t%s\n", t); pa_xfree(t); } return pa_strbuf_tostring_free(s); }
char *pa_source_output_list_to_string(pa_core *c) { pa_strbuf *s; pa_source_output *o; uint32_t idx = PA_IDXSET_INVALID; static const char* const state_table[] = { [PA_SOURCE_OUTPUT_INIT] = "INIT", [PA_SOURCE_OUTPUT_RUNNING] = "RUNNING", [PA_SOURCE_OUTPUT_CORKED] = "CORKED", [PA_SOURCE_OUTPUT_UNLINKED] = "UNLINKED" }; pa_assert(c); s = pa_strbuf_new(); pa_strbuf_printf(s, "%u source outputs(s) available.\n", pa_idxset_size(c->source_outputs)); for (o = pa_idxset_first(c->source_outputs, &idx); o; o = pa_idxset_next(c->source_outputs, &idx)) { char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t, clt[28]; pa_usec_t cl; const char *cmn; cmn = pa_channel_map_to_pretty_name(&o->channel_map); if ((cl = pa_source_output_get_requested_latency(o)) == (pa_usec_t) -1) pa_snprintf(clt, sizeof(clt), "n/a"); else pa_snprintf(clt, sizeof(clt), "%0.2f ms", (double) cl / PA_USEC_PER_MSEC); pa_assert(o->source); pa_strbuf_printf( s, " index: %u\n" "\tdriver: <%s>\n" "\tflags: %s%s%s%s%s%s%s%s%s%s%s\n" "\tstate: %s\n" "\tsource: %u <%s>\n" "\tcurrent latency: %0.2f ms\n" "\trequested latency: %s\n" "\tsample spec: %s\n" "\tchannel map: %s%s%s\n" "\tresample method: %s\n", o->index, o->driver, o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE ? "VARIABLE_RATE " : "", o->flags & PA_SOURCE_OUTPUT_DONT_MOVE ? "DONT_MOVE " : "", o->flags & PA_SOURCE_OUTPUT_START_CORKED ? "START_CORKED " : "", o->flags & PA_SOURCE_OUTPUT_NO_REMAP ? "NO_REMAP " : "", o->flags & PA_SOURCE_OUTPUT_NO_REMIX ? "NO_REMIX " : "", o->flags & PA_SOURCE_OUTPUT_FIX_FORMAT ? "FIX_FORMAT " : "", o->flags & PA_SOURCE_OUTPUT_FIX_RATE ? "FIX_RATE " : "", o->flags & PA_SOURCE_OUTPUT_FIX_CHANNELS ? "FIX_CHANNELS " : "", o->flags & PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND ? "DONT_INHIBIT_AUTO_SUSPEND " : "", o->flags & PA_SOURCE_OUTPUT_NO_CREATE_ON_SUSPEND ? "NO_CREATE_ON_SUSPEND " : "", o->flags & PA_SOURCE_OUTPUT_KILL_ON_SUSPEND ? "KILL_ON_SUSPEND " : "", state_table[pa_source_output_get_state(o)], o->source->index, o->source->name, (double) pa_source_output_get_latency(o, NULL) / PA_USEC_PER_MSEC, clt, pa_sample_spec_snprint(ss, sizeof(ss), &o->sample_spec), pa_channel_map_snprint(cm, sizeof(cm), &o->channel_map), cmn ? "\n\t " : "", cmn ? cmn : "", pa_resample_method_to_string(pa_source_output_get_resample_method(o))); if (o->module) pa_strbuf_printf(s, "\towner module: %u\n", o->module->index); if (o->client) pa_strbuf_printf(s, "\tclient: %u <%s>\n", o->client->index, pa_strnull(pa_proplist_gets(o->client->proplist, PA_PROP_APPLICATION_NAME))); if (o->direct_on_input) pa_strbuf_printf(s, "\tdirect on input: %u\n", o->direct_on_input->index); t = pa_proplist_to_string_sep(o->proplist, "\n\t\t"); pa_strbuf_printf(s, "\tproperties:\n\t\t%s\n", t); pa_xfree(t); } return pa_strbuf_tostring_free(s); }
char *pa_source_list_to_string(pa_core *c) { pa_strbuf *s; pa_source *source; uint32_t idx = PA_IDXSET_INVALID; pa_assert(c); s = pa_strbuf_new(); pa_strbuf_printf(s, "%u source(s) available.\n", pa_idxset_size(c->sources)); for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) { char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cvdb[PA_SW_CVOLUME_SNPRINT_DB_MAX], v[PA_VOLUME_SNPRINT_MAX], vdb[PA_SW_VOLUME_SNPRINT_DB_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], *t; const char *cmn; cmn = pa_channel_map_to_pretty_name(&source->channel_map); pa_strbuf_printf( s, " %c index: %u\n" "\tname: <%s>\n" "\tdriver: <%s>\n" "\tflags: %s%s%s%s%s%s%s\n" "\tstate: %s\n" "\tsuspend cause: %s%s%s%s\n" "\tpriority: %u\n" "\tvolume: %s%s%s\n" "\t balance %0.2f\n" "\tbase volume: %s%s%s\n" "\tvolume steps: %u\n" "\tmuted: %s\n" "\tcurrent latency: %0.2f ms\n" "\tmax rewind: %lu KiB\n" "\tsample spec: %s\n" "\tchannel map: %s%s%s\n" "\tused by: %u\n" "\tlinked by: %u\n", c->default_source == source ? '*' : ' ', source->index, source->name, source->driver, source->flags & PA_SOURCE_HARDWARE ? "HARDWARE " : "", source->flags & PA_SOURCE_NETWORK ? "NETWORK " : "", source->flags & PA_SOURCE_HW_MUTE_CTRL ? "HW_MUTE_CTRL " : "", source->flags & PA_SOURCE_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "", source->flags & PA_SOURCE_DECIBEL_VOLUME ? "DECIBEL_VOLUME " : "", source->flags & PA_SOURCE_LATENCY ? "LATENCY " : "", source->flags & PA_SOURCE_DYNAMIC_LATENCY ? "DYNAMIC_LATENCY" : "", source_state_to_string(pa_source_get_state(source)), source->suspend_cause & PA_SUSPEND_USER ? "USER " : "", source->suspend_cause & PA_SUSPEND_APPLICATION ? "APPLICATION " : "", source->suspend_cause & PA_SUSPEND_IDLE ? "IDLE " : "", source->suspend_cause & PA_SUSPEND_SESSION ? "SESSION" : "", source->priority, pa_cvolume_snprint(cv, sizeof(cv), pa_source_get_volume(source, FALSE)), source->flags & PA_SOURCE_DECIBEL_VOLUME ? "\n\t " : "", source->flags & PA_SOURCE_DECIBEL_VOLUME ? pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), pa_source_get_volume(source, FALSE)) : "", pa_cvolume_get_balance(pa_source_get_volume(source, FALSE), &source->channel_map), pa_volume_snprint(v, sizeof(v), source->base_volume), source->flags & PA_SOURCE_DECIBEL_VOLUME ? "\n\t " : "", source->flags & PA_SOURCE_DECIBEL_VOLUME ? pa_sw_volume_snprint_dB(vdb, sizeof(vdb), source->base_volume) : "", source->n_volume_steps, pa_yes_no(pa_source_get_mute(source, FALSE)), (double) pa_source_get_latency(source) / PA_USEC_PER_MSEC, (unsigned long) pa_source_get_max_rewind(source) / 1024, pa_sample_spec_snprint(ss, sizeof(ss), &source->sample_spec), pa_channel_map_snprint(cm, sizeof(cm), &source->channel_map), cmn ? "\n\t " : "", cmn ? cmn : "", pa_source_used_by(source), pa_source_linked_by(source)); if (source->flags & PA_SOURCE_DYNAMIC_LATENCY) { pa_usec_t min_latency, max_latency; pa_source_get_latency_range(source, &min_latency, &max_latency); pa_strbuf_printf( s, "\tconfigured latency: %0.2f ms; range is %0.2f .. %0.2f ms\n", (double) pa_source_get_requested_latency(source) / PA_USEC_PER_MSEC, (double) min_latency / PA_USEC_PER_MSEC, (double) max_latency / PA_USEC_PER_MSEC); } else pa_strbuf_printf( s, "\tfixed latency: %0.2f ms\n", (double) pa_source_get_fixed_latency(source) / PA_USEC_PER_MSEC); if (source->monitor_of) pa_strbuf_printf(s, "\tmonitor_of: %u\n", source->monitor_of->index); if (source->card) pa_strbuf_printf(s, "\tcard: %u <%s>\n", source->card->index, source->card->name); if (source->module) pa_strbuf_printf(s, "\tmodule: %u\n", source->module->index); t = pa_proplist_to_string_sep(source->proplist, "\n\t\t"); pa_strbuf_printf(s, "\tproperties:\n\t\t%s\n", t); pa_xfree(t); append_port_list(s, source->ports); if (source->active_port) pa_strbuf_printf( s, "\tactive port: <%s>\n", source->active_port->name); } return pa_strbuf_tostring_free(s); }
char *pa_daemon_conf_dump(pa_daemon_conf *c) { static const char* const log_level_to_string[] = { [PA_LOG_DEBUG] = "debug", [PA_LOG_INFO] = "info", [PA_LOG_NOTICE] = "notice", [PA_LOG_WARN] = "warning", [PA_LOG_ERROR] = "error" }; pa_strbuf *s; char cm[PA_CHANNEL_MAP_SNPRINT_MAX]; pa_assert(c); s = pa_strbuf_new(); if (c->config_file) pa_strbuf_printf(s, _("### Read from configuration file: %s ###\n"), c->config_file); pa_assert(c->log_level < PA_LOG_LEVEL_MAX); pa_strbuf_printf(s, "daemonize = %s\n", pa_yes_no(c->daemonize)); pa_strbuf_printf(s, "fail = %s\n", pa_yes_no(c->fail)); pa_strbuf_printf(s, "high-priority = %s\n", pa_yes_no(c->high_priority)); pa_strbuf_printf(s, "nice-level = %i\n", c->nice_level); pa_strbuf_printf(s, "realtime-scheduling = %s\n", pa_yes_no(c->realtime_scheduling)); pa_strbuf_printf(s, "realtime-priority = %i\n", c->realtime_priority); pa_strbuf_printf(s, "allow-module-loading = %s\n", pa_yes_no(!c->disallow_module_loading)); pa_strbuf_printf(s, "allow-exit = %s\n", pa_yes_no(!c->disallow_exit)); pa_strbuf_printf(s, "use-pid-file = %s\n", pa_yes_no(c->use_pid_file)); pa_strbuf_printf(s, "system-instance = %s\n", pa_yes_no(c->system_instance)); pa_strbuf_printf(s, "cpu-limit = %s\n", pa_yes_no(!c->no_cpu_limit)); pa_strbuf_printf(s, "enable-shm = %s\n", pa_yes_no(!c->disable_shm)); pa_strbuf_printf(s, "flat-volumes = %s\n", pa_yes_no(c->flat_volumes)); pa_strbuf_printf(s, "lock-memory = %s\n", pa_yes_no(c->lock_memory)); pa_strbuf_printf(s, "exit-idle-time = %i\n", c->exit_idle_time); pa_strbuf_printf(s, "scache-idle-time = %i\n", c->scache_idle_time); pa_strbuf_printf(s, "dl-search-path = %s\n", pa_strempty(c->dl_search_path)); pa_strbuf_printf(s, "default-script-file = %s\n", pa_strempty(pa_daemon_conf_get_default_script_file(c))); pa_strbuf_printf(s, "load-default-script-file = %s\n", pa_yes_no(c->load_default_script_file)); pa_strbuf_printf(s, "log-target = %s\n", c->auto_log_target ? "auto" : (c->log_target == PA_LOG_SYSLOG ? "syslog" : "stderr")); pa_strbuf_printf(s, "log-level = %s\n", log_level_to_string[c->log_level]); pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method)); pa_strbuf_printf(s, "enable-remixing = %s\n", pa_yes_no(!c->disable_remixing)); pa_strbuf_printf(s, "enable-lfe-remixing = %s\n", pa_yes_no(!c->disable_lfe_remixing)); pa_strbuf_printf(s, "default-sample-format = %s\n", pa_sample_format_to_string(c->default_sample_spec.format)); pa_strbuf_printf(s, "default-sample-rate = %u\n", c->default_sample_spec.rate); pa_strbuf_printf(s, "default-sample-channels = %u\n", c->default_sample_spec.channels); pa_strbuf_printf(s, "default-channel-map = %s\n", pa_channel_map_snprint(cm, sizeof(cm), &c->default_channel_map)); pa_strbuf_printf(s, "default-fragments = %u\n", c->default_n_fragments); pa_strbuf_printf(s, "default-fragment-size-msec = %u\n", c->default_fragment_size_msec); pa_strbuf_printf(s, "shm-size-bytes = %lu\n", (unsigned long) c->shm_size); pa_strbuf_printf(s, "log-meta = %s\n", pa_yes_no(c->log_meta)); pa_strbuf_printf(s, "log-time = %s\n", pa_yes_no(c->log_time)); pa_strbuf_printf(s, "log-backtrace = %u\n", c->log_backtrace); #ifdef HAVE_SYS_RESOURCE_H pa_strbuf_printf(s, "rlimit-fsize = %li\n", c->rlimit_fsize.is_set ? (long int) c->rlimit_fsize.value : -1); pa_strbuf_printf(s, "rlimit-data = %li\n", c->rlimit_data.is_set ? (long int) c->rlimit_data.value : -1); pa_strbuf_printf(s, "rlimit-stack = %li\n", c->rlimit_stack.is_set ? (long int) c->rlimit_stack.value : -1); pa_strbuf_printf(s, "rlimit-core = %li\n", c->rlimit_core.is_set ? (long int) c->rlimit_core.value : -1); #ifdef RLIMIT_RSS pa_strbuf_printf(s, "rlimit-rss = %li\n", c->rlimit_rss.is_set ? (long int) c->rlimit_rss.value : -1); #endif #ifdef RLIMIT_AS pa_strbuf_printf(s, "rlimit-as = %li\n", c->rlimit_as.is_set ? (long int) c->rlimit_as.value : -1); #endif #ifdef RLIMIT_NPROC pa_strbuf_printf(s, "rlimit-nproc = %li\n", c->rlimit_nproc.is_set ? (long int) c->rlimit_nproc.value : -1); #endif #ifdef RLIMIT_NOFILE pa_strbuf_printf(s, "rlimit-nofile = %li\n", c->rlimit_nofile.is_set ? (long int) c->rlimit_nofile.value : -1); #endif #ifdef RLIMIT_MEMLOCK pa_strbuf_printf(s, "rlimit-memlock = %li\n", c->rlimit_memlock.is_set ? (long int) c->rlimit_memlock.value : -1); #endif #ifdef RLIMIT_LOCKS pa_strbuf_printf(s, "rlimit-locks = %li\n", c->rlimit_locks.is_set ? (long int) c->rlimit_locks.value : -1); #endif #ifdef RLIMIT_SIGPENDING pa_strbuf_printf(s, "rlimit-sigpending = %li\n", c->rlimit_sigpending.is_set ? (long int) c->rlimit_sigpending.value : -1); #endif #ifdef RLIMIT_MSGQUEUE pa_strbuf_printf(s, "rlimit-msgqueue = %li\n", c->rlimit_msgqueue.is_set ? (long int) c->rlimit_msgqueue.value : -1); #endif #ifdef RLIMIT_NICE pa_strbuf_printf(s, "rlimit-nice = %li\n", c->rlimit_nice.is_set ? (long int) c->rlimit_nice.value : -1); #endif #ifdef RLIMIT_RTPRIO pa_strbuf_printf(s, "rlimit-rtprio = %li\n", c->rlimit_rtprio.is_set ? (long int) c->rlimit_rtprio.value : -1); #endif #ifdef RLIMIT_RTTIME pa_strbuf_printf(s, "rlimit-rttime = %li\n", c->rlimit_rttime.is_set ? (long int) c->rlimit_rttime.value : -1); #endif #endif return pa_strbuf_tostring_free(s); }
int pa_cmdline_parse(pa_daemon_conf *conf, int argc, char *const argv [], int *d) { pa_strbuf *buf = NULL; int c; pa_assert(conf); pa_assert(argc > 0); pa_assert(argv); buf = pa_strbuf_new(); if (conf->script_commands) pa_strbuf_puts(buf, conf->script_commands); while ((c = getopt_long(argc, argv, "L:F:ChDnp:kv", long_options, NULL)) != -1) { switch (c) { case ARG_HELP: case 'h': conf->cmd = PA_CMD_HELP; break; case ARG_VERSION: conf->cmd = PA_CMD_VERSION; break; case ARG_DUMP_CONF: conf->cmd = PA_CMD_DUMP_CONF; break; case ARG_DUMP_MODULES: conf->cmd = PA_CMD_DUMP_MODULES; break; case ARG_DUMP_RESAMPLE_METHODS: conf->cmd = PA_CMD_DUMP_RESAMPLE_METHODS; break; case ARG_CLEANUP_SHM: conf->cmd = PA_CMD_CLEANUP_SHM; break; case 'k': case ARG_KILL: conf->cmd = PA_CMD_KILL; break; case ARG_CHECK: conf->cmd = PA_CMD_CHECK; break; case ARG_LOAD: case 'L': pa_strbuf_printf(buf, "load-module %s\n", optarg); break; case ARG_FILE: case 'F': { char *p; pa_strbuf_printf(buf, ".include %s\n", p = pa_make_path_absolute(optarg)); pa_xfree(p); break; } case 'C': pa_strbuf_puts(buf, "load-module module-cli exit_on_eof=1\n"); break; case ARG_DAEMONIZE: case 'D': if ((conf->daemonize = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) { pa_log("--daemonize expects boolean argument"); goto fail; } break; case ARG_FAIL: if ((conf->fail = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) { pa_log("--fail expects boolean argument"); goto fail; } break; case 'v': case ARG_LOG_LEVEL: if (optarg) { if (pa_daemon_conf_set_log_level(conf, optarg) < 0) { pa_log("--log-level expects log level argument (either numeric in range 0..4 or one of debug, info, notice, warn, error)."); goto fail; } } else { if (conf->log_level < PA_LOG_LEVEL_MAX-1) conf->log_level++; } break; case ARG_HIGH_PRIORITY: if ((conf->high_priority = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) { pa_log("--high-priority expects boolean argument"); goto fail; } break; case ARG_REALTIME: if ((conf->realtime_scheduling = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) { pa_log("--realtime expects boolean argument"); goto fail; } break; case ARG_DISALLOW_MODULE_LOADING: if ((conf->disallow_module_loading = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) { pa_log("--disallow-module-loading expects boolean argument"); goto fail; } break; case ARG_USE_PID_FILE: if ((conf->use_pid_file = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) { pa_log("--use-pid-file expects boolean argument"); goto fail; } break; case 'p': case ARG_DL_SEARCH_PATH: pa_xfree(conf->dl_search_path); conf->dl_search_path = *optarg ? pa_xstrdup(optarg) : NULL; break; case 'n': pa_xfree(conf->default_script_file); conf->default_script_file = NULL; break; case ARG_LOG_TARGET: if (pa_daemon_conf_set_log_target(conf, optarg) < 0) { pa_log("Invalid log target: use either 'syslog', 'stderr' or 'auto'."); goto fail; } break; case ARG_EXIT_IDLE_TIME: conf->exit_idle_time = atoi(optarg); break; case ARG_MODULE_IDLE_TIME: conf->module_idle_time = atoi(optarg); break; case ARG_SCACHE_IDLE_TIME: conf->scache_idle_time = atoi(optarg); break; case ARG_RESAMPLE_METHOD: if (pa_daemon_conf_set_resample_method(conf, optarg) < 0) { pa_log("Invalid resample method '%s'.", optarg); goto fail; } break; case ARG_SYSTEM: if ((conf->system_instance = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) { pa_log("--system expects boolean argument"); goto fail; } break; case ARG_NO_CPU_LIMIT: if ((conf->no_cpu_limit = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) { pa_log("--no-cpu-limit expects boolean argument"); goto fail; } break; case ARG_DISABLE_SHM: if ((conf->disable_shm = optarg ? pa_parse_boolean(optarg) : TRUE) < 0) { pa_log("--disable-shm expects boolean argument"); goto fail; } break; default: goto fail; } } pa_xfree(conf->script_commands); conf->script_commands = pa_strbuf_tostring_free(buf); if (!conf->script_commands) { pa_xfree(conf->script_commands); conf->script_commands = NULL; } *d = optind; return 0; fail: if (buf) pa_strbuf_free(buf); return -1; }
static void line_callback(pa_ioline *line, const char *s, void *userdata) { char *delimpos; char *s2, *s2p; pa_rtsp_client *c = userdata; pa_assert(line); pa_assert(c); pa_assert(c->callback); if (!s) { /* Keep the ioline/iochannel open as they will be freed automatically */ c->ioline = NULL; c->callback(c, STATE_DISCONNECTED, NULL, c->userdata); return; } s2 = pa_xstrdup(s); /* Trim trailing carriage returns */ s2p = s2 + strlen(s2) - 1; while (s2p >= s2 && '\r' == *s2p) { *s2p = '\0'; s2p -= 1; } if (c->waiting && 0 == strcmp("RTSP/1.0 200 OK", s2)) { c->waiting = 0; if (c->response_headers) pa_headerlist_free(c->response_headers); c->response_headers = pa_headerlist_new(); goto exit; } if (c->waiting) { pa_log_warn("Unexpected response: %s", s2); goto exit;; } if (!strlen(s2)) { /* End of headers */ /* We will have a header left from our looping iteration, so add it in :) */ if (c->last_header) { char *tmp = pa_strbuf_tostring_free(c->header_buffer); /* This is not a continuation header so let's dump it into our proplist */ pa_headerlist_puts(c->response_headers, c->last_header, tmp); pa_xfree(tmp); pa_xfree(c->last_header); c->last_header = NULL; c->header_buffer = NULL; } pa_log_debug("Full response received. Dispatching"); headers_read(c); c->waiting = 1; goto exit; } /* Read and parse a header (we know it's not empty) */ /* TODO: Move header reading into the headerlist. */ /* If the first character is a space, it's a continuation header */ if (c->last_header && ' ' == s2[0]) { pa_assert(c->header_buffer); /* Add this line to the buffer (sans the space. */ pa_strbuf_puts(c->header_buffer, &(s2[1])); goto exit; } if (c->last_header) { char *tmp = pa_strbuf_tostring_free(c->header_buffer); /* This is not a continuation header so let's dump the full header/value into our proplist */ pa_headerlist_puts(c->response_headers, c->last_header, tmp); pa_xfree(tmp); pa_xfree(c->last_header); c->last_header = NULL; c->header_buffer = NULL; } delimpos = strstr(s2, ":"); if (!delimpos) { pa_log_warn("Unexpected response when expecting header: %s", s); goto exit; } pa_assert(!c->header_buffer); pa_assert(!c->last_header); c->header_buffer = pa_strbuf_new(); if (strlen(delimpos) > 1) { /* Cut our line off so we can copy the header name out */ *delimpos++ = '\0'; /* Trim the front of any spaces */ while (' ' == *delimpos) ++delimpos; pa_strbuf_puts(c->header_buffer, delimpos); } else { /* Cut our line off so we can copy the header name out */ *delimpos = '\0'; } /* Save the header name */ c->last_header = pa_xstrdup(s2); exit: pa_xfree(s2); }
char *pa_source_list_to_string(pa_core *c) { pa_strbuf *s; pa_source *source; uint32_t idx = PA_IDXSET_INVALID; static const char* const state_table[] = { [PA_SOURCE_RUNNING] = "RUNNING", [PA_SOURCE_SUSPENDED] = "SUSPENDED", [PA_SOURCE_IDLE] = "IDLE", [PA_SOURCE_UNLINKED] = "UNLINKED" }; pa_assert(c); s = pa_strbuf_new(); pa_strbuf_printf(s, "%u source(s) available.\n", pa_idxset_size(c->sources)); for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) { char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX]; pa_strbuf_printf( s, " %c index: %u\n" "\tname: <%s>\n" "\tdriver: <%s>\n" "\tflags: %s%s%s%s\n" "\tstate: %s\n" "\tvolume: <%s>\n" "\tmute: <%u>\n" "\tlatency: <%0.0f usec>\n" "\tsample spec: <%s>\n" "\tchannel map: <%s>\n" "\tused by: <%u>\n" "\tlinked by: <%u>\n", c->default_source_name && !strcmp(source->name, c->default_source_name) ? '*' : ' ', source->index, source->name, source->driver, source->flags & PA_SOURCE_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "", source->flags & PA_SOURCE_LATENCY ? "LATENCY " : "", source->flags & PA_SOURCE_HARDWARE ? "HARDWARE " : "", source->flags & PA_SOURCE_NETWORK ? "NETWORK " : "", state_table[pa_source_get_state(source)], pa_cvolume_snprint(cv, sizeof(cv), pa_source_get_volume(source)), !!pa_source_get_mute(source), (double) pa_source_get_latency(source), pa_sample_spec_snprint(ss, sizeof(ss), &source->sample_spec), pa_channel_map_snprint(cm, sizeof(cm), &source->channel_map), pa_source_used_by(source), pa_source_linked_by(source)); if (source->monitor_of) pa_strbuf_printf(s, "\tmonitor_of: <%u>\n", source->monitor_of->index); if (source->module) pa_strbuf_printf(s, "\tmodule: <%u>\n", source->module->index); if (source->description) pa_strbuf_printf(s, "\tdescription: <%s>\n", source->description); } return pa_strbuf_tostring_free(s); }
static void devices_add(struct pa_classify_device **p_devices, const char *type, const char *prop, enum pa_classify_method method, const char *arg, pa_hashmap *ports, uint32_t flags) { struct pa_classify_device *devs; struct pa_classify_device_def *d; size_t newsize; const char *method_name; char *ports_string = NULL; /* Just for log output. */ pa_strbuf *buf; /* For building ports_string. */ pa_assert(p_devices); pa_assert_se((devs = *p_devices)); newsize = sizeof(*devs) + sizeof(devs->defs[0]) * (devs->ndef + 1); devs = *p_devices = pa_xrealloc(devs, newsize); d = devs->defs + devs->ndef; memset(d+1, 0, sizeof(devs->defs[0])); d->type = pa_xstrdup(type); d->prop = pa_xstrdup(prop); buf = pa_strbuf_new(); if (ports && !pa_hashmap_isempty(ports)) { struct pa_classify_port_entry *port; void *state; pa_bool_t first = TRUE; /* Copy the ports hashmap to d->data.ports. */ d->data.ports = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); PA_HASHMAP_FOREACH(port, ports, state) { struct pa_classify_port_entry *port_copy = pa_xnew(struct pa_classify_port_entry, 1); port_copy->device_name = pa_xstrdup(port->device_name); port_copy->port_name = pa_xstrdup(port->port_name); pa_hashmap_put(d->data.ports, port_copy->device_name, port_copy); if (!first) { pa_strbuf_putc(buf, ','); } first = FALSE; pa_strbuf_printf(buf, "%s:%s", port->device_name, port->port_name); } } d->data.flags = flags; switch (method) { case pa_method_equals: method_name = "equals"; d->method = pa_classify_method_equals; d->arg.string = pa_xstrdup(arg); break; case pa_method_startswith: method_name = "startswidth"; d->method = pa_classify_method_startswith; d->arg.string = pa_xstrdup(arg); break; case pa_method_matches: method_name = "matches"; if (regcomp(&d->arg.rexp, arg, 0) == 0) { d->method = pa_classify_method_matches; break; } /* intentional fall trough */ default: pa_log("%s: invalid device definition %s", __FUNCTION__, type); memset(d, 0, sizeof(*d)); pa_strbuf_free(buf); return; } devs->ndef++; ports_string = pa_strbuf_tostring_free(buf); pa_log_info("device '%s' added (%s|%s|%s|%s|0x%04x)", type, d->prop, method_name, arg, ports_string, d->data.flags); pa_xfree(ports_string); }
int main(int argc, char *argv[]) { pa_core *c = NULL; pa_strbuf *buf = NULL; pa_daemon_conf *conf = NULL; pa_mainloop *mainloop = NULL; char *s; int r = 0, retval = 1, d = 0; pa_bool_t valid_pid_file = FALSE; pa_bool_t ltdl_init = FALSE; int passed_fd = -1; const char *e; #ifdef HAVE_FORK int daemon_pipe[2] = { -1, -1 }; #endif #ifdef OS_IS_WIN32 pa_time_event *win32_timer; struct timeval win32_tv; #endif int autospawn_fd = -1; pa_bool_t autospawn_locked = FALSE; #ifdef HAVE_DBUS pa_dbus_connection *dbus = NULL; #endif pa_log_set_ident("pulseaudio"); pa_log_set_level(PA_LOG_NOTICE); pa_log_set_flags(PA_LOG_COLORS|PA_LOG_PRINT_FILE|PA_LOG_PRINT_LEVEL, PA_LOG_RESET); #if defined(__linux__) && defined(__OPTIMIZE__) /* Disable lazy relocations to make usage of external libraries more deterministic for our RT threads. We abuse __OPTIMIZE__ as a check whether we are a debug build or not. This all is admittedly a bit snake-oilish. */ if (!getenv("LD_BIND_NOW")) { char *rp; char *canonical_rp; /* We have to execute ourselves, because the libc caches the * value of $LD_BIND_NOW on initialization. */ pa_set_env("LD_BIND_NOW", "1"); if ((canonical_rp = pa_realpath(PA_BINARY))) { if ((rp = pa_readlink("/proc/self/exe"))) { if (pa_streq(rp, canonical_rp)) pa_assert_se(execv(rp, argv) == 0); else pa_log_warn("/proc/self/exe does not point to %s, cannot self execute. Are you playing games?", canonical_rp); pa_xfree(rp); } else pa_log_warn("Couldn't read /proc/self/exe, cannot self execute. Running in a chroot()?"); pa_xfree(canonical_rp); } else pa_log_warn("Couldn't canonicalize binary path, cannot self execute."); } #endif if ((e = getenv("PULSE_PASSED_FD"))) { passed_fd = atoi(e); if (passed_fd <= 2) passed_fd = -1; } /* We might be autospawned, in which case have no idea in which * context we have been started. Let's cleanup our execution * context as good as possible */ pa_reset_personality(); pa_drop_root(); pa_close_all(passed_fd, -1); pa_reset_sigs(-1); pa_unblock_sigs(-1); pa_reset_priority(); setlocale(LC_ALL, ""); pa_init_i18n(); conf = pa_daemon_conf_new(); if (pa_daemon_conf_load(conf, NULL) < 0) goto finish; if (pa_daemon_conf_env(conf) < 0) goto finish; if (pa_cmdline_parse(conf, argc, argv, &d) < 0) { pa_log(_("Failed to parse command line.")); goto finish; } pa_log_set_level(conf->log_level); pa_log_set_target(conf->auto_log_target ? PA_LOG_STDERR : conf->log_target); if (conf->log_meta) pa_log_set_flags(PA_LOG_PRINT_META, PA_LOG_SET); if (conf->log_time) pa_log_set_flags(PA_LOG_PRINT_TIME, PA_LOG_SET); pa_log_set_show_backtrace(conf->log_backtrace); LTDL_SET_PRELOADED_SYMBOLS(); pa_ltdl_init(); ltdl_init = TRUE; if (conf->dl_search_path) lt_dlsetsearchpath(conf->dl_search_path); #ifdef OS_IS_WIN32 { WSADATA data; WSAStartup(MAKEWORD(2, 0), &data); } #endif pa_random_seed(); switch (conf->cmd) { case PA_CMD_DUMP_MODULES: pa_dump_modules(conf, argc-d, argv+d); retval = 0; goto finish; case PA_CMD_DUMP_CONF: { if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } s = pa_daemon_conf_dump(conf); fputs(s, stdout); pa_xfree(s); retval = 0; goto finish; } case PA_CMD_DUMP_RESAMPLE_METHODS: { int i; if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } for (i = 0; i < PA_RESAMPLER_MAX; i++) if (pa_resample_method_supported(i)) printf("%s\n", pa_resample_method_to_string(i)); retval = 0; goto finish; } case PA_CMD_HELP : pa_cmdline_help(argv[0]); retval = 0; goto finish; case PA_CMD_VERSION : if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } printf(PACKAGE_NAME" "PACKAGE_VERSION"\n"); retval = 0; goto finish; case PA_CMD_CHECK: { pid_t pid; if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } if (pa_pid_file_check_running(&pid, "pulseaudio") < 0) pa_log_info(_("Daemon not running")); else { pa_log_info(_("Daemon running as PID %u"), pid); retval = 0; } goto finish; } case PA_CMD_KILL: if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } if (pa_pid_file_kill(SIGINT, NULL, "pulseaudio") < 0) pa_log(_("Failed to kill daemon: %s"), pa_cstrerror(errno)); else retval = 0; goto finish; case PA_CMD_CLEANUP_SHM: if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } if (pa_shm_cleanup() >= 0) retval = 0; goto finish; default: pa_assert(conf->cmd == PA_CMD_DAEMON || conf->cmd == PA_CMD_START); } if (d < argc) { pa_log("Too many arguments.\n"); goto finish; } if (getuid() == 0 && !conf->system_instance) pa_log_warn(_("This program is not intended to be run as root (unless --system is specified).")); else if (getuid() != 0 && conf->system_instance) { pa_log(_("Root privileges required.")); goto finish; } if (conf->cmd == PA_CMD_START && conf->system_instance) { pa_log(_("--start not supported for system instances.")); goto finish; } if (conf->system_instance && !conf->disallow_exit) pa_log_warn(_("Running in system mode, but --disallow-exit not set!")); if (conf->system_instance && !conf->disallow_module_loading) pa_log_warn(_("Running in system mode, but --disallow-module-loading not set!")); if (conf->system_instance && !conf->disable_shm) { pa_log_notice(_("Running in system mode, forcibly disabling SHM mode!")); conf->disable_shm = TRUE; } if (conf->system_instance && conf->exit_idle_time >= 0) { pa_log_notice(_("Running in system mode, forcibly disabling exit idle time!")); conf->exit_idle_time = -1; } if (conf->cmd == PA_CMD_START) { /* If we shall start PA only when it is not running yet, we * first take the autospawn lock to make things * synchronous. */ if ((autospawn_fd = pa_autospawn_lock_init()) < 0) { pa_log("Failed to initialize autospawn lock"); goto finish; } if ((pa_autospawn_lock_acquire(TRUE) < 0)) { pa_log("Failed to acquire autospawn lock"); goto finish; } autospawn_locked = TRUE; } if (conf->daemonize) { pid_t child; int tty_fd; if (pa_stdio_acquire() < 0) { pa_log(_("Failed to acquire stdio.")); goto finish; } #ifdef HAVE_FORK if (pipe(daemon_pipe) < 0) { pa_log(_("pipe failed: %s"), pa_cstrerror(errno)); goto finish; } if ((child = fork()) < 0) { pa_log(_("fork() failed: %s"), pa_cstrerror(errno)); goto finish; } if (child != 0) { ssize_t n; /* Father */ pa_assert_se(pa_close(daemon_pipe[1]) == 0); daemon_pipe[1] = -1; if ((n = pa_loop_read(daemon_pipe[0], &retval, sizeof(retval), NULL)) != sizeof(retval)) { if (n < 0) pa_log(_("read() failed: %s"), pa_cstrerror(errno)); retval = 1; } if (retval) pa_log(_("Daemon startup failed.")); else pa_log_info(_("Daemon startup successful.")); goto finish; } if (autospawn_fd >= 0) { /* The lock file is unlocked from the parent, so we need * to close it in the child */ pa_autospawn_lock_release(); pa_autospawn_lock_done(TRUE); autospawn_locked = FALSE; autospawn_fd = -1; } pa_assert_se(pa_close(daemon_pipe[0]) == 0); daemon_pipe[0] = -1; #endif if (conf->auto_log_target) pa_log_set_target(PA_LOG_SYSLOG); #ifdef HAVE_SETSID setsid(); #endif #ifdef HAVE_SETPGID setpgid(0,0); #endif #ifndef OS_IS_WIN32 pa_close(0); pa_close(1); pa_close(2); pa_assert_se(open("/dev/null", O_RDONLY) == 0); pa_assert_se(open("/dev/null", O_WRONLY) == 1); pa_assert_se(open("/dev/null", O_WRONLY) == 2); #else FreeConsole(); #endif #ifdef SIGTTOU signal(SIGTTOU, SIG_IGN); #endif #ifdef SIGTTIN signal(SIGTTIN, SIG_IGN); #endif #ifdef SIGTSTP signal(SIGTSTP, SIG_IGN); #endif #ifdef TIOCNOTTY if ((tty_fd = open("/dev/tty", O_RDWR)) >= 0) { ioctl(tty_fd, TIOCNOTTY, (char*) 0); pa_assert_se(pa_close(tty_fd) == 0); } #endif } pa_set_env_and_record("PULSE_INTERNAL", "1"); pa_assert_se(chdir("/") == 0); umask(0022); #ifdef HAVE_SYS_RESOURCE_H set_all_rlimits(conf); #endif pa_rtclock_hrtimer_enable(); pa_raise_priority(conf->nice_level); if (conf->system_instance) if (change_user() < 0) goto finish; pa_set_env_and_record("PULSE_SYSTEM", conf->system_instance ? "1" : "0"); pa_log_info(_("This is PulseAudio %s"), PACKAGE_VERSION); pa_log_debug(_("Compilation host: %s"), CANONICAL_HOST); pa_log_debug(_("Compilation CFLAGS: %s"), PA_CFLAGS); s = pa_uname_string(); pa_log_debug(_("Running on host: %s"), s); pa_xfree(s); pa_log_debug(_("Found %u CPUs."), pa_ncpus()); pa_log_info(_("Page size is %lu bytes"), (unsigned long) PA_PAGE_SIZE); #ifdef HAVE_VALGRIND_MEMCHECK_H pa_log_debug(_("Compiled with Valgrind support: yes")); #else pa_log_debug(_("Compiled with Valgrind support: no")); #endif pa_log_debug(_("Running in valgrind mode: %s"), pa_yes_no(pa_in_valgrind())); pa_log_debug(_("Running in VM: %s"), pa_yes_no(pa_running_in_vm())); #ifdef __OPTIMIZE__ pa_log_debug(_("Optimized build: yes")); #else pa_log_debug(_("Optimized build: no")); #endif #ifdef NDEBUG pa_log_debug(_("NDEBUG defined, all asserts disabled.")); #elif defined(FASTPATH) pa_log_debug(_("FASTPATH defined, only fast path asserts disabled.")); #else pa_log_debug(_("All asserts enabled.")); #endif if (!(s = pa_machine_id())) { pa_log(_("Failed to get machine ID")); goto finish; } pa_log_info(_("Machine ID is %s."), s); pa_xfree(s); if ((s = pa_session_id())) { pa_log_info(_("Session ID is %s."), s); pa_xfree(s); } if (!(s = pa_get_runtime_dir())) goto finish; pa_log_info(_("Using runtime directory %s."), s); pa_xfree(s); if (!(s = pa_get_state_dir())) goto finish; pa_log_info(_("Using state directory %s."), s); pa_xfree(s); pa_log_info(_("Using modules directory %s."), conf->dl_search_path); pa_log_info(_("Running in system mode: %s"), pa_yes_no(pa_in_system_mode())); if (pa_in_system_mode()) pa_log_warn(_("OK, so you are running PA in system mode. Please note that you most likely shouldn't be doing that.\n" "If you do it nonetheless then it's your own fault if things don't work as expected.\n" "Please read http://pulseaudio.org/wiki/WhatIsWrongWithSystemMode for an explanation why system mode is usually a bad idea.")); if (conf->use_pid_file) { int z; if ((z = pa_pid_file_create("pulseaudio")) != 0) { if (conf->cmd == PA_CMD_START && z > 0) { /* If we are already running and with are run in * --start mode, then let's return this as success. */ retval = 0; goto finish; } pa_log(_("pa_pid_file_create() failed.")); goto finish; } valid_pid_file = TRUE; } pa_disable_sigpipe(); if (pa_rtclock_hrtimer()) pa_log_info(_("Fresh high-resolution timers available! Bon appetit!")); else pa_log_info(_("Dude, your kernel stinks! The chef's recommendation today is Linux with high-resolution timers enabled!")); if (conf->lock_memory) { #ifdef HAVE_SYS_MMAN_H if (mlockall(MCL_FUTURE) < 0) pa_log_warn("mlockall() failed: %s", pa_cstrerror(errno)); else pa_log_info("Sucessfully locked process into memory."); #else pa_log_warn("Memory locking requested but not supported on platform."); #endif } pa_memtrap_install(); if (!getenv("PULSE_NO_SIMD")) { pa_cpu_init_x86(); pa_cpu_init_arm(); } pa_assert_se(mainloop = pa_mainloop_new()); if (!(c = pa_core_new(pa_mainloop_get_api(mainloop), !conf->disable_shm, conf->shm_size))) { pa_log(_("pa_core_new() failed.")); goto finish; } c->default_sample_spec = conf->default_sample_spec; c->default_channel_map = conf->default_channel_map; c->default_n_fragments = conf->default_n_fragments; c->default_fragment_size_msec = conf->default_fragment_size_msec; c->exit_idle_time = conf->exit_idle_time; c->scache_idle_time = conf->scache_idle_time; c->resample_method = conf->resample_method; c->realtime_priority = conf->realtime_priority; c->realtime_scheduling = !!conf->realtime_scheduling; c->disable_remixing = !!conf->disable_remixing; c->disable_lfe_remixing = !!conf->disable_lfe_remixing; c->running_as_daemon = !!conf->daemonize; c->disallow_exit = conf->disallow_exit; c->flat_volumes = conf->flat_volumes; pa_assert_se(pa_signal_init(pa_mainloop_get_api(mainloop)) == 0); pa_signal_new(SIGINT, signal_callback, c); pa_signal_new(SIGTERM, signal_callback, c); #ifdef SIGUSR1 pa_signal_new(SIGUSR1, signal_callback, c); #endif #ifdef SIGUSR2 pa_signal_new(SIGUSR2, signal_callback, c); #endif #ifdef SIGHUP pa_signal_new(SIGHUP, signal_callback, c); #endif #ifdef OS_IS_WIN32 win32_timer = pa_mainloop_get_api(mainloop)->rtclock_time_new(pa_mainloop_get_api(mainloop), pa_gettimeofday(&win32_tv), message_cb, NULL); #endif if (!conf->no_cpu_limit) pa_assert_se(pa_cpu_limit_init(pa_mainloop_get_api(mainloop)) == 0); buf = pa_strbuf_new(); if (conf->load_default_script_file) { FILE *f; if ((f = pa_daemon_conf_open_default_script_file(conf))) { r = pa_cli_command_execute_file_stream(c, f, buf, &conf->fail); fclose(f); } } if (r >= 0) r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail); pa_log_error("%s", s = pa_strbuf_tostring_free(buf)); pa_xfree(s); /* We completed the initial module loading, so let's disable it * from now on, if requested */ c->disallow_module_loading = !!conf->disallow_module_loading; if (r < 0 && conf->fail) { pa_log(_("Failed to initialize daemon.")); goto finish; } if (!c->modules || pa_idxset_size(c->modules) == 0) { pa_log(_("Daemon startup without any loaded modules, refusing to work.")); goto finish; } #ifdef HAVE_FORK if (daemon_pipe[1] >= 0) { int ok = 0; pa_loop_write(daemon_pipe[1], &ok, sizeof(ok), NULL); pa_close(daemon_pipe[1]); daemon_pipe[1] = -1; } #endif #ifdef HAVE_DBUS dbus = register_dbus(c); #endif pa_log_info(_("Daemon startup complete.")); retval = 0; if (pa_mainloop_run(mainloop, &retval) < 0) goto finish; pa_log_info(_("Daemon shutdown initiated.")); finish: #ifdef HAVE_DBUS if (dbus) pa_dbus_connection_unref(dbus); #endif if (autospawn_fd >= 0) { if (autospawn_locked) pa_autospawn_lock_release(); pa_autospawn_lock_done(FALSE); } #ifdef OS_IS_WIN32 if (win32_timer) pa_mainloop_get_api(mainloop)->time_free(win32_timer); #endif if (c) { pa_core_unref(c); pa_log_info(_("Daemon terminated.")); } if (!conf->no_cpu_limit) pa_cpu_limit_done(); pa_signal_done(); #ifdef HAVE_FORK if (daemon_pipe[1] >= 0) pa_loop_write(daemon_pipe[1], &retval, sizeof(retval), NULL); pa_close_pipe(daemon_pipe); #endif if (mainloop) pa_mainloop_free(mainloop); if (conf) pa_daemon_conf_free(conf); if (valid_pid_file) pa_pid_file_remove(); /* This has no real purpose except making things valgrind-clean */ pa_unset_env_recorded(); #ifdef OS_IS_WIN32 WSACleanup(); #endif if (ltdl_init) pa_ltdl_done(); #ifdef HAVE_DBUS dbus_shutdown(); #endif return retval; }