diff options
-rw-r--r-- | plugins/alsa/alsa-api-pcm.c | 34 | ||||
-rw-r--r-- | plugins/alsa/alsa-api-streams.c | 3 | ||||
-rw-r--r-- | plugins/alsa/alsa-api-zones.c | 2 | ||||
-rw-r--r-- | plugins/alsa/alsa-plug-route.c | 4 | ||||
-rw-r--r-- | plugins/alsa/alsa-softmixer.h | 6 |
5 files changed, 44 insertions, 5 deletions
diff --git a/plugins/alsa/alsa-api-pcm.c b/plugins/alsa/alsa-api-pcm.c index ce74982..50246e1 100644 --- a/plugins/alsa/alsa-api-pcm.c +++ b/plugins/alsa/alsa-api-pcm.c @@ -536,7 +536,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 +554,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 !}" , "uid", &pcm->uid , "pcmplug_params", &pcm->sndcard->cid.pcmplug_params , "path", &pcm->sndcard->cid.devpath @@ -564,9 +564,10 @@ PUBLIC AlsaSndPcmT * ApiPcmAttachOne(SoftMixerT *mixer, const char *uid, snd_pcm , "sink", &sinkJ , "source", &sourceJ , "params", ¶msJ + , "quirks", &quirksJ ); 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' error=%s args=%s", __func__, uid, wrap_json_get_error_string(error), json_object_get_string(argsJ)); goto fail_pcm_sndcard; } @@ -579,8 +580,10 @@ PUBLIC AlsaSndPcmT * ApiPcmAttachOne(SoftMixerT *mixer, const char *uid, snd_pcm // try to open sound card control interface pcm->sndcard->ctl = AlsaByPathOpenCtl(mixer, pcm->uid, pcm->sndcard); if (!pcm->sndcard->ctl) { + 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 +661,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 +767,7 @@ PUBLIC AlsaSndPcmT * ApiPcmAttachOne(SoftMixerT *mixer, const char *uid, snd_pcm goto fail_pcm_uid; } } - +done: return pcm; fail_pcm_uid: diff --git a/plugins/alsa/alsa-api-streams.c b/plugins/alsa/alsa-api-streams.c index f7149cc..7241f41 100644 --- a/plugins/alsa/alsa-api-streams.c +++ b/plugins/alsa/alsa-api-streams.c @@ -445,8 +445,9 @@ STATIC int CreateOneStream(SoftMixerT *mixer, const char * uid, AlsaStreamAudioT } streamPcm->isPcmPlug = zone->isPcmPlug; + streamPcm->quirks = zone->quirks; - AFB_ApiDebug(mixer->api, "%s: Opening PCM PLAYBACK name %s", __func__, playbackName); + AFB_ApiDebug(mixer->api, "%s: Opening PCM PLAYBACK name %s (quirks=0x%x)", __func__, playbackName, streamPcm->quirks); // everything is now ready to open playback pcm in BLOCKING mode this time error = snd_pcm_open(&streamPcm->handle, playbackName, SND_PCM_STREAM_PLAYBACK, 0 /* will block*/ ); diff --git a/plugins/alsa/alsa-api-zones.c b/plugins/alsa/alsa-api-zones.c index bf3bece..03a2264 100644 --- a/plugins/alsa/alsa-api-zones.c +++ b/plugins/alsa/alsa-api-zones.c @@ -81,6 +81,7 @@ fail: return NULL; } + STATIC AlsaSndZoneT *AttachOneZone(SoftMixerT *mixer, const char *uid, json_object *zoneJ) { AFB_ApiDebug(mixer->api, "%s uid %s", __func__, uid); @@ -241,6 +242,7 @@ PUBLIC AlsaSndZoneT * zoneCreate(SoftMixerT* mixer, const char * uid, json_objec } zone->isPcmPlug = routeConfig->isPcmPlug; + zone->quirks = routeConfig->quirks; fail: return zone; diff --git a/plugins/alsa/alsa-plug-route.c b/plugins/alsa/alsa-plug-route.c index a192e03..d3f22a7 100644 --- a/plugins/alsa/alsa-plug-route.c +++ b/plugins/alsa/alsa-plug-route.c @@ -31,6 +31,7 @@ typedef struct { int ccount; int port; bool isPcmPlug; + unsigned int quirks; } ChannelCardPortT; STATIC int CardChannelByUid(SoftMixerT *mixer, const char *uid, ChannelCardPortT *response) { @@ -59,6 +60,7 @@ STATIC int CardChannelByUid(SoftMixerT *mixer, const char *uid, ChannelCardPortT response->cardidx = pcm->sndcard->cid.cardidx; response->pcmplug_params = pcm->sndcard->cid.pcmplug_params; response->isPcmPlug= pcm->isPcmPlug; + response->quirks = pcm->quirks; found = true; break; } @@ -151,6 +153,8 @@ PUBLIC AlsaPcmCtlT* AlsaCreateRoute(SoftMixerT *mixer, AlsaSndZoneT *zone, int o pcmRoute->isPcmPlug = true; } + pcmRoute->quirks = slave.quirks; + // temporary store to enable multiple channel to route to the same port snd_config_t **cports = alloca(zone->nbSinks * sizeof (void*)); diff --git a/plugins/alsa/alsa-softmixer.h b/plugins/alsa/alsa-softmixer.h index 2e7874d..c73dd0e 100644 --- a/plugins/alsa/alsa-softmixer.h +++ b/plugins/alsa/alsa-softmixer.h @@ -128,6 +128,7 @@ typedef struct { bool closeAtDeletion; // intermediate pcms in the pcm chain must not be closed, else it make libasound abort() bool isPcmPlug; + unsigned int quirks; } AlsaPcmCtlT; typedef struct { @@ -224,8 +225,12 @@ typedef struct { struct cds_list_head list; snd_config_t * routeConfig; bool isPcmPlug; + unsigned int quirks; } AlsaSndZoneT; +/* This is a list of known sound card (hardware or driver) specific bugs */ +/* - do not trust the result of snd_pcm_poll_descriptors_revents */ +#define QUIRK_BOGUS_POLL_REVENTS_DEMANGLING (1<<0) typedef struct { const char *uid; const char *verb; @@ -238,6 +243,7 @@ typedef struct { struct cds_list_head list; bool isPcmPlug; void * apiVerbHandle; + unsigned int quirks; } AlsaSndPcmT; typedef struct { |