static char *list_string(struct string_conversion *list, uint32_t flags) { char *str = NULL; char *tmp; #if AUDIO_API_VERSION_MAJ >= 2 if (flags & AUDIO_DEVICE_BIT_IN) flags &= ~AUDIO_DEVICE_BIT_IN; #endif for (unsigned int i = 0; list[i].str; i++) { #if AUDIO_API_VERSION_MAJ >= 2 if (list[i].value & AUDIO_DEVICE_BIT_IN) { if (popcount(list[i].value & ~AUDIO_DEVICE_BIT_IN) != 1) continue; } else #endif if (popcount(list[i].value) != 1) continue; if (flags & list[i].value) { if (str) { tmp = pa_sprintf_malloc("%s|%s", str, list[i].str); pa_xfree(str); str = tmp; } else { str = pa_sprintf_malloc("%s", list[i].str); } } } return str; }
static pa_strlist *prepend_per_user(pa_strlist *l) { char *ufn; #ifdef ENABLE_LEGACY_RUNTIME_DIR char *legacy_dir; /* The very old per-user instance path (< 0.9.11). This is supported only to ease upgrades */ if ((legacy_dir = get_very_old_legacy_runtime_dir())) { char *p = pa_sprintf_malloc("%s" PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET, legacy_dir); l = pa_strlist_prepend(l, p); pa_xfree(p); pa_xfree(legacy_dir); } /* The old per-user instance path (< 0.9.12). This is supported only to ease upgrades */ if ((legacy_dir = get_old_legacy_runtime_dir())) { char *p = pa_sprintf_malloc("%s" PA_PATH_SEP PA_NATIVE_DEFAULT_UNIX_SOCKET, legacy_dir); l = pa_strlist_prepend(l, p); pa_xfree(p); pa_xfree(legacy_dir); } #endif /* The per-user instance */ if ((ufn = pa_runtime_path(PA_NATIVE_DEFAULT_UNIX_SOCKET))) { l = pa_strlist_prepend(l, ufn); pa_xfree(ufn); } return l; }
static void card_changed(struct userdata *u, struct udev_device *dev) { struct device *d; const char *path; const char *t; char *n; 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); d->args = pa_sprintf_malloc("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=1 " "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_xfree(n); pa_hashmap_put(u->devices, d->path, d); verify_access(u, d); }
char *pa_sample_spec_to_mime_type(const pa_sample_spec *ss, const pa_channel_map *cm) { pa_assert(pa_channel_map_compatible(cm, ss)); pa_assert(pa_sample_spec_valid(ss)); if (!pa_sample_spec_is_mime(ss, cm)) return NULL; switch (ss->format) { case PA_SAMPLE_S16BE: case PA_SAMPLE_S24BE: case PA_SAMPLE_U8: /* Stupid UPnP implementations (PS3...) choke on spaces in * the mime type, that's why we write only ';' here, * instead of '; '. */ return pa_sprintf_malloc("audio/%s;rate=%u;channels=%u", ss->format == PA_SAMPLE_S16BE ? "L16" : (ss->format == PA_SAMPLE_S24BE ? "L24" : "L8"), ss->rate, ss->channels); case PA_SAMPLE_ULAW: return pa_xstrdup("audio/basic"); default: pa_assert_not_reached(); } }
static struct service *get_service(struct userdata *u, pa_object *device) { struct service *s; char *hn, *un; const char *n; pa_assert(u); pa_object_assert_ref(device); if ((s = pa_hashmap_get(u->services, device))) return s; s = pa_xnew0(struct service, 1); s->userdata = u; s->device = device; if (pa_sink_isinstance(device)) { if (!(n = pa_proplist_gets(PA_SINK(device)->proplist, PA_PROP_DEVICE_DESCRIPTION))) n = PA_SINK(device)->name; } else { if (!(n = pa_proplist_gets(PA_SOURCE(device)->proplist, PA_PROP_DEVICE_DESCRIPTION))) n = PA_SOURCE(device)->name; } hn = pa_get_host_name_malloc(); un = pa_get_user_name_malloc(); s->service_name = pa_truncate_utf8(pa_sprintf_malloc("%s@%s: %s", un, hn, n), kDNSServiceMaxDomainName-1); pa_xfree(un); pa_xfree(hn); pa_hashmap_put(u->services, s->device, s); return s; }
pa_auth_cookie* pa_auth_cookie_get(pa_core *core, const char *cn, bool create, size_t size) { pa_auth_cookie *c; char *t; pa_assert(core); pa_assert(size > 0); t = pa_sprintf_malloc("auth-cookie%s%s", cn ? "@" : "", cn ? cn : ""); if ((c = pa_shared_get(core, t))) { pa_xfree(t); if (c->size != size) return NULL; return pa_auth_cookie_ref(c); } c = pa_xmalloc(PA_ALIGN(sizeof(pa_auth_cookie)) + size); PA_REFCNT_INIT(c); c->core = core; c->name = t; c->size = size; pa_assert_se(pa_shared_set(core, t, c) >= 0); if (pa_authkey_load(cn, create, (uint8_t*) c + PA_ALIGN(sizeof(pa_auth_cookie)), size) < 0) { pa_auth_cookie_unref(c); return NULL; } return c; }
static pa_hook_result_t source_new_hook_callback(pa_core *c, pa_source_new_data *new_data, struct userdata *u) { char *name; struct entry *e; pa_assert(c); pa_assert(new_data); pa_assert(u); pa_assert(u->restore_port); name = pa_sprintf_malloc("source:%s", new_data->name); if ((e = read_entry(u, name))) { if (e->port_valid) { if (!new_data->active_port) { pa_log_info("Restoring port for source %s.", name); pa_source_new_data_set_port(new_data, e->port); new_data->save_port = TRUE; } else pa_log_debug("Not restoring port for source %s, because already set.", name); } pa_xfree(e); } pa_xfree(name); return PA_HOOK_OK; }
/* When a source is created, loopback it to default sink */ static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source, void* userdata) { const char *s; const char *role; char *args; pa_assert(c); pa_assert(source); /* Only consider bluetooth sinks and sources */ s = pa_proplist_gets(source->proplist, PA_PROP_DEVICE_BUS); if (!s) return PA_HOOK_OK; if (!pa_streq(s, "bluetooth")) return PA_HOOK_OK; /* Restrict to A2DP profile (sink role) */ s = pa_proplist_gets(source->proplist, "bluetooth.protocol"); if (!s) return PA_HOOK_OK; if (pa_streq(s, "a2dp_source")) role = "music"; else { pa_log_debug("Profile %s cannot be selected for loopback", s); return PA_HOOK_OK; } /* Load module-loopback */ args = pa_sprintf_malloc("source=\"%s\" source_dont_move=\"true\" sink_input_properties=\"media.role=%s\"", source->name, role); (void) pa_module_load(c, "module-loopback", args); pa_xfree(args); return PA_HOOK_OK; }
pa_database* pa_database_open(const char *fn, bool for_write) { GDBM_FILE f; int gdbm_cache_size; char *path; pa_assert(fn); /* We include the host identifier in the file name because gdbm * files are CPU dependent, and we don't want things to go wrong * if we are on a multiarch system. */ path = pa_sprintf_malloc("%s."CANONICAL_HOST".gdbm", fn); errno = 0; /* We need to set the block size explicitly here, since otherwise * gdbm takes the native block size of the underlying file system * which might be incredibly large. */ f = gdbm_open((char*) path, 1024, GDBM_NOLOCK | (for_write ? GDBM_WRCREAT : GDBM_READER), 0644, NULL); if (f) pa_log_debug("Opened GDBM database '%s'", path); pa_xfree(path); if (!f) { if (errno == 0) errno = EIO; return NULL; } /* By default the cache of gdbm is rather large, let's reduce it a bit to save memory */ gdbm_cache_size = 10; gdbm_setopt(f, GDBM_CACHESIZE, &gdbm_cache_size, sizeof(gdbm_cache_size)); return (pa_database*) f; }
/* Called from main thread */ static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) { struct userdata *u; char *output_description; const char *n; if (!dest) return; pa_sink_input_assert_ref(i); pa_assert_ctl_context(); pa_assert_se(u = i->userdata); output_description = pa_sprintf_malloc("Loopback to %s", pa_strnull(pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION))); pa_source_output_set_property(u->source_output, PA_PROP_MEDIA_NAME, output_description); pa_xfree(output_description); if ((n = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_ICON_NAME))) pa_source_output_set_property(u->source_output, PA_PROP_MEDIA_ICON_NAME, n); if (pa_sink_get_state(dest) == PA_SINK_SUSPENDED) pa_source_output_cork(u->source_output, true); else pa_source_output_cork(u->source_output, false); update_adjust_timer(u); }
static void thread_func(void *data) { char *s = data; int n = 0; int b = 1; while (!quit) { char *text; /* Allocate some memory, if possible take it from the flist */ if (b && (text = pa_flist_pop(flist))) pa_log("%s: popped '%s'", s, text); else { text = pa_sprintf_malloc("Block %i, allocated by %s", n++, s); pa_log("%s: allocated '%s'", s, text); } b = !b; spin(); /* Give it back to the flist if possible */ if (pa_flist_push(flist, text) < 0) { pa_log("%s: failed to push back '%s'", s, text); pa_xfree(text); } else pa_log("%s: pushed", s); spin(); } if (pa_flist_push(flist, s) < 0) pa_xfree(s); }
static char* client_name(pa_client *c) { char *t, *e; if (!c->name || !c->driver) return NULL; t = pa_sprintf_malloc("%s$%s", c->driver, c->name); t[strcspn(t, "\n\r#")] = 0; if (!*t) { pa_xfree(t); return NULL; } if ((e = strrchr(t, '('))) { char *k = e + 1 + strspn(e + 1, "0123456789-"); /* Dirty trick: truncate all trailing parens with numbers in * between, since they are usually used to identify multiple * sessions of the same application, which is something we * explicitly don't want. Besides other stuff this makes xmms * with esound work properly for us. */ if (*k == ')' && *(k+1) == 0) *e = 0; } return t; }
pa_void_func_t pa_load_sym(lt_dlhandle handle, const char *module, const char *symbol) { char *sn, *c; pa_void_func_t f; pa_assert(handle); pa_assert(module); pa_assert(symbol); if ((f = ((pa_void_func_t) (long) lt_dlsym(handle, symbol)))) return f; /* As the .la files might have been cleansed from the system, we should * try with the ltdl prefix as well. */ sn = pa_sprintf_malloc("%s_LTX_%s", module, symbol); for (c = sn; *c; c++) if (!isalnum(*c)) *c = '_'; f = (pa_void_func_t) (long) lt_dlsym(handle, sn); pa_xfree(sn); return f; }
int pa_rtsp_record(pa_rtsp_client *c, uint16_t *seq, uint32_t *rtptime) { pa_headerlist *headers; char *info; int rv; pa_assert(c); if (!c->session) { /* No session in progress */ return -1; } pa_random(seq, sizeof(*seq)); pa_random(rtptime, sizeof(*rtptime)); headers = pa_headerlist_new(); pa_headerlist_puts(headers, "Range", "npt=0-"); info = pa_sprintf_malloc("seq=%u;rtptime=%u", *seq, *rtptime); pa_headerlist_puts(headers, "RTP-Info", info); pa_xfree(info); c->state = STATE_RECORD; rv = rtsp_exec(c, "RECORD", NULL, NULL, 1, headers); pa_headerlist_free(headers); return rv; }
static void load_null_sink_if_needed(pa_core *c, pa_sink *sink, struct userdata* u) { pa_sink *target; uint32_t idx; char *t; pa_module *m; pa_assert(c); pa_assert(u); pa_assert(u->null_module == PA_INVALID_INDEX); /* Loop through all sinks and check to see if we have *any* * sinks. Ignore the sink passed in (if it's not null) */ for (target = pa_idxset_first(c->sinks, &idx); target; target = pa_idxset_next(c->sinks, &idx)) if (!sink || target != sink) break; if (target) return; pa_log_debug("Autoloading null-sink as no other sinks detected."); u->ignore = TRUE; t = pa_sprintf_malloc("sink_name=%s sink_properties='device.description=\"%s\"'", u->sink_name, _("Dummy Output")); m = pa_module_load(c, "module-null-sink", t); u->null_module = m ? m->index : PA_INVALID_INDEX; pa_xfree(t); u->ignore = FALSE; if (!m) pa_log_warn("Unable to load module-null-sink"); }
int pa_rtsp_record(pa_rtsp_client* c, uint16_t* seq, uint32_t* rtptime) { pa_headerlist* headers; int rv; char *info; pa_assert(c); if (!c->session) { /* No session in progress */ return -1; } /* Todo: Generate these values randomly as per spec */ *seq = *rtptime = 0; headers = pa_headerlist_new(); pa_headerlist_puts(headers, "Range", "npt=0-"); info = pa_sprintf_malloc("seq=%u;rtptime=%u", *seq, *rtptime); pa_headerlist_puts(headers, "RTP-Info", info); pa_xfree(info); c->state = STATE_RECORD; rv = rtsp_exec(c, "RECORD", NULL, NULL, 1, headers); pa_headerlist_free(headers); return rv; }
static int proc_name_ours(pid_t pid, const char *procname) { #ifdef __linux__ char bn[PATH_MAX]; FILE *f; pa_snprintf(bn, sizeof(bn), "/proc/%lu/stat", (unsigned long) pid); if (!(f = pa_fopen_cloexec(bn, "r"))) { pa_log_info("Failed to open %s: %s", bn, pa_cstrerror(errno)); return -1; } else { char *expected; pa_bool_t good; char stored[64]; if (!(fgets(stored, sizeof(stored), f))) { int saved_errno = feof(f) ? EINVAL : errno; pa_log_info("Failed to read from %s: %s", bn, feof(f) ? "EOF" : pa_cstrerror(errno)); fclose(f); errno = saved_errno; return -1; } fclose(f); expected = pa_sprintf_malloc("%lu (%s)", (unsigned long) pid, procname); good = pa_startswith(stored, expected); pa_xfree(expected); /*#if !defined(__OPTIMIZE__)*/ if (!good) { /* libtool likes to rename our binary names ... */ expected = pa_sprintf_malloc("%lu (lt-%s)", (unsigned long) pid, procname); good = pa_startswith(stored, expected); pa_xfree(expected); } /*#endif*/ return !!good; } #else return 1; #endif }
int pa_parse_address(const char *name, pa_parsed_address *ret_p) { const char *p; pa_assert(name); pa_assert(ret_p); memset(ret_p, 0, sizeof(pa_parsed_address)); ret_p->type = PA_PARSED_ADDRESS_TCP_AUTO; if (*name == '{') { char *id, *pfx; /* The URL starts with a host id for detecting local connections */ if (!(id = pa_machine_id())) return -1; pfx = pa_sprintf_malloc("{%s}", id); pa_xfree(id); if (!pa_startswith(name, pfx)) { pa_xfree(pfx); /* Not local */ return -1; } p = name + strlen(pfx); pa_xfree(pfx); } else p = name; if (*p == '/') ret_p->type = PA_PARSED_ADDRESS_UNIX; else if (pa_startswith(p, "unix:")) { ret_p->type = PA_PARSED_ADDRESS_UNIX; p += sizeof("unix:")-1; } else if (pa_startswith(p, "tcp:")) { ret_p->type = PA_PARSED_ADDRESS_TCP4; p += sizeof("tcp:")-1; } else if (pa_startswith(p, "tcp4:")) { ret_p->type = PA_PARSED_ADDRESS_TCP4; p += sizeof("tcp4:")-1; } else if (pa_startswith(p, "tcp6:")) { ret_p->type = PA_PARSED_ADDRESS_TCP6; p += sizeof("tcp6:")-1; } if (ret_p->type == PA_PARSED_ADDRESS_UNIX) ret_p->path_or_host = pa_xstrdup(p); else if (!(ret_p->path_or_host = parse_host(p, &ret_p->port))) return -1; return 0; }
int pa__init(pa_module*m) { struct userdata *u; pa_modargs *ma = NULL; char *hn, *un; int error; if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments."); goto fail; } m->userdata = u = pa_xnew(struct userdata, 1); u->core = m->core; u->module = m; u->native = pa_native_protocol_get(u->core); u->avahi_poll = pa_avahi_poll_new(m->core->mainloop); u->services = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); u->sink_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_LATE, (pa_hook_cb_t) device_new_or_changed_cb, u); u->sink_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_CHANGED], PA_HOOK_LATE, (pa_hook_cb_t) device_new_or_changed_cb, u); u->sink_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) device_unlink_cb, u); u->source_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_LATE, (pa_hook_cb_t) device_new_or_changed_cb, u); u->source_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED], PA_HOOK_LATE, (pa_hook_cb_t) device_new_or_changed_cb, u); u->source_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) device_unlink_cb, u); u->main_entry_group = NULL; un = pa_get_user_name_malloc(); hn = pa_get_host_name_malloc(); u->service_name = pa_truncate_utf8(pa_sprintf_malloc("%s@%s", un, hn), AVAHI_LABEL_MAX-1); pa_xfree(un); pa_xfree(hn); if (!(u->client = avahi_client_new(u->avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, u, &error))) { pa_log("avahi_client_new() failed: %s", avahi_strerror(error)); goto fail; } pa_modargs_free(ma); return 0; fail: pa__done(m); if (ma) pa_modargs_free(ma); return -1; }
static char * find_desktop_file_in_dir(struct rule *r, const char *desktop_file_dir, struct stat *st) { char *fn = NULL; pa_assert(st); fn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s.desktop", desktop_file_dir, r->process_name); if (stat(fn, st) == 0) return fn; pa_xfree(fn); #ifdef DT_DIR { DIR *desktopfiles_dir; struct dirent *dir; /* Let's try a more aggressive search, but only one level */ if ((desktopfiles_dir = opendir(desktop_file_dir))) { while ((dir = readdir(desktopfiles_dir))) { if (dir->d_type != DT_DIR || pa_streq(dir->d_name, ".") || pa_streq(dir->d_name, "..")) continue; fn = pa_sprintf_malloc("%s" PA_PATH_SEP "%s" PA_PATH_SEP "%s.desktop", desktop_file_dir, dir->d_name, r->process_name); if (stat(fn, st) == 0) { closedir(desktopfiles_dir); return fn; } pa_xfree(fn); } closedir(desktopfiles_dir); } } #endif return NULL; }
static bool control_node_belongs_to_device( struct device *d, const char *node) { char *cd; bool b; cd = pa_sprintf_malloc("controlC%s", path_get_card_id(d->path)); b = pa_streq(node, cd); pa_xfree(cd); return b; }
static bool pcm_node_belongs_to_device( struct device *d, const char *node) { char *cd; bool b; cd = pa_sprintf_malloc("pcmC%sD", path_get_card_id(d->path)); b = pa_startswith(node, cd); pa_xfree(cd); return b; }
void pa_dbus_append_basic_array_variant(DBusMessageIter *iter, int item_type, const void *array, unsigned n) { DBusMessageIter variant_iter; char *array_signature; pa_assert(iter); pa_assert(dbus_type_is_basic(item_type)); pa_assert(array || n == 0); array_signature = pa_sprintf_malloc("a%c", *signature_from_basic_type(item_type)); pa_assert_se(dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, array_signature, &variant_iter)); pa_dbus_append_basic_array(&variant_iter, item_type, array, n); pa_assert_se(dbus_message_iter_close_container(iter, &variant_iter)); pa_xfree(array_signature); }
int pa_rtsp_flush(pa_rtsp_client *c, uint16_t seq, uint32_t rtptime) { pa_headerlist* headers; int rv; char *info; pa_assert(c); headers = pa_headerlist_new(); info = pa_sprintf_malloc("seq=%u;rtptime=%u", seq, rtptime); pa_headerlist_puts(headers, "RTP-Info", info); pa_xfree(info); c->state = STATE_FLUSH; rv = rtsp_exec(c, "FLUSH", NULL, NULL, 1, headers); pa_headerlist_free(headers); return rv; }
static pa_hook_result_t source_fixate_hook_callback(pa_core *c, pa_source_new_data *new_data, struct userdata *u) { char *name; struct entry *e; pa_assert(c); pa_assert(new_data); pa_assert(u); pa_assert(u->restore_volume || u->restore_muted); name = pa_sprintf_malloc("source:%s", new_data->name); if ((e = read_entry(u, name))) { if (u->restore_volume && e->volume_valid) { if (!new_data->volume_is_set) { pa_cvolume v; pa_log_info("Restoring volume for source %s.", new_data->name); v = e->volume; pa_cvolume_remap(&v, &e->channel_map, &new_data->channel_map); pa_source_new_data_set_volume(new_data, &v); new_data->save_volume = TRUE; } else pa_log_debug("Not restoring volume for source %s, because already set.", new_data->name); } if (u->restore_muted && e->muted_valid) { if (!new_data->muted_is_set) { pa_log_info("Restoring mute state for source %s.", new_data->name); pa_source_new_data_set_muted(new_data, e->muted); new_data->save_muted = TRUE; } else pa_log_debug("Not restoring mute state for source %s, because already set.", new_data->name); } pa_xfree(e); } pa_xfree(name); return PA_HOOK_OK; }
static void on_connection(pa_socket_client *sc, pa_iochannel *io, void *userdata) { pa_rtsp_client *c = userdata; union { struct sockaddr sa; struct sockaddr_in in; struct sockaddr_in6 in6; } sa; socklen_t sa_len = sizeof(sa); pa_assert(sc); pa_assert(c); pa_assert(STATE_CONNECT == c->state); pa_assert(c->sc == sc); pa_socket_client_unref(c->sc); c->sc = NULL; if (!io) { pa_log("Connection failed: %s", pa_cstrerror(errno)); return; } pa_assert(!c->ioline); c->ioline = pa_ioline_new(io); pa_ioline_set_callback(c->ioline, line_callback, c); /* Get the local IP address for use externally */ if (0 == getsockname(pa_iochannel_get_recv_fd(io), &sa.sa, &sa_len)) { char buf[INET6_ADDRSTRLEN]; const char *res = NULL; if (AF_INET == sa.sa.sa_family) { if ((res = inet_ntop(sa.sa.sa_family, &sa.in.sin_addr, buf, sizeof(buf)))) { c->localip = pa_xstrdup(res); } } else if (AF_INET6 == sa.sa.sa_family) { if ((res = inet_ntop(AF_INET6, &sa.in6.sin6_addr, buf, sizeof(buf)))) { c->localip = pa_sprintf_malloc("[%s]", res); } } } pa_log_debug("Established RTSP connection from local ip %s", c->localip); if (c->callback) c->callback(c, c->state, NULL, c->userdata); }
pa_daemon_conf *pa_daemon_conf_new(void) { pa_daemon_conf *c; c = pa_xnewdup(pa_daemon_conf, &default_conf, 1); #ifdef OS_IS_WIN32 c->dl_search_path = pa_sprintf_malloc("%s" PA_PATH_SEP "lib" PA_PATH_SEP "pulse-%d.%d" PA_PATH_SEP "modules", pa_win32_get_toplevel(NULL), PA_MAJOR, PA_MINOR); #else if (pa_run_from_build_tree()) { pa_log_notice("Detected that we are run from the build tree, fixing search path."); c->dl_search_path = pa_xstrdup(PA_BUILDDIR); } else c->dl_search_path = pa_xstrdup(PA_DLSEARCHPATH); #endif return c; }
int pa_scache_add_directory_lazy(pa_core *c, const char *pathname) { DIR *dir; pa_core_assert_ref(c); pa_assert(pathname); /* First try to open this as directory */ if (!(dir = opendir(pathname))) { #ifdef HAVE_GLOB_H glob_t p; unsigned int i; /* If that fails, try to open it as shell glob */ if (glob(pathname, GLOB_ERR|GLOB_NOSORT, NULL, &p) < 0) { pa_log("failed to open directory '%s': %s", pathname, pa_cstrerror(errno)); return -1; } for (i = 0; i < p.gl_pathc; i++) add_file(c, p.gl_pathv[i]); globfree(&p); #else return -1; #endif } else { struct dirent *e; while ((e = readdir(dir))) { char *p; if (e->d_name[0] == '.') continue; p = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", pathname, e->d_name); add_file(c, p); pa_xfree(p); } closedir(dir); } return 0; }
int pa__init(pa_module*m) { struct userdata *u; pa_modargs *ma = NULL; char *hn, *un; 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->module = m; u->native = pa_native_protocol_get(u->core); u->services = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); u->sink_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_LATE, (pa_hook_cb_t) device_new_or_changed_cb, u); u->sink_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_CHANGED], PA_HOOK_LATE, (pa_hook_cb_t) device_new_or_changed_cb, u); u->sink_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) device_unlink_cb, u); u->source_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_PUT], PA_HOOK_LATE, (pa_hook_cb_t) device_new_or_changed_cb, u); u->source_changed_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED], PA_HOOK_LATE, (pa_hook_cb_t) device_new_or_changed_cb, u); u->source_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) device_unlink_cb, u); un = pa_get_user_name_malloc(); hn = pa_get_host_name_malloc(); u->service_name = pa_truncate_utf8(pa_sprintf_malloc("%s@%s", un, hn), kDNSServiceMaxDomainName-1); pa_xfree(un); pa_xfree(hn); publish_all_services(u); pa_modargs_free(ma); return 0; fail: pa__done(m); if (ma) pa_modargs_free(ma); return -1; }
static bool pcm_is_modem(const char *card_idx, const char *pcm) { char *sysfs_path, *pcm_class; bool is_modem; pa_assert(card_idx); pa_assert(pcm); /* Check /sys/class/sound/card.../pcmC...../pcm_class. An HDA * modem can be used simultaneously with generic * playback/record. */ sysfs_path = pa_sprintf_malloc("pcmC%sD%s/pcm_class", card_idx, pcm); pcm_class = card_get_sysattr(card_idx, sysfs_path); is_modem = pcm_class && pa_streq(pcm_class, "modem"); pa_xfree(pcm_class); pa_xfree(sysfs_path); return is_modem; }