Re: [pulseaudio-discuss] [PATCH 5/6] alsa: create ucm profiles

2011-04-07 Thread Margarita Olaya
Hi David,

On Wed, Apr 6, 2011 at 1:41 AM, David Henningsson
david.hennings...@canonical.com wrote:
 On 2011-04-05 22:34, Margarita Olaya wrote:

 +static pa_hook_result_t jack_insert_new_hook_callback(pa_core *c,
 struct userdata *u) {
 +    struct pa_alsa_ucm_config *ucm =u-ucm;
 +    struct profile_data *d;
 +    char *device_name;
 +
 +    pa_assert(u);
 +
 +    d = PA_CARD_PROFILE_DATA(u-card-active_profile);
 +
 +    pa_log_debug(Jack insert new hook callback);
 +
 +    device_name = strchr(d-profile-name, ':') + 2;
 +    if (!device_name) {
 +        pa_log(no device found for %s, d-profile-name);
 +        return PA_HOOK_CANCEL;
 +    }
 +
 +    if (strcmp(device_name, Headset.0) == 0)
 +        return PA_HOOK_OK;
 +
 +    /* Set headset.0 device per default */
 +    if (snd_use_case_set(ucm-ucm_mgr, _enadev, Headset.0)  0) {
 +        pa_log(failed to set device Headset.0);
 +        return PA_HOOK_CANCEL;
 +    }
 +
 +    return PA_HOOK_OK;
 +}

 About this function:

 1) pa_hook_cb_t defines three pointers as input, but this one only takes
 two. Is that really working on all platforms?

This is a mistake in this version, It is fixed now.

 2) There is no matching against what card sent the event, is that irrelevant
 for UCM?

The UCM data is store per sound, I'm looking into a way of passing the
card name to the hook and compare it with the one passed in the
userdata.

 3) Is Headset.0 a reserved identifier in UCM, or is this unfinished test
 code? What if there isn't a headset, just a separate external mic, or
 external speakers connected to line out?

It depends on the driver to report here what was inserted or removed.

 +
 +static pa_hook_result_t jack_remove_new_hook_callback(pa_core *c,
 struct userdata *u) {
 +    struct profile_data *d;
 +    struct pa_alsa_ucm_config *ucm =u-ucm;
 +    char *device_name;
 +
 +    pa_assert(u);
 +
 +    d = PA_CARD_PROFILE_DATA(u-card-active_profile);
 +
 +    pa_log_debug(Jack removed new hook callback);
 +
 +    device_name = strchr(d-profile-name, ':') + 2;
 +    if(!device_name) {
 +        pa_log(no device found for %s, d-profile-name);
 +        return PA_HOOK_CANCEL;
 +    }
 +
 +    /* Set current profile device */
 +    if (snd_use_case_set(ucm-ucm_mgr, _enadev, Headset.0)  0) {
 +        pa_log(failed to set device Headset.0);
 +        return PA_HOOK_CANCEL;
 +    }
 +
 +    return PA_HOOK_OK;
 +}

 Ehm, seems like you set it to the Headset device both on plug and unplug...?

hmm, here we will switch to device_name gotten from the current
profile, in case of failure the device will be disabled.

I will post the changes soon.

Regards,
Margarita

 --
 David Henningsson, Canonical Ltd.
 http://launchpad.net/~diwic
 ___
 pulseaudio-discuss mailing list
 pulseaudio-discuss@mail.0pointer.de
 https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss

___
pulseaudio-discuss mailing list
pulseaudio-discuss@mail.0pointer.de
https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH 5/6] alsa: create ucm profiles

2011-04-06 Thread David Henningsson

On 2011-04-05 22:34, Margarita Olaya wrote:

+static pa_hook_result_t jack_insert_new_hook_callback(pa_core *c,
struct userdata *u) {
+struct pa_alsa_ucm_config *ucm =u-ucm;
+struct profile_data *d;
+char *device_name;
+
+pa_assert(u);
+
+d = PA_CARD_PROFILE_DATA(u-card-active_profile);
+
+pa_log_debug(Jack insert new hook callback);
+
+device_name = strchr(d-profile-name, ':') + 2;
+if (!device_name) {
+pa_log(no device found for %s, d-profile-name);
+return PA_HOOK_CANCEL;
+}
+
+if (strcmp(device_name, Headset.0) == 0)
+return PA_HOOK_OK;
+
+/* Set headset.0 device per default */
+if (snd_use_case_set(ucm-ucm_mgr, _enadev, Headset.0)  0) {
+pa_log(failed to set device Headset.0);
+return PA_HOOK_CANCEL;
+}
+
+return PA_HOOK_OK;
+}


About this function:

1) pa_hook_cb_t defines three pointers as input, but this one only takes 
two. Is that really working on all platforms?


2) There is no matching against what card sent the event, is that 
irrelevant for UCM?


3) Is Headset.0 a reserved identifier in UCM, or is this unfinished 
test code? What if there isn't a headset, just a separate external mic, 
or external speakers connected to line out?



+
+static pa_hook_result_t jack_remove_new_hook_callback(pa_core *c,
struct userdata *u) {
+struct profile_data *d;
+struct pa_alsa_ucm_config *ucm =u-ucm;
+char *device_name;
+
+pa_assert(u);
+
+d = PA_CARD_PROFILE_DATA(u-card-active_profile);
+
+pa_log_debug(Jack removed new hook callback);
+
+device_name = strchr(d-profile-name, ':') + 2;
+if(!device_name) {
+pa_log(no device found for %s, d-profile-name);
+return PA_HOOK_CANCEL;
+}
+
+/* Set current profile device */
+if (snd_use_case_set(ucm-ucm_mgr, _enadev, Headset.0)  0) {
+pa_log(failed to set device Headset.0);
+return PA_HOOK_CANCEL;
+}
+
+return PA_HOOK_OK;
+}


Ehm, seems like you set it to the Headset device both on plug and unplug...?

--
David Henningsson, Canonical Ltd.
http://launchpad.net/~diwic
___
pulseaudio-discuss mailing list
pulseaudio-discuss@mail.0pointer.de
https://tango.0pointer.de/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH 5/6] alsa: create ucm profiles

2011-04-05 Thread Margarita Olaya
This patch adds ALSA UCM (Use Case Manager) support to module alsa card.
It checks if UCM is available for each card and if found, scans each UCM
property verb, device and modifier for the card. It then then creates
mappings for each supported UCM verb and device so that changes to the
pulseaudio profile cause corresponding changes to the UCM verb and
device for the card.

This patch also adds hook for jack insertion and removal in order for
the UCM device to be changed upon a jack event.

Signed-off-by: Margarita Olaya Cabrera m...@slimlogic.co.uk
---
 src/modules/alsa/module-alsa-card.c |  657 ++-
 1 files changed, 650 insertions(+), 7 deletions(-)

diff --git a/src/modules/alsa/module-alsa-card.c
b/src/modules/alsa/module-alsa-card.c
index e60aa5e..8794c7c 100644
--- a/src/modules/alsa/module-alsa-card.c
+++ b/src/modules/alsa/module-alsa-card.c
@@ -106,12 +106,207 @@ struct userdata {
 pa_modargs *modargs;

 pa_alsa_profile_set *profile_set;
+
+pa_alsa_ucm_config ucm;
+
+pa_hook_slot
+*jack_insert_new_hook_slot,
+*jack_remove_new_hook_slot;
 };

 struct profile_data {
 pa_alsa_profile *profile;
 };

+struct ucm_items {
+const char *id;
+const char *property;
+};
+
+struct ucm_info {
+const char *id;
+int priority;
+pa_alsa_direction_t direction;
+int channels;
+};
+
+static struct ucm_items item[] = {
+{PlaybackPCM, PA_PROP_UCM_SINK},
+{CapturePCM, PA_PROP_UCM_SOURCE},
+{PlaybackVolume, PA_PROP_UCM_PLAYBACK_VOLUME},
+{PlaybackSwitch, PA_PROP_UCM_PLAYBACK_SWITCH},
+{CaptureVolume, PA_PROP_UCM_CAPTURE_VOLUME},
+{CaptureSwitch, PA_PROP_UCM_CAPTURE_SWITCH},
+{TQ, PA_PROP_UCM_QOS},
+{NULL, NULL},
+};
+
+/* UCM device info - this should eventually be part of policy manangement */
+static struct ucm_info dev_info[] = {
+{SND_USE_CASE_DEV_SPEAKER, 100, PA_ALSA_DIRECTION_OUTPUT, 2},
+{SND_USE_CASE_DEV_LINE, 100, PA_ALSA_DIRECTION_ANY, 2},
+{SND_USE_CASE_DEV_HEADPHONES, 100, PA_ALSA_DIRECTION_OUTPUT, 2},
+{SND_USE_CASE_DEV_HEADSET, 300, PA_ALSA_DIRECTION_ANY, 2},
+{SND_USE_CASE_DEV_HANDSET, 200, PA_ALSA_DIRECTION_ANY, 2},
+{SND_USE_CASE_DEV_BLUETOOTH, 400, PA_ALSA_DIRECTION_ANY, 1},
+{SND_USE_CASE_DEV_EARPIECE, 100, PA_ALSA_DIRECTION_OUTPUT, 1},
+{SND_USE_CASE_DEV_SPDIF, 100, PA_ALSA_DIRECTION_ANY, 2},
+{SND_USE_CASE_DEV_HDMI, 100, PA_ALSA_DIRECTION_ANY, 8},
+{SND_USE_CASE_DEV_NONE, 100, PA_ALSA_DIRECTION_ANY, 2},
+{NULL, 0, PA_ALSA_DIRECTION_ANY, 0},
+};
+
+/* UCM profile properties - The verb data is store so it can be used to fill
+ * the new profiles properties */
+
+static int ucm_get_property(struct pa_alsa_ucm_verb *verb,
snd_use_case_mgr_t *uc_mgr, const char *verb_name) {
+const char *value;
+int i = 0;
+
+do {
+int err;
+
+err = snd_use_case_get(uc_mgr, item[i].id, value);
+if (err  0 ) {
+pa_log_info(No %s for verb %s, item[i].id, verb_name);
+continue;
+}
+
+pa_log_info(Got %s for verb %s, item[i].id, verb_name);
+pa_proplist_sets(verb-proplist, item[i].property, value);
+}  while (item[++i].id);
+
+return 0;
+};
+
+/* Create a property list for this ucm device */
+static int ucm_get_device_property(struct pa_alsa_ucm_device *device,
snd_use_case_mgr_t *uc_mgr, const char *device_name) {
+const char *value;
+char *id;
+int i = 0;
+
+do {
+int err;
+
+id = pa_sprintf_malloc(%s/%s, item[i].id, device_name);
+
+err = snd_use_case_get(uc_mgr, id, value);
+if (err  0 ) {
+pa_log_info(No %s for device %s, id, device_name);
+pa_xfree(id);
+continue;
+}
+
+pa_log_info(Got %s for device %s, id, device_name);
+pa_xfree(id);
+pa_proplist_sets(device-proplist, item[i].property, value);
+}  while (item[++i].id);
+
+return 0;
+};
+
+/* Create a property list for this ucm modifier */
+static int ucm_get_modifier_property(struct pa_alsa_ucm_modifier
*modifier, snd_use_case_mgr_t *uc_mgr, const char *modifier_name) {
+const char *value;
+char *id;
+int i = 0;
+
+do {
+int err;
+
+id = pa_sprintf_malloc(%s/%s, item[i].id, modifier_name);
+
+err = snd_use_case_get(uc_mgr, id, value);
+if (err  0 ) {
+pa_log_info(No %s for modifier %s, id, modifier_name);
+pa_xfree(id);
+continue;
+}
+
+pa_log_info(Got %s for modifier %s, id, modifier_name);
+pa_xfree(id);
+pa_proplist_sets(modifier-proplist, item[i].property, value);
+}  while (item[++i].id);
+
+return 0;
+};
+
+/* Create a list of devices for this verb */
+static int ucm_get_devices(struct pa_alsa_ucm_verb *verb,
snd_use_case_mgr_t *uc_mgr) {
+const char **dev_list;
+int num_dev, i;
+
+num_dev = snd_use_case_get_list(uc_mgr, _devices, dev_list);
+if