Re: [pulseaudio-discuss] [PATCH 5/6] alsa: create ucm profiles
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
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
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