Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 4
0
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();
    }
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
/* 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;
}
Ejemplo n.º 9
0
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;
}
Ejemplo n.º 10
0
/* 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);
}
Ejemplo n.º 11
0
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);
}
Ejemplo n.º 12
0
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;
}
Ejemplo n.º 13
0
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;
}
Ejemplo n.º 14
0
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;
}
Ejemplo n.º 15
0
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");
}
Ejemplo n.º 16
0
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;
}
Ejemplo n.º 17
0
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

}
Ejemplo n.º 18
0
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;
}
Ejemplo n.º 20
0
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;
}
Ejemplo n.º 21
0
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;
}
Ejemplo n.º 22
0
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;
}
Ejemplo n.º 23
0
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);
}
Ejemplo n.º 24
0
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;
}
Ejemplo n.º 25
0
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;
}
Ejemplo n.º 26
0
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);
}
Ejemplo n.º 27
0
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;
}
Ejemplo n.º 28
0
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;
}
Ejemplo n.º 29
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;
}
Ejemplo n.º 30
0
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;
}