Example #1
0
ALCboolean alc_pulse_init(BackendFuncs *func_list)
{
    ALCboolean ret = ALC_FALSE;

    if(pulse_load())
    {
        pa_threaded_mainloop *loop;

        pulse_ctx_flags = 0;
        if(!GetConfigValueBool("pulse", "spawn-server", 0))
            pulse_ctx_flags |= PA_CONTEXT_NOAUTOSPAWN;

        if((loop=pa_threaded_mainloop_new()) &&
           pa_threaded_mainloop_start(loop) >= 0)
        {
            pa_context *context;

            pa_threaded_mainloop_lock(loop);
            context = connect_context(loop, AL_TRUE);
            if(context)
            {
                *func_list = pulse_funcs;
                ret = ALC_TRUE;

                /* Some libraries (Phonon, Qt) set some pulseaudio properties
                 * through environment variables, which causes all streams in
                 * the process to inherit them. This attempts to filter those
                 * properties out by setting them to 0-length data. */
                prop_filter = pa_proplist_new();
                pa_proplist_set(prop_filter, PA_PROP_MEDIA_ROLE, NULL, 0);
                pa_proplist_set(prop_filter, "phonon.streamid", NULL, 0);

                pa_context_disconnect(context);
                pa_context_unref(context);
            }
            pa_threaded_mainloop_unlock(loop);
            pa_threaded_mainloop_stop(loop);
        }
        if(loop)
            pa_threaded_mainloop_free(loop);
    }

    return ret;
}
Example #2
0
pa_proplist *pa_dbus_get_proplist_arg(DBusConnection *c, DBusMessage *msg, DBusMessageIter *iter) {
    DBusMessageIter dict_iter;
    DBusMessageIter dict_entry_iter;
    char *signature;
    pa_proplist *proplist = NULL;
    const char *key = NULL;
    const uint8_t *value = NULL;
    int value_length = 0;

    pa_assert(c);
    pa_assert(msg);
    pa_assert(iter);

    pa_assert(signature = dbus_message_iter_get_signature(iter));
    pa_assert_se(pa_streq(signature, "a{say}"));

    dbus_free(signature);

    proplist = pa_proplist_new();

    dbus_message_iter_recurse(iter, &dict_iter);

    while (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_INVALID) {
        dbus_message_iter_recurse(&dict_iter, &dict_entry_iter);

        dbus_message_iter_get_basic(&dict_entry_iter, &key);
        dbus_message_iter_next(&dict_entry_iter);

        if (strlen(key) <= 0 || !pa_ascii_valid(key)) {
            pa_dbus_send_error(c, msg, DBUS_ERROR_INVALID_ARGS, "Invalid property list key: '%s'.", key);
            goto fail;
        }

        dbus_message_iter_get_fixed_array(&dict_entry_iter, &value, &value_length);

        pa_assert(value_length >= 0);

        pa_assert_se(pa_proplist_set(proplist, key, value, value_length) >= 0);

        dbus_message_iter_next(&dict_iter);
    }

    dbus_message_iter_next(iter);

    return proplist;

fail:
    if (proplist)
        pa_proplist_free(proplist);

    return NULL;
}
static pa_hook_result_t sink_input_neew(void *hook_data, void *call_data,
                                       void *slot_data)
{
    static uint32_t         route_flags = PA_POLICY_GROUP_FLAG_SET_SINK |
                                          PA_POLICY_GROUP_FLAG_ROUTE_AUDIO;
    static pa_volume_t      max_volume  = PA_VOLUME_NORM;


    struct pa_sink_input_new_data
                           *data = (struct pa_sink_input_new_data *)call_data;
    struct userdata        *u    = (struct userdata *)slot_data;
    uint32_t                flags;
    const char             *group_name;
    const char             *sinp_name;
    const char             *sink_name;
    int                     local_route;
    int                     local_volume;
    struct pa_policy_group *group;

    pa_assert(u);
    pa_assert(data);

    if ((group_name = pa_classify_sink_input_by_data(u,data,&flags)) != NULL &&
        (group      = pa_policy_group_find(u, group_name)          ) != NULL ){

        /* Let's just set the policy group property here already so that we
         * don't have to classify again when the sink input is put, because we
         * can just retrieve the group from the proplist. Also, this prevents
         * the classification from breaking later because of the proplist
         * overwriting done below. */
        pa_proplist_sets(data->proplist, PA_PROP_POLICY_GROUP, group_name);

        /* Proplist overwriting can also mess up the retrieval of
         * stream-specific flags later on, so we need to store those to the
         * proplist as well (ugly hack). We could probably cope without this
         * one though, since the stream-specific flags don't really seem to be
         * used. */
        pa_proplist_set(data->proplist, PA_PROP_POLICY_STREAM_FLAGS,
                        (void*)&flags, sizeof(flags));

        if (group->properties != NULL) {
            pa_proplist_update(data->proplist, PA_UPDATE_REPLACE, group->properties);
            pa_log_debug("new sink input inserted into %s. "
                         "force the following properties:", group_name);
        }

        if (group->sink != NULL) {
            sinp_name = pa_proplist_gets(data->proplist, PA_PROP_MEDIA_NAME);

            if (!sinp_name)
                sinp_name = "<unknown>";

            local_route  = flags & PA_POLICY_LOCAL_ROUTE;
            local_volume = flags & PA_POLICY_LOCAL_VOLMAX;

            if (group->mutebyrt && !local_route) {
                sink_name = u->nullsink->name;

                pa_log_debug("force stream '%s'/'%s' to sink '%s' due to "
                             "mute-by-route", group_name,sinp_name, sink_name);

#ifdef HAVE_OLD_LIBPULSE
                data->sink = u->nullsink->sink;
#else
                pa_sink_input_new_data_set_sink(data, u->nullsink->sink, false);
#endif
            }
            else if (group->flags & route_flags) {
                sink_name = pa_sink_ext_get_name(group->sink);

                pa_log_debug("force stream '%s'/'%s' to sink '%s'",
                             group_name, sinp_name, sink_name); 

#ifdef HAVE_OLD_LIBPULSE
                data->sink = group->sink;
#else
                pa_sink_input_new_data_set_sink(data, group->sink, false);
#endif
            }

            if (local_volume) {
                pa_log_debug("force stream '%s'/'%s' volume to %d",
                             group_name, sinp_name,
                             (max_volume * 100) / PA_VOLUME_NORM);
                
                pa_cvolume_set(&data->volume, data->channel_map.channels,
                               max_volume);

                data->volume_is_set      = TRUE;
                data->save_volume        = FALSE;
            }
        }

    }


    return PA_HOOK_OK;
}
Example #4
0
void on_set_common(pa_proplist* p, pa_tagstruct* t, pa_core* c)
{
    pa_log_info("on_set_common");

    const char* attribute = pa_proplist_gets(p, PROPLIST_KEY_ATTRIBUTE);
    if (!attribute) {
        pa_log_error("on_set_common: attribute not found!");
        return;
    }

    if (!strcmp(attribute, PROPLIST_VALUE_GET_INFO)) {
        const char* str_device = pa_proplist_gets(p, PROPLIST_KEY_DEVICE);
        if (!str_device) {
            pa_log_error("on_set_common device not specific!");
            return;
        }

        int device_id = atoi(str_device);
        pa_sink* sink = NULL;
        pa_source* source = NULL;

        sink = find_sink(c, device_id);
        if (!sink) {
            source = find_source(c, device_id);
        }

        if (!sink && !source) {
            pa_log_error("do not find any sink or source of device %d", device_id);
            return;
        }

        int n_used = 0;
        if (sink) {
            n_used = pa_module_get_n_used(sink->module);
        }
        else {
            n_used = pa_module_get_n_used(source->module);
        }

        char value[32];
        snprintf(value, sizeof(value), "%d", n_used);
        pa_proplist* replyp = pa_proplist_new();
        pa_proplist_sets(replyp, PROPLIST_KEY_VALUE, value);
        pa_tagstruct_put_proplist(t, replyp);
        pa_proplist_free(replyp);
    }
    else if (!strcmp(attribute, PROPLIST_VALUE_REMOTE_SINK)) {
#ifdef HAVE_WEB_SOCKET
        extern void start_web_socket();
        start_web_socket();
#endif
        on_set_debug(c, p, EAUDIO_STREAM_DEVICE_VIRTUALOUPUT_REMOTE, NULL);
    }
    else if (!strcmp(attribute, PROPLIST_VALUE_FILE_SINK)) {
        const char* str_path = pa_proplist_gets(p, PROPLIST_VALUE_PATH);
        char args[64] = { 0 };
        if (str_path) {
            snprintf(args, sizeof(args), "path=%s", str_path);
        }
        on_set_debug(c, p, EAUDIO_STREAM_DEVICE_VIRTUALOUPUT_FILE, str_path ? args : NULL);
    }
    else if (!strcmp(attribute, PROPLIST_VALUE_ALSA_BUFFER)) {
        const char* str_device = pa_proplist_gets(p, PROPLIST_KEY_DEVICE);
        if (!str_device) {
            pa_log_error("on_set_common alsa-buffer device not specific!");
            return;
        }

        int device = atoi(str_device);
        pa_sink* s = find_sink(c, device);
        if (!s) {
            pa_log_error("sink not found %d", device);
            return;
        }

        pa_usec_t left_to_play = pa_sink_get_left_to_play(s);
        pa_proplist* replyp = pa_proplist_new();
        pa_proplist_set(replyp, PROPLIST_KEY_COMMAND_RESULT, &left_to_play, sizeof(left_to_play));
        pa_tagstruct_put_proplist(t, replyp);
        pa_proplist_free(replyp);
    }
    else if (!strcmp(attribute, PROPLIST_VALUE_STOP_TEST)) {
        pthread_t tid_stop;
        int err = pthread_create(&tid_stop, NULL, stop_thread, NULL);
        if (err != 0) {
            pa_log_error("can't create thread: %s\n", strerror(err));
            return;
        }
    }
#ifdef HAVE_WEB_SOCKET
        else if (!strcmp(attribute, "web-start")) {
            extern void start_web_socket();
            start_web_socket();
        }
        else if (!strcmp(attribute, "web-stop")) {
            extern void stop_web_socket();
            stop_web_socket();
        }
#endif
}