aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/alsa/alsa-api-pcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/alsa/alsa-api-pcm.c')
-rw-r--r--plugins/alsa/alsa-api-pcm.c62
1 files changed, 53 insertions, 9 deletions
diff --git a/plugins/alsa/alsa-api-pcm.c b/plugins/alsa/alsa-api-pcm.c
index ce74982..464a725 100644
--- a/plugins/alsa/alsa-api-pcm.c
+++ b/plugins/alsa/alsa-api-pcm.c
@@ -384,14 +384,17 @@ PUBLIC void ApiPcmDelParams(SoftMixerT* mixer, AlsaPcmHwInfoT* params) {
}
PUBLIC void ApiPcmParamsShow(SoftMixerT * mixer, const char *msg, const AlsaPcmHwInfoT * params) {
- AFB_ApiInfo(mixer->api, "%s PARAMS: rate=%d, format=%d, formatString=%s",
- msg, params->rate, params->format, params->formatString);
+ AFB_ApiInfo(mixer->api, "%s PARAMS: rate=%d, format=%d, formatString=%s, channels %d",
+ msg, params->rate, params->format, params->formatString, params->channels);
}
PUBLIC AlsaPcmHwInfoT * ApiPcmSetParams(SoftMixerT *mixer, const char *uid, json_object * paramsJ) {
const char *format = NULL, *access = NULL;
+
+ AFB_API_NOTICE(mixer->api, "%s for %s: params are %s", __func__, uid, json_object_get_string(paramsJ));
+
AlsaPcmHwInfoT *params = calloc(1, sizeof (AlsaPcmHwInfoT));
if (params == NULL) {
SOFTMIXER_NOMEM(mixer->api);
@@ -405,10 +408,11 @@ PUBLIC AlsaPcmHwInfoT * ApiPcmSetParams(SoftMixerT *mixer, const char *uid, json
if (paramsJ) {
int error =
- wrap_json_unpack(paramsJ, "{s?i,s?s,s?s !}",
+ wrap_json_unpack(paramsJ, "{s?i,s?s,s?s,s?i !}",
"rate", &params->rate,
"format", &format,
- "access", &access);
+ "access", &access,
+ "channels", &params->channels);
if (error) {
AFB_ApiError(mixer->api, "%s: sndcard=%s invalid params=%s",
__func__, uid, json_object_get_string(paramsJ));
@@ -416,6 +420,9 @@ PUBLIC AlsaPcmHwInfoT * ApiPcmSetParams(SoftMixerT *mixer, const char *uid, json
}
}
+ AFB_API_NOTICE(mixer->api, "%s:%s rate set to %d", __func__, uid, params->rate);
+ AFB_API_NOTICE(mixer->api, "%s:%s channels set to %d", __func__, uid, params->channels);
+
// default format
if (!format) {
params->format = SND_PCM_FORMAT_S16_LE;
@@ -502,7 +509,9 @@ PUBLIC void ApiPcmDelete(SoftMixerT * mixer, AlsaSndPcmT * pcm) {
pcmChannelsDestroy(mixer, pcm);
- snd_ctl_close(card->ctl);
+ if (card->ctl)
+ snd_ctl_close(card->ctl);
+
free(card);
free ((char*)pcm->mute.name);
free ((char*)pcm->volume.name);
@@ -536,7 +545,7 @@ fail:
PUBLIC AlsaSndPcmT * ApiPcmAttachOne(SoftMixerT *mixer, const char *uid, snd_pcm_stream_t direction, json_object * argsJ) {
- json_object *sourceJ = NULL, *paramsJ = NULL, *sinkJ = NULL, *targetJ = NULL;
+ json_object *sourceJ = NULL, *paramsJ = NULL, *sinkJ = NULL, *targetJ = NULL, *quirksJ = NULL;
char *apiVerb = NULL, *apiInfo = NULL;
apiVerbHandleT *handle = NULL;
int error;
@@ -554,7 +563,7 @@ PUBLIC AlsaSndPcmT * ApiPcmAttachOne(SoftMixerT *mixer, const char *uid, snd_pcm
}
CDS_INIT_LIST_HEAD(&pcm->sndcard->registryList);
- error = wrap_json_unpack(argsJ, "{ss,s?s,s?s,s?s,s?i,s?i,s?o,s?o,s?o !}"
+ error = wrap_json_unpack(argsJ, "{ss,s?s,s?s,s?s,s?i,s?i,s?o,s?o,s?o,s?o,s?b !}"
, "uid", &pcm->uid
, "pcmplug_params", &pcm->sndcard->cid.pcmplug_params
, "path", &pcm->sndcard->cid.devpath
@@ -564,9 +573,11 @@ PUBLIC AlsaSndPcmT * ApiPcmAttachOne(SoftMixerT *mixer, const char *uid, snd_pcm
, "sink", &sinkJ
, "source", &sourceJ
, "params", &paramsJ
+ , "quirks", &quirksJ
+ , "optional", &pcm->optional
);
if (error) {
- AFB_ApiError(mixer->api, "%s: hal=%s missing 'uid|path|cardid|device|sink|source|params' error=%s args=%s",
+ AFB_ApiError(mixer->api, "%s: hal=%s missing 'uid|path|cardid|device|sink|source|params|quirks|optional' error=%s args=%s",
__func__, uid, wrap_json_get_error_string(error), json_object_get_string(argsJ));
goto fail_pcm_sndcard;
}
@@ -576,11 +587,21 @@ PUBLIC AlsaSndPcmT * ApiPcmAttachOne(SoftMixerT *mixer, const char *uid, snd_pcm
else
pcm->isPcmPlug = false;
+ pcm->sndcard->optional = pcm->optional;
+
// try to open sound card control interface
pcm->sndcard->ctl = AlsaByPathOpenCtl(mixer, pcm->uid, pcm->sndcard);
if (!pcm->sndcard->ctl) {
+ if (pcm->optional) {
+
+ AFB_API_INFO(mixer->api, "%s: hal=%s Fail to open OPTIONAL sndcard uid=%s devpath=%s cardid=%s",
+ __func__, uid, pcm->uid, pcm->sndcard->cid.devpath, pcm->sndcard->cid.cardid);
+ goto done;
+ }
+
AFB_ApiError(mixer->api, "%s: hal=%s Fail to open sndcard uid=%s devpath=%s cardid=%s",
__func__, uid, pcm->uid, pcm->sndcard->cid.devpath, pcm->sndcard->cid.cardid);
+
goto fail_pcm_sndcard;
}
@@ -658,6 +679,29 @@ PUBLIC AlsaSndPcmT * ApiPcmAttachOne(SoftMixerT *mixer, const char *uid, snd_pcm
pcm->sndcard->params->channels = pcm->nbChannels;
+ if (quirksJ) {
+ int nbQuirks = (int) json_object_array_length(quirksJ);
+
+ for (int idx = 0; idx < nbQuirks; idx++) {
+ json_object * quirkJ = json_object_array_get_idx(quirksJ, idx);
+
+ if (!json_object_is_type(quirkJ, json_type_string)) {
+ AFB_API_ERROR(mixer->api, "%s: hal=%s quirk must be of type string, arg=%s",
+ __func__, uid, json_object_get_string(quirkJ));
+ goto fail_pcm_channels;
+ }
+ const char * quirk = json_object_get_string(quirkJ);
+
+#define QUIRK_CHECK(quirkS, quirk) \
+ if (!strcmp(quirkS, #quirk)) { \
+ pcm->quirks |= quirk; \
+ AFB_API_INFO(mixer->api, "%s: PCM=%s has quirk %s",__func__, uid, #quirk);\
+ }
+
+ QUIRK_CHECK(quirk, QUIRK_BOGUS_POLL_REVENTS_DEMANGLING);
+ }
+ }
+
if (controlsJ) {
json_object *volJ = NULL, *muteJ = NULL;
error = wrap_json_unpack(controlsJ, "{s?o,s?o !}"
@@ -741,7 +785,7 @@ PUBLIC AlsaSndPcmT * ApiPcmAttachOne(SoftMixerT *mixer, const char *uid, snd_pcm
goto fail_pcm_uid;
}
}
-
+done:
return pcm;
fail_pcm_uid: