summaryrefslogtreecommitdiffstats
path: root/plugins/alsa
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/alsa')
-rw-r--r--plugins/alsa/alsa-api-pcm.c34
-rw-r--r--plugins/alsa/alsa-api-streams.c3
-rw-r--r--plugins/alsa/alsa-api-zones.c2
-rw-r--r--plugins/alsa/alsa-plug-route.c4
-rw-r--r--plugins/alsa/alsa-softmixer.h6
5 files changed, 44 insertions, 5 deletions
diff --git a/plugins/alsa/alsa-api-pcm.c b/plugins/alsa/alsa-api-pcm.c
index 7fa97e1..26ea9dd 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", &paramsJ
+ , "quirks", &quirksJ
);
if (error) {
- AFB_API_ERROR(mixer->api, "%s: hal=%s missing 'uid|path|cardid|device|sink|source|params' error=%s args=%s",
+ AFB_API_ERROR(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_API_ERROR(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 edf506e..43485b4 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_API_DEBUG(mixer->api, "%s: Opening PCM PLAYBACK name %s", __func__, playbackName);
+ AFB_API_DEBUG(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 522058d..fcd29d7 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_API_DEBUG(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 2c7851d..8b49f99 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 2fb9370..f33ea62 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 {