summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/alsa/alsa-api-loop.c62
-rw-r--r--plugins/alsa/alsa-api-mixer.c50
-rw-r--r--plugins/alsa/alsa-api-pcm.c45
-rw-r--r--plugins/alsa/alsa-api-streams.c24
-rw-r--r--plugins/alsa/alsa-core-ctl.c99
-rw-r--r--plugins/alsa/alsa-core-pcm.c24
-rw-r--r--plugins/alsa/alsa-effect-ramp.c17
-rw-r--r--plugins/alsa/alsa-plug-dmix.c2
-rw-r--r--plugins/alsa/alsa-plug-rate.c2
-rw-r--r--plugins/alsa/alsa-plug-route.c12
-rw-r--r--plugins/alsa/alsa-softmixer.c5
-rw-r--r--plugins/alsa/alsa-softmixer.h17
-rw-r--r--plugins/alsa/alsa-transaction.c62
-rw-r--r--plugins/alsa/alsa-transaction.h7
-rw-r--r--plugins/alsa/alsa-utils-bypath.c16
15 files changed, 312 insertions, 132 deletions
diff --git a/plugins/alsa/alsa-api-loop.c b/plugins/alsa/alsa-api-loop.c
index 16491a0..ffab6bc 100644
--- a/plugins/alsa/alsa-api-loop.c
+++ b/plugins/alsa/alsa-api-loop.c
@@ -40,20 +40,25 @@ PUBLIC AlsaLoopSubdevT *ApiLoopFindSubdev(SoftMixerT *mixer, const char *streamU
AlsaLoopSubdevT * subdev;
cds_list_for_each_entry(subdev, &_loop->subdevs.list, list) {
if (!subdev->uid) {
- subdev->uid = streamUid;
+ subdev->uid = strdup(streamUid);
+ if (!subdev->uid) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto fail;
+ }
*loop = _loop;
return subdev;
}
}
}
}
+fail:
return NULL;
}
STATIC AlsaLoopSubdevT *ProcessOneSubdev(SoftMixerT *mixer, AlsaSndLoopT *loop, json_object *subdevJ) {
- AFB_ApiDebug(mixer->api, "%s", __func__);
+ AFB_ApiDebug(mixer->api, "%s : %s", __func__, json_object_get_string(subdevJ));
AlsaLoopSubdevT *subdev = calloc(1, sizeof (AlsaLoopSubdevT));
if (subdev == NULL) {
@@ -69,7 +74,7 @@ STATIC AlsaLoopSubdevT *ProcessOneSubdev(SoftMixerT *mixer, AlsaSndLoopT *loop,
if (error) {
AFB_ApiError(mixer->api,
"%s: loop=%s missing (uid|subdev|numid) error=%s json=%s",
- __func__, loop->uid, wrap_json_get_error_string(error),json_object_get_string(subdevJ));
+ __func__, loop->uid, wrap_json_get_error_string(error), json_object_get_string(subdevJ));
goto fail_subdev;
}
@@ -100,6 +105,7 @@ STATIC AlsaLoopSubdevT *ProcessOneSubdev(SoftMixerT *mixer, AlsaSndLoopT *loop,
pcmCtl->closeAtDeletion = true;
// free PCM as we only open loop to assert it's a valid capture device
+ AlsaMixerTransactionObjectForget(mixer->transaction, pcmCtl);
AlsaPcmCtlDelete(mixer, pcmCtl);
AFB_ApiDebug(mixer->api, "%s DONE", __func__);
@@ -114,9 +120,8 @@ fail:
return NULL;
}
-static void freeSubdev(AlsaLoopSubdevT * subdev) {
- if (subdev->uid)
- free((char*)subdev->uid);
+static void freeSubdev(SoftMixerT* mixer, AlsaLoopSubdevT * subdev) {
+ free(subdev->uid);
free(subdev);
}
@@ -219,7 +224,7 @@ fail_loop_subdev: {
AlsaLoopSubdevT * subdev, *tmp;
cds_list_for_each_entry_safe(subdev, tmp, &loop->subdevs.list, list) {
cds_list_del(&subdev->list);
- freeSubdev(subdev);
+ freeSubdev(mixer, subdev);
}
}
@@ -235,37 +240,38 @@ fail:
static void loopDestroy(SoftMixerT * mixer, void* arg) {
AlsaSndLoopT * loop = (AlsaSndLoopT*) arg;
- AFB_ApiDebug(mixer->api, "%s... %s not implemented", __func__, loop->uid);
- return;
-
- if (loop->sndcard) {
- if (loop->sndcard->ctl) {
- snd_ctl_close(loop->sndcard->ctl);
- free(loop->sndcard->ctl);
- }
- free(loop->sndcard);
- }
+ AFB_ApiDebug(mixer->api, "%s... %s", __func__, loop->uid);
AlsaLoopSubdevT * subdev, *tmp;
cds_list_for_each_entry_safe(subdev, tmp, &loop->subdevs.list, list) {
cds_list_del(&subdev->list);
- freeSubdev(subdev);
+ freeSubdev(mixer, subdev);
}
+
+ if (loop->sndcard->ctl)
+ snd_ctl_close(loop->sndcard->ctl);
+
mixer->nbLoops--;
+ cds_list_del(&loop->list);
free(loop);
+ AFB_ApiDebug(mixer->api, "DONE !");
}
static AlsaSndLoopT * loopCreate(SoftMixerT *mixer, const char *uid, json_object *argsJ) {
+
AlsaSndLoopT * newLoop = AttachOneLoop(mixer, uid, argsJ);
if (!newLoop) {
goto fail;
}
mixer->nbLoops++;
- cds_list_add_tail(&newLoop->list, &mixer->loops.list);
+ cds_list_add(&newLoop->list, &mixer->loops.list);
AlsaMixerTransactionObjectAdd(mixer->transaction, newLoop, loopDestroy);
+ loopsDisplay(mixer);
+
+
fail:
return newLoop;
}
@@ -315,3 +321,21 @@ fail_loop:
fail:
return -1;
}
+
+
+static void subdevDisplay(SoftMixerT *mixer, AlsaLoopSubdevT * subdev) {
+ AFB_ApiInfo(mixer->api, "\t\tsubdev id %d, uid %s", subdev->numid, subdev->uid);
+}
+
+PUBLIC void loopsDisplay(SoftMixerT *mixer) {
+ AlsaSndLoopT * loop;
+ AFB_ApiInfo(mixer->api, "Mixer %s LOOPS:", mixer->uid);
+ cds_list_for_each_entry(loop, &mixer->loops.list, list) {
+ AFB_ApiInfo(mixer->api, "\tLOOP %s", loop->uid);
+ AlsaLoopSubdevT * subdev;
+ cds_list_for_each_entry(subdev, &loop->subdevs.list, list) {
+ subdevDisplay(mixer, subdev);
+ }
+ }
+ AFB_ApiInfo(mixer->api, "--------------");
+}
diff --git a/plugins/alsa/alsa-api-mixer.c b/plugins/alsa/alsa-api-mixer.c
index ae08461..6d80b55 100644
--- a/plugins/alsa/alsa-api-mixer.c
+++ b/plugins/alsa/alsa-api-mixer.c
@@ -23,6 +23,38 @@
#include <string.h>
#include <pthread.h>
+static struct cds_list_head mixerList;
+
+static void MixerDelete(SoftMixerT * mixer);
+
+static void MixerExit() {
+ SoftMixerT *mixer, *tmp;
+ printf("%s !\n", __func__);
+
+ cds_list_for_each_entry_safe(mixer, tmp, &mixerList, list) {
+ // remove this mixer from the global mixer list
+ cds_list_del(&mixer->list);
+ AFB_ApiInfo(mixer->api, "Terminating mixer %s", mixer->uid);
+
+ AlsaMixerTransaction * transaction, * tmp_trans;
+ cds_list_for_each_entry_safe(transaction, tmp_trans, &mixer->transactionList, transaction_node) {
+ cds_list_del(&transaction->transaction_node);
+ AlsaMixerTransactionDoCleanup(transaction);
+ AlsaMixerTransactionDelete(transaction);
+ }
+ MixerDelete(mixer);
+ }
+ printf("%s DONE ! Bye !\n", __func__);
+}
+
+CTLP_ONLOAD(plugin, callbacks){
+
+ AFB_ApiInfo(plugin->api, "MIXER INIT");
+ CDS_INIT_LIST_HEAD(&mixerList);
+
+ atexit(MixerExit);
+ return 0;
+}
static void MixerRemoveVerb(AFB_ReqT request) {
@@ -249,7 +281,7 @@ STATIC json_object *MixerInfoOneZone(AlsaSndZoneT *zone, int verbose) {
json_object *paramsJ;
wrap_json_pack(&paramsJ, "{si,ss,si}"
, "rate", zone->params->rate
- , "format", zone->params->formatS
+ , "format", zone->params->formatString
, "channels", zone->params->channels
);
json_object_object_add(responseJ, "params", paramsJ);
@@ -514,6 +546,8 @@ STATIC void MixerAttachVerb(AFB_ReqT request) {
int error;
AlsaMixerTransaction * transaction = NULL;
+ AFB_ApiInfo(mixer->api, "%s: %s", __func__, json_object_get_string(argsJ));
+
error = wrap_json_unpack(argsJ, "{ss,s?s,s?s,s?o,s?o,s?o,s?o,s?o,s?o !}"
, "uid", &uid
, "prefix", &prefix
@@ -688,6 +722,8 @@ CTLP_CAPI(MixerAttach, source, argsJ, responseJ) {
goto OnErrorExit;
}
+ mixer->transaction = transaction;
+
if (playbackJ) {
error = ApiSinkAttach(mixer, NULL, uid, playbackJ);
if (error) goto OnErrorExit;
@@ -718,6 +754,8 @@ CTLP_CAPI(MixerAttach, source, argsJ, responseJ) {
if (error) goto OnErrorExit;
}
+ mixer->transaction = NULL;
+
// return mixer info data after attach
return 0;
@@ -725,7 +763,14 @@ OnErrorExit:
return -1;
}
+static void MixerDelete(SoftMixerT * mixer) {
+ free((char*)mixer->info);
+ free((char*)mixer->uid);
+ free(mixer);
+}
+
CTLP_CAPI(MixerCreate, source, argsJ, responseJ) {
+
SoftMixerT *mixer = calloc(1, sizeof (SoftMixerT));
if (mixer == NULL) {
SOFTMIXER_NOMEM(source->api);
@@ -790,6 +835,7 @@ CTLP_CAPI(MixerCreate, source, argsJ, responseJ) {
CDS_INIT_LIST_HEAD(&mixer->zones.list);
CDS_INIT_LIST_HEAD(&mixer->streams.list);
CDS_INIT_LIST_HEAD(&mixer->ramps.list);
+ CDS_INIT_LIST_HEAD(&mixer->transactionList);
mixer->sdLoop = AFB_GetEventLoop(source->api);
mixer->api = source->api;
@@ -799,6 +845,8 @@ CTLP_CAPI(MixerCreate, source, argsJ, responseJ) {
if (error)
goto fail_info;
+ cds_list_add_tail(&mixer->list, &mixerList);
+
return 0;
fail_info:
diff --git a/plugins/alsa/alsa-api-pcm.c b/plugins/alsa/alsa-api-pcm.c
index 85e3c3a..036f158 100644
--- a/plugins/alsa/alsa-api-pcm.c
+++ b/plugins/alsa/alsa-api-pcm.c
@@ -372,11 +372,23 @@ OnErrorExit:
return;
}
+PUBLIC AlsaPcmHwInfoT* ApiPcmParamsDup(SoftMixerT* mixer, AlsaPcmHwInfoT* params) {
+ AlsaPcmHwInfoT* _params = (AlsaPcmHwInfoT*) malloc(sizeof(AlsaPcmHwInfoT));
+ if (params)
+ memcpy(_params, params, sizeof(AlsaPcmHwInfoT));
+ return _params;
+}
+
PUBLIC void ApiPcmDelParams(SoftMixerT* mixer, AlsaPcmHwInfoT* params) {
- free((char*)params->formatS);
free(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);
+
+}
+
PUBLIC AlsaPcmHwInfoT * ApiPcmSetParams(SoftMixerT *mixer, const char *uid, json_object * paramsJ) {
const char *format = NULL, *access = NULL;
@@ -404,20 +416,14 @@ PUBLIC AlsaPcmHwInfoT * ApiPcmSetParams(SoftMixerT *mixer, const char *uid, json
}
}
+ // default format
if (!format) {
params->format = SND_PCM_FORMAT_S16_LE;
- params->formatS = strdup("S16_LE");
- if (params->formatS == NULL) {
- SOFTMIXER_NOMEM(mixer->api);
- goto fail_params;
- }
+ strcpy(params->formatString, SND_FORMAT_DEFAULT);
goto check_access;
}
- params->formatS = strdup(format);
- if (params->formatS == NULL) {
- SOFTMIXER_NOMEM(mixer->api);
- goto fail_params;
- }
+ strncpy(params->formatString, format, SND_FORMAT_STRING_LEN);
+
#define FORMAT_CHECK(arg) if (!strcmp(format,#arg)) { params->format = SND_PCM_FORMAT_##arg; goto check_access; }
FORMAT_CHECK(S16_LE);
@@ -441,7 +447,7 @@ PUBLIC AlsaPcmHwInfoT * ApiPcmSetParams(SoftMixerT *mixer, const char *uid, json
goto fail_params;
check_access:
- AFB_ApiNotice(mixer->api, "%s: %s format set to SND_PCM_FORMAT_%s", __func__, uid, params->formatS);
+ AFB_ApiNotice(mixer->api, "%s: %s format set to SND_PCM_FORMAT_%s", __func__, uid, params->formatString);
#define ACCESS_CHECK(arg) if (!strcmp(access,#arg)) { params->access = SND_PCM_ACCESS_##arg; goto success;}
@@ -466,33 +472,33 @@ success:
return params;
fail_params:
- free(params);
+ ApiPcmDelParams(mixer, params);
fail:
return NULL;
}
static void pcmChannelsDestroy(SoftMixerT * mixer, AlsaSndPcmT * pcm) {
- AFB_ApiDebug(mixer->api, "%s: pcm %s (%d channels)", __func__, pcm->uid, pcm->nbChannels);
+ AFB_ApiDebug(mixer->api, "\t%s: pcm %s (%d channels)", __func__, pcm->uid, pcm->nbChannels);
AlsaPcmChannelT * channel, *tmp;
cds_list_for_each_entry_safe(channel, tmp, &pcm->channels.list, list) {
cds_list_del(&channel->list);
- AFB_ApiDebug(mixer->api, "%s: del channel %s", __func__, channel->uid);
free((char *)channel->uid);
free(channel);
}
- AFB_ApiDebug(mixer->api, "%s: pcm %s DONE", __func__, pcm->uid);
+ AFB_ApiDebug(mixer->api, "\t%s: pcm %s DONE", __func__, pcm->uid);
}
PUBLIC void ApiPcmDelete(SoftMixerT * mixer, AlsaSndPcmT * pcm) {
- AFB_ApiDebug(mixer->api, "%s: pcm %s", __func__, pcm->uid);
+ AFB_ApiDebug(mixer->api, "%s: pcm %s\n", __func__, pcm->uid);
free(pcm->apiVerbHandle);
AlsaSndCtlT * card = pcm->sndcard;
- if (card->cid.pcmplug_params)
+ if (card->cid.pcmplug_params) {
free((char*)card->cid.pcmplug_params);
+ }
pcmChannelsDestroy(mixer, pcm);
@@ -503,10 +509,11 @@ PUBLIC void ApiPcmDelete(SoftMixerT * mixer, AlsaSndPcmT * pcm) {
if (pcm->verb &&
(strcmp(pcm->verb, SOFTMIXER_VERB_NONE)!=0)) {
- int error = afb_api_del_verb(mixer->api, pcm->verb, (void**)&pcm->apiVerbHandle);
+ int error = afb_api_del_verb(mixer->api, pcm->verb, (void**)NULL);
if (error) {
AFB_ApiError(mixer->api, "Failed to remove verb %s", pcm->verb);
}
+ free((char*)pcm->verb);
}
free((char*)pcm->uid);
diff --git a/plugins/alsa/alsa-api-streams.c b/plugins/alsa/alsa-api-streams.c
index e35a8b7..80609bc 100644
--- a/plugins/alsa/alsa-api-streams.c
+++ b/plugins/alsa/alsa-api-streams.c
@@ -196,7 +196,7 @@ static void paramsOverride(SoftMixerT *mixer, AlsaStreamAudioT * destStream, con
if (dest->format != src->format) {
AFB_ApiNotice(mixer->api, "Stream %s overrides format to %d", destStream->uid, src->format);
dest->format = src->format;
- dest->formatS = strdup(src->formatS);
+ strncpy(dest->formatString, src->formatString, SND_FORMAT_STRING_LEN );
}
if (dest->access != src->access) {
@@ -334,11 +334,14 @@ STATIC int CreateOneStream(SoftMixerT *mixer, const char * uid, AlsaStreamAudioT
// create a fake zone for rate converter selection
zone=alloca(sizeof(AlsaSndZoneT));
- zone->uid= playback->uid;
- zone->params = playback->sndcard->params;
+ zone->uid = playback->uid;
+
+ ApiPcmParamsShow(mixer,"PLAYBACK to FAKE ZONE", playback->sndcard->params);
+
+ zone->params = ApiPcmParamsDup(mixer, playback->sndcard->params);
zone->ccount = playback->nbChannels;
- }
+ }
// create mute control and Registry it as pause/resume ctl)
if (asprintf(&runName, "pause-%s", stream->uid) == -1) {
@@ -379,6 +382,9 @@ STATIC int CreateOneStream(SoftMixerT *mixer, const char * uid, AlsaStreamAudioT
AFB_ApiDebug(mixer->api,"%s: create softvol control", __func__);
+ ApiPcmParamsShow(mixer, "Stream ", stream->params);
+ ApiPcmParamsShow(mixer, "Zone", zone->params);
+
// create volume control before softvol pcm is opened
volNumid = AlsaCtlCreateControl(mixer,
captureCard,
@@ -396,14 +402,14 @@ STATIC int CreateOneStream(SoftMixerT *mixer, const char * uid, AlsaStreamAudioT
if ((zone->params->rate != stream->params->rate) ||
(zone->params->format != stream->params->format)) {
AFB_ApiNotice(mixer->api,
- "%s: Instanciate a RATE CONVERTER (stream [%d,%s(%d),%d channels], zone [%d,%s(%d), %d channels])",
+ "%s: Instanciate a RATE CONVERTER (stream [rate %d,%s(%d),%d channels], zone [rate %d,%s(%d), %d channels])",
__func__,
stream->params->rate,
- stream->params->formatS,
+ stream->params->formatString,
stream->params->format,
stream->params->channels,
zone->params->rate,
- zone->params->formatS,
+ zone->params->formatString,
zone->params->format,
zone->params->channels);
@@ -423,9 +429,9 @@ STATIC int CreateOneStream(SoftMixerT *mixer, const char * uid, AlsaStreamAudioT
playbackName = (char*) streamPcm->cid.cardid;
}
- streamPcm->isPcmPlug = zone->isPcmPlug;
+ streamPcm->isPcmPlug = zone->isPcmPlug;
- AFB_ApiDebug(mixer->api, "%s: Opening PCM PLAYBACK name %s", __func__, playbackName);
+ AFB_ApiDebug(mixer->api, "%s: Opening PCM PLAYBACK name %s", __func__, playbackName);
// 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-core-ctl.c b/plugins/alsa/alsa-core-ctl.c
index dcfd860..020c13c 100644
--- a/plugins/alsa/alsa-core-ctl.c
+++ b/plugins/alsa/alsa-core-ctl.c
@@ -42,7 +42,7 @@ PUBLIC snd_ctl_elem_id_t *AlsaCtlGetNumidElemId(SoftMixerT *mixer, AlsaSndCtlT *
int error;
int index;
snd_ctl_elem_list_t *ctlList = NULL;
- snd_ctl_elem_id_t *elemId;
+ snd_ctl_elem_id_t *elemId = NULL;
snd_ctl_elem_list_alloca(&ctlList);
@@ -50,14 +50,14 @@ PUBLIC snd_ctl_elem_id_t *AlsaCtlGetNumidElemId(SoftMixerT *mixer, AlsaSndCtlT *
AFB_ApiError(mixer->api,
"%s [%s] fail retrieve controls",
__func__, ALSA_CTL_UID(sndcard->ctl, string));
- goto OnErrorExit;
+ goto fail;
}
if ((error = snd_ctl_elem_list_alloc_space(ctlList, snd_ctl_elem_list_get_count(ctlList))) < 0) {
AFB_ApiError(mixer->api,
"%s [%s] fail retrieve count",
__func__, ALSA_CTL_UID(sndcard->ctl, string));
- goto OnErrorExit;
+ goto fail;
}
// Fulup: do not understand why snd_ctl_elem_list should be call twice to get a valid ctlCount
@@ -65,7 +65,7 @@ PUBLIC snd_ctl_elem_id_t *AlsaCtlGetNumidElemId(SoftMixerT *mixer, AlsaSndCtlT *
AFB_ApiError(mixer->api,
"%s [%s] fail retrieve controls",
__func__, ALSA_CTL_UID(sndcard->ctl, string));
- goto OnErrorExit;
+ goto fail_space;
}
// loop on control to find the right one
@@ -83,23 +83,25 @@ PUBLIC snd_ctl_elem_id_t *AlsaCtlGetNumidElemId(SoftMixerT *mixer, AlsaSndCtlT *
AFB_ApiNotice(mixer->api,
"%s [%s] fail get numid=%i count",
__func__, ALSA_CTL_UID(sndcard->ctl, string), numid);
- goto OnErrorExit;
+ goto fail_space;
}
- // clear ctl list and return elemid
- snd_ctl_elem_list_clear(ctlList);
- return elemId;
+ snd_ctl_elem_list_free_space(ctlList);
+ return elemId;
-OnErrorExit:
- if (ctlList) snd_ctl_elem_list_clear(ctlList);
+fail_space:
+ snd_ctl_elem_list_free_space(ctlList);
+fail:
return NULL;
+
+
}
PUBLIC snd_ctl_elem_id_t *AlsaCtlGetNameElemId(SoftMixerT *mixer, AlsaSndCtlT *sndcard, const char *ctlName) {
int error;
int index;
snd_ctl_elem_list_t *ctlList = NULL;
- snd_ctl_elem_id_t *elemId;
+ snd_ctl_elem_id_t *elemId = NULL;
snd_ctl_elem_list_alloca(&ctlList);
@@ -107,14 +109,14 @@ PUBLIC snd_ctl_elem_id_t *AlsaCtlGetNameElemId(SoftMixerT *mixer, AlsaSndCtlT *s
AFB_ApiError(mixer->api,
"%s cardid='%s' cardname='%s' fail retrieve controls",
__func__, sndcard->cid.cardid, sndcard->cid.name);
- goto OnErrorExit;
+ goto fail;
}
if ((error = snd_ctl_elem_list_alloc_space(ctlList, snd_ctl_elem_list_get_count(ctlList))) < 0) {
AFB_ApiError(mixer->api,
"%s cardid='%s' cardname='%s' fail retrieve count",
__func__, sndcard->cid.cardid, sndcard->cid.name);
- goto OnErrorExit;
+ goto fail;
}
// Fulup: do not understand why snd_ctl_elem_list should be call twice to get a valid ctlCount
@@ -122,7 +124,7 @@ PUBLIC snd_ctl_elem_id_t *AlsaCtlGetNameElemId(SoftMixerT *mixer, AlsaSndCtlT *s
AFB_ApiError(mixer->api,
"%s cardid='%s' cardname='%s' fail retrieve controls",
__func__, sndcard->cid.cardid, sndcard->cid.name);
- goto OnErrorExit;
+ goto fail_space;
}
// loop on control to find the right one
@@ -138,16 +140,17 @@ PUBLIC snd_ctl_elem_id_t *AlsaCtlGetNameElemId(SoftMixerT *mixer, AlsaSndCtlT *s
if (index == ctlCount) {
AFB_ApiNotice(mixer->api, "AlsaCtlGetNameElemId cardid='%s' cardname='%s' ctl not found name=%s", sndcard->cid.cardid, sndcard->cid.name, ctlName);
- goto OnErrorExit;
+ goto fail_space;
}
- // clear ctl list and return elemid
- snd_ctl_elem_list_clear(ctlList);
- return elemId;
+ snd_ctl_elem_list_free_space(ctlList);
+ return elemId;
+
+fail_space:
+ snd_ctl_elem_list_free_space(ctlList);
+fail:
+ return NULL;
-OnErrorExit:
- if (ctlList) snd_ctl_elem_list_clear(ctlList);
- return NULL;
}
@@ -317,7 +320,7 @@ PUBLIC int AlsaCtlNumidSetLong(SoftMixerT *mixer, AlsaSndCtlT *sndcard, int numi
AFB_ApiError(mixer->api,
"%s cardid=%s cardname=%s fail to find numid=%d",
__func__, sndcard->cid.cardid, sndcard->cid.longname, numid);
- goto OnErrorExit;
+ goto fail;
}
int error = CtlElemIdSetLong(mixer, sndcard, elemId, value);
@@ -325,11 +328,15 @@ PUBLIC int AlsaCtlNumidSetLong(SoftMixerT *mixer, AlsaSndCtlT *sndcard, int numi
AFB_ApiError(mixer->api,
"%s cardid=%s cardname=%s fail to set numid=%d value=%ld",
__func__, sndcard->cid.cardid, sndcard->cid.longname, numid, value);
- goto OnErrorExit;
+ goto fail_elemId;
}
+ free(elemId);
return 0;
-OnErrorExit:
+
+fail_elemId:
+ free(elemId);
+fail:
return -1;
}
@@ -340,7 +347,7 @@ PUBLIC int AlsaCtlNumidGetLong(SoftMixerT *mixer, AlsaSndCtlT *sndcard, int numi
AFB_ApiError(mixer->api,
"%s cardid=%s cardname=%s fail to find numid=%d",
__func__, sndcard->cid.cardid, sndcard->cid.longname, numid);
- goto OnErrorExit;
+ goto fail;
}
int error = CtlElemIdGetLong(mixer, sndcard, elemId, value);
@@ -348,12 +355,16 @@ PUBLIC int AlsaCtlNumidGetLong(SoftMixerT *mixer, AlsaSndCtlT *sndcard, int numi
AFB_ApiError(mixer->api,
"%s cardid=%s cardname=%s fail to get numid=%d value",
__func__, sndcard->cid.cardid, sndcard->cid.longname, numid);
- goto OnErrorExit;
+ goto fail_elemId;
}
+ free(elemId);
return 0;
-OnErrorExit:
- return -1;
+
+fail_elemId:
+ free(elemId);
+fail:
+ return -1;
}
PUBLIC int AlsaCtlNameSetLong(SoftMixerT *mixer, AlsaSndCtlT *sndcard, const char *ctlName, long value) {
@@ -363,7 +374,7 @@ PUBLIC int AlsaCtlNameSetLong(SoftMixerT *mixer, AlsaSndCtlT *sndcard, const cha
AFB_ApiError(mixer->api,
"%s cardid=%s cardname=%s fail to find crlName=%s",
__func__, sndcard->cid.cardid, sndcard->cid.longname, ctlName);
- goto OnErrorExit;
+ goto fail;
}
int error = CtlElemIdSetLong(mixer, sndcard, elemId, value);
@@ -371,11 +382,15 @@ PUBLIC int AlsaCtlNameSetLong(SoftMixerT *mixer, AlsaSndCtlT *sndcard, const cha
AFB_ApiError(mixer->api,
"%s cardid=%s cardname=%s fail to set crlName=%s value=%ld",
__func__, sndcard->cid.cardid, sndcard->cid.longname, ctlName, value);
- goto OnErrorExit;
+ goto fail_elemId;
}
+ free(elemId);
return 0;
-OnErrorExit:
+
+fail_elemId:
+ free(elemId);
+fail:
return -1;
}
@@ -386,7 +401,7 @@ PUBLIC int AlsaCtlNameGetLong(SoftMixerT *mixer, AlsaSndCtlT *sndcard, const cha
AFB_ApiError(mixer->api,
"%s cardid=%s cardname=%s fail to find crlName=%s",
__func__, sndcard->cid.cardid, sndcard->cid.longname, ctlName);
- goto OnErrorExit;
+ goto fail;
}
int error = CtlElemIdGetLong(mixer, sndcard, elemId, value);
@@ -394,11 +409,15 @@ PUBLIC int AlsaCtlNameGetLong(SoftMixerT *mixer, AlsaSndCtlT *sndcard, const cha
AFB_ApiError(mixer->api,
"%s cardid=%s cardname=%s fail to get crlName=%s value",
__func__, sndcard->cid.cardid, sndcard->cid.longname, ctlName);
- goto OnErrorExit;
+ goto fail_elemId;
}
+ free(elemId);
return 0;
-OnErrorExit:
+
+fail_elemId:
+ free(elemId);
+fail:
return -1;
}
@@ -462,7 +481,7 @@ PUBLIC int AlsaCtlCreateControl(SoftMixerT *mixer, AlsaSndCtlT *sndcard, char* c
AFB_ApiError(mixer->api,
"%s cardid=%s cardname=%s fail to create ctlName=%s",
__func__, sndcard->cid.cardid, sndcard->cid.longname, ctlName);
- goto OnErrorExit;
+ goto fail;
}
elemId = AlsaCtlGetNumidElemId(mixer, sndcard, numid);
@@ -473,15 +492,17 @@ PUBLIC int AlsaCtlCreateControl(SoftMixerT *mixer, AlsaSndCtlT *sndcard, char* c
AFB_ApiError(mixer->api,
"%s cardid=%s cardname=%s fail to set ctlName=%s Numid=%d",
__func__, sndcard->cid.cardid, sndcard->cid.longname, ctlName, numid);
- goto OnErrorExit;
+ goto fail;
}
AFB_ApiNotice(mixer->api,
"%s cardid=%s cardname=%s ctl create name=%s numid=%d value=%ld",
- __func__, sndcard->cid.cardid, sndcard->cid.longname, ctlName, numid, value);
+
+ __func__, sndcard->cid.cardid, sndcard->cid.longname, ctlName, numid, value);
+fail:
+ free(elemId);
return numid;
-OnErrorExit:
- return -1;
+
}
STATIC int CtlSubscribeEventCB(sd_event_source* src, int fd, uint32_t revents, void* userData) {
diff --git a/plugins/alsa/alsa-core-pcm.c b/plugins/alsa/alsa-core-pcm.c
index adceebc..a45d463 100644
--- a/plugins/alsa/alsa-core-pcm.c
+++ b/plugins/alsa/alsa-core-pcm.c
@@ -29,6 +29,9 @@ for the specific language governing permissions and
#include <sys/syscall.h>
#include <sched.h>
+#include <signal.h>
+#include <poll.h>
+
#include "time_utils.h"
static int xrun(snd_pcm_t * pcm, int error);
@@ -127,7 +130,7 @@ PUBLIC int AlsaPcmConf(SoftMixerT *mixer, AlsaPcmCtlT *pcm, int mode) {
if ((error = snd_pcm_hw_params_set_format(pcm->handle, pxmHwParams, opts->format)) < 0) {
AFB_ApiError(mixer->api,
"%s (%s) mixer=%s Set_Format=%s (%d) FAILED current=%d error=%s",
- __func__, card, mixer->uid, opts->formatS, opts->format, format, snd_strerror(error));
+ __func__, card, mixer->uid, opts->formatString, opts->format, format, snd_strerror(error));
AlsaDumpFormats(mixer, pcm->handle);
goto OnErrorExit;
}
@@ -483,6 +486,7 @@ static void *readThreadEntry(void *handle) {
if (muted)
readSuspend(pcmCopyHandle);
+
/* loop until end */
for (;;) {
@@ -531,7 +535,7 @@ static void *readThreadEntry(void *handle) {
continue;
}
- unsigned short revents;
+ unsigned short revents = 0;
int res = snd_pcm_poll_descriptors_revents(pcmCopyHandle->pcmIn->handle, framePfds, pcmCopyHandle->nbPcmFds, &revents);
@@ -549,6 +553,7 @@ static void *readThreadEntry(void *handle) {
}
done:
pthread_exit(0);
+
return NULL;
}
@@ -689,9 +694,14 @@ PUBLIC int AlsaPcmCopyStop(SoftMixerT *mixer, AlsaPcmCopyHandleT * handle) {
if (pthread_join(handle->rthread, NULL) != 0)
AFB_ApiDebug(mixer->api, "%s: Failed to join read thread", __func__);
+ AFB_ApiDebug(mixer->api, "%s: Copy threads of %s are STOPPED", __func__, handle->stream->uid);
+
sem_destroy(&handle->sem);
- AFB_ApiDebug(mixer->api, "%s: Copy threads of %s are STOPPED", __func__, handle->stream->uid);
+ alsa_ringbuf_free(handle->rbuf);
+
+ free(handle->pollFds);
+ free(handle);
return 0;
@@ -709,9 +719,17 @@ PUBLIC int AlsaPcmCopyStart(SoftMixerT *mixer, AlsaStreamAudioT *stream, AlsaPcm
/* remember configuration of capture */
pcmIn->params = (AlsaPcmHwInfoT*)malloc(sizeof(AlsaPcmHwInfoT));
+ if (!pcmIn->params) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto OnErrorExit;
+ }
memcpy(pcmIn->params, opts, sizeof(AlsaPcmHwInfoT));
pcmOut->params = (AlsaPcmHwInfoT*)malloc(sizeof(AlsaPcmHwInfoT));
+ if (!pcmOut->params) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto OnErrorExit;
+ }
memcpy(pcmOut->params, opts, sizeof(AlsaPcmHwInfoT));
pcmIn->mixer = mixer;
diff --git a/plugins/alsa/alsa-effect-ramp.c b/plugins/alsa/alsa-effect-ramp.c
index e51879d..a3bf54b 100644
--- a/plugins/alsa/alsa-effect-ramp.c
+++ b/plugins/alsa/alsa-effect-ramp.c
@@ -125,12 +125,12 @@ PUBLIC int AlsaVolRampApply(SoftMixerT *mixer, AlsaSndCtlT *sndcard, AlsaStreamA
if (newvol < 0) newvol = curvol - newvol;
else newvol = curvol + newvol;
}
-
+
if (count != 1) {
AFB_ApiError(mixer->api,
"%s: mixer=%s stream=%s invalid-numeric expect {uid:%s, vol:[+,-,=]value} get vol:%s",
__func__, mixer->uid, stream->uid, uid, json_object_get_string(volJ));
- goto OnErrorExit;
+ goto OnErrorExit;
}
break;
case json_type_int:
@@ -152,21 +152,22 @@ PUBLIC int AlsaVolRampApply(SoftMixerT *mixer, AlsaSndCtlT *sndcard, AlsaStreamA
__func__, mixer->uid, stream->uid, uid, stream->volume);
goto OnErrorExit;
}
-
+
// search for ramp uid in mixer
AlsaVolRampT * ramp;
bool found = false;
cds_list_for_each_entry(ramp, &mixer->ramps.list, list) {
if (ramp->uid && !strcasecmp(ramp->uid, uid)) {
- break;
- }
- }
-
+ found=true;
+ break;
+ }
+ }
+
if (!found) {
AFB_ApiError(mixer->api,
"%s: mixer=%s stream=%s ramp=%s does not exit",
__func__, mixer->uid, stream->uid, uid);
- goto OnErrorExit;
+ goto OnErrorExit;
}
VolRampHandleT *rHandle = calloc(1, sizeof (VolRampHandleT));
diff --git a/plugins/alsa/alsa-plug-dmix.c b/plugins/alsa/alsa-plug-dmix.c
index d63b79f..9aaf866 100644
--- a/plugins/alsa/alsa-plug-dmix.c
+++ b/plugins/alsa/alsa-plug-dmix.c
@@ -86,7 +86,7 @@ PUBLIC AlsaPcmCtlT* AlsaCreateDmix(SoftMixerT *mixer, const char* pcmName, AlsaS
}
if (sndSlave->params->format) {
- error += snd_config_imake_string(&elemConfig, "format", sndSlave->params->formatS);
+ error += snd_config_imake_string(&elemConfig, "format", sndSlave->params->formatString);
if (error) goto OnErrorExit;
error += snd_config_add(slaveConfig, elemConfig);
if (error) goto OnErrorExit;
diff --git a/plugins/alsa/alsa-plug-rate.c b/plugins/alsa/alsa-plug-rate.c
index b2c43d2..d4a3068 100644
--- a/plugins/alsa/alsa-plug-rate.c
+++ b/plugins/alsa/alsa-plug-rate.c
@@ -55,7 +55,7 @@ PUBLIC AlsaPcmCtlT* AlsaCreateRate(SoftMixerT *mixer, AlsaStreamAudioT * stream,
error += snd_config_add(slaveConfig, elemConfig);
}
if (params->format) {
- error += snd_config_imake_string(&elemConfig, "format", params->formatS);
+ error += snd_config_imake_string(&elemConfig, "format", params->formatString);
error += snd_config_add(slaveConfig, elemConfig);
}
if (error) goto OnErrorExit;
diff --git a/plugins/alsa/alsa-plug-route.c b/plugins/alsa/alsa-plug-route.c
index c00c0cf..ebc7074 100644
--- a/plugins/alsa/alsa-plug-route.c
+++ b/plugins/alsa/alsa-plug-route.c
@@ -113,7 +113,17 @@ PUBLIC AlsaPcmCtlT* AlsaCreateRoute(SoftMixerT *mixer, AlsaSndZoneT *zone, int o
goto fail_nodump;
}
- zone->params = pcmRoute->params;
+ pcmRoute->params = ApiPcmParamsDup(mixer, pcmRoute->params);
+ if (!pcmRoute->params) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto fail_nodump;
+ }
+
+ zone->params = ApiPcmParamsDup(mixer, pcmRoute->params);
+ if (!zone->params) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto fail_nodump;
+ }
// use 1st zone channel to retrieve sound card name + channel count.
diff --git a/plugins/alsa/alsa-softmixer.c b/plugins/alsa/alsa-softmixer.c
index c8b50a0..f0d280e 100644
--- a/plugins/alsa/alsa-softmixer.c
+++ b/plugins/alsa/alsa-softmixer.c
@@ -24,9 +24,4 @@
CTLP_LUA_REGISTER("alsa-softmixer")
-// Call at initialisation time
-CTLP_ONLOAD(plugin, callbacks){
-// AFB_ApiDebug(plugin->api, "SoftMixer Plugin Registered: uid='%s' 'info='%s'", plugin->uid, plugin->info);
- return 0;
-}
diff --git a/plugins/alsa/alsa-softmixer.h b/plugins/alsa/alsa-softmixer.h
index a8cc6de..346964a 100644
--- a/plugins/alsa/alsa-softmixer.h
+++ b/plugins/alsa/alsa-softmixer.h
@@ -101,10 +101,13 @@ typedef struct {
int subdev;
} AlsaDevInfoT;
+#define SND_FORMAT_STRING_LEN 16
+#define SND_FORMAT_DEFAULT "S16_LE"
+
typedef struct {
unsigned int rate;
unsigned int channels;
- const char *formatS;
+ char formatString[SND_FORMAT_STRING_LEN];
snd_pcm_format_t format;
snd_pcm_access_t access;
size_t sampleSize;
@@ -238,7 +241,7 @@ typedef struct {
} AlsaSndPcmT;
typedef struct {
- const char*uid;
+ char * uid;
int index;
int numid;
struct cds_list_head list;
@@ -305,7 +308,11 @@ typedef struct SoftMixerT_{
unsigned int nbRamps;
AlsaVolRampT ramps;
- AlsaMixerTransaction * transaction;
+ AlsaMixerTransaction * transaction; // current transaction
+
+ struct cds_list_head list; // node to list of all mixers
+
+ struct cds_list_head transactionList; // all transactions of this mixer
} SoftMixerT;
// alsa-utils-bypath.c
@@ -368,12 +375,16 @@ PUBLIC int ApiStreamAttach(SoftMixerT *mixer, AFB_ReqT request, const char * uid
PUBLIC int ApiZoneAttach(SoftMixerT *mixer, AFB_ReqT request, const char *, json_object * argsJ);
PUBLIC int ApiRampAttach(SoftMixerT *mixer, AFB_ReqT request, const char *, json_object *argsJ);
+PUBLIC void loopsDisplay(SoftMixerT * mixer);
+
// helper used for attach verb,and also by the streams API for fake zones
PUBLIC AlsaSndZoneT * zoneCreate(SoftMixerT* mixer, const char * uid, json_object * argsJ);
PUBLIC AlsaLoopSubdevT *ApiLoopFindSubdev(SoftMixerT *mixer, const char *streamUid, const char *targetUid, AlsaSndLoopT **loop);
PUBLIC AlsaPcmHwInfoT *ApiPcmSetParams(SoftMixerT *mixer, const char *uid, json_object *paramsJ);
+PUBLIC AlsaPcmHwInfoT* ApiPcmParamsDup(SoftMixerT* mixer, AlsaPcmHwInfoT* params);
+PUBLIC void ApiPcmParamsShow(SoftMixerT * mixer, const char * msg, const AlsaPcmHwInfoT * params);
PUBLIC void ApiPcmDelParams(SoftMixerT*, AlsaPcmHwInfoT*);
PUBLIC AlsaSndPcmT *ApiPcmAttachOne(SoftMixerT *mixer, const char *uid, snd_pcm_stream_t direction, json_object *argsJ);
diff --git a/plugins/alsa/alsa-transaction.c b/plugins/alsa/alsa-transaction.c
index bd32603..1958c87 100644
--- a/plugins/alsa/alsa-transaction.c
+++ b/plugins/alsa/alsa-transaction.c
@@ -5,23 +5,30 @@
#include "alsa-transaction.h"
#include "wrap-json.h"
+
+void AlsaMixerTransactionDelete(AlsaMixerTransaction * transaction) {
+ free((char*)transaction->uid);
+ free(transaction);
+}
+
AlsaMixerTransaction * AlsaMixerTransactionNew(struct SoftMixerT_ * mixer, const char * uid) {
- AlsaMixerTransaction * newList = (AlsaMixerTransaction *) malloc(sizeof(AlsaMixerTransaction));
- if (newList == NULL)
+ AlsaMixerTransaction * transaction = (AlsaMixerTransaction *) malloc(sizeof(AlsaMixerTransaction));
+ if (transaction == NULL)
goto fail;
- CDS_INIT_LIST_HEAD(&newList->list);
- newList->uid = strdup(uid);
- if (newList->uid == NULL) {
+ CDS_INIT_LIST_HEAD(&transaction->item_list);
+ transaction->uid = strdup(uid);
+ if (transaction->uid == NULL) {
goto fail_list;
}
- newList->mixer = mixer;
+ transaction->mixer = mixer;
+ cds_list_add(&transaction->transaction_node, &mixer->transactionList);
- return newList;
+ return transaction;
fail_list:
- free(newList);
+ free(transaction);
fail:
return NULL;
}
@@ -30,6 +37,15 @@ void AlsaMixerTransactionDataListDestroy(AlsaMixerTransaction* list) {
free(list);
}
+void AlsaMixerTransactionObjectForget(AlsaMixerTransaction* list, void * object) {
+ AlsaMixerTransactionDataItem *item, *tmp;
+ cds_list_for_each_entry_safe(item, tmp, &list->item_list, list_entry)
+ if (item->object == object) {
+ cds_list_del(&item->list_entry);
+ free(item);
+ }
+ }
+
bool AlsaMixerTransactionObjectAdd(AlsaMixerTransaction* list, void* object, AlsaTransactionDestructor destructor) {
bool ret = false;
AlsaMixerTransactionDataItem * newItem = NULL;
@@ -43,7 +59,7 @@ bool AlsaMixerTransactionObjectAdd(AlsaMixerTransaction* list, void* object, Als
CDS_INIT_LIST_HEAD(&newItem->list_entry);
newItem->object = object;
newItem->destructor = destructor;
- cds_list_add(&newItem->list_entry, &list->list);
+ cds_list_add(&newItem->list_entry, &list->item_list);
ret = true;
fail:
@@ -54,13 +70,17 @@ fail:
void AlsaMixerTransactionDoCleanup(AlsaMixerTransaction* transaction) {
AlsaMixerTransactionDataItem * item, *sav;
- cds_list_for_each_entry_safe(item, sav, &transaction->list, list_entry) {
+ AFB_ApiInfo(transaction->mixer->api, "%s for transaction %s", __func__, transaction->uid);
+
+ cds_list_for_each_entry_safe(item, sav, &transaction->item_list, list_entry) {
if (item->destructor)
item->destructor(transaction->mixer, item->object);
cds_list_del(&item->list_entry);
free(item);
}
+
+ AFB_ApiInfo(transaction->mixer->api, "%s for transaction %s .. DONE !", __func__, transaction->uid);
}
void AlsaMixerTransactionVerbCB(AFB_ReqT request) {
@@ -69,43 +89,47 @@ void AlsaMixerTransactionVerbCB(AFB_ReqT request) {
json_object *argsJ = afb_req_json(request);
int error;
char * action = NULL;
- const char * uid;
+ const char * uid = NULL;
error = wrap_json_unpack(argsJ, "{ss!}",
"action", &action);
if (error) {
AFB_ReqFailF(request, "missing action", "%s: missing 'action' field: %s", transaction->uid, json_object_get_string(argsJ));
- goto OnErrorExit;
+ goto fail;
}
uid = strdup(transaction->uid);
if (!uid) {
SOFTMIXER_NOMEM(transaction->mixer->api);
- goto OnErrorExit;
+ goto fail;
}
if (strcmp(action, "remove") == 0) {
AlsaMixerTransactionDoCleanup(transaction);
- error = afb_api_del_verb(transaction->mixer->api, transaction->uid, (void**)transaction);
+
+ // remove this transaction for the list of mixer
+ cds_list_del(&transaction->transaction_node);
+
+ error = afb_api_del_verb(transaction->mixer->api, transaction->uid, (void**)NULL);
if (error) {
AFB_ReqFail(request, "verb deletion" , "verb was not removed");
- goto OnErrorExit;
+ goto fail;
}
+ AlsaMixerTransactionDelete(transaction);
+
} else {
AFB_ReqFailF(request, "unsupported action", "%s: unsupported action %s (supported ones are ['remove']", transaction->uid, action);
- goto OnErrorExit;
+ goto fail;
}
responseJ=json_object_new_object();
json_object_object_add(responseJ, "result", json_object_new_string("OK"));
AFB_ReqSuccess(request, responseJ, uid);
+fail:
free((char*)uid);
return;
-OnErrorExit:
- return;
-
}
diff --git a/plugins/alsa/alsa-transaction.h b/plugins/alsa/alsa-transaction.h
index a0af0ae..dd6e91b 100644
--- a/plugins/alsa/alsa-transaction.h
+++ b/plugins/alsa/alsa-transaction.h
@@ -13,7 +13,8 @@ typedef void (*AlsaTransactionDestructor) (struct SoftMixerT_ *, void*);
typedef struct {
const char * uid;
struct SoftMixerT_* mixer;
- struct cds_list_head list;
+ struct cds_list_head item_list; // list of items
+ struct cds_list_head transaction_node; // node in a list of transactions
} AlsaMixerTransaction;
typedef struct {
@@ -24,10 +25,14 @@ typedef struct {
extern AlsaMixerTransaction * AlsaMixerTransactionNew(struct SoftMixerT_ * api, const char*);
+extern void AlsaMixerTransactionDelete(AlsaMixerTransaction * transaction);
+
extern void AlsaMixerTransactionDataListDestroy(AlsaMixerTransaction*);
extern bool AlsaMixerTransactionObjectAdd(AlsaMixerTransaction*, void * object, AlsaTransactionDestructor destructor);
+extern void AlsaMixerTransactionObjectForget(AlsaMixerTransaction* list, void * object);
+
extern void AlsaMixerTransactionDoCleanup(AlsaMixerTransaction*);
extern bool AlsaMixerTransactionVerbCreate(AlsaMixerTransaction*);
diff --git a/plugins/alsa/alsa-utils-bypath.c b/plugins/alsa/alsa-utils-bypath.c
index 908d247..49f89e4 100644
--- a/plugins/alsa/alsa-utils-bypath.c
+++ b/plugins/alsa/alsa-utils-bypath.c
@@ -91,15 +91,18 @@ PUBLIC void AlsaPcmCtlDelete(SoftMixerT* mixer, void * arg) {
AlsaPcmCtlT * pcmCtl = (AlsaPcmCtlT *) arg;
+ AFB_ApiDebug(mixer->api, "%s of %s (plug: %d)", __func__, pcmCtl->name, pcmCtl->isPcmPlug);
+
if (!pcmCtl->closeAtDeletion)
goto done;
+ // TODO REMOVE THIS ONCE THE BUG IN BLUEZ-ALSA IS CORRECTED. Else Closing it make SIGSEGV
if (pcmCtl->isPcmPlug) {
- AFB_ApiDebug(mixer->api, "%s: Wont' close '%s' PCM, its slave is a plug", __func__, pcmCtl->cid.cardid);
+ AFB_ApiDebug(mixer->api, "%s: Wont' close '%s' PCM, it uses is a plug", __func__, pcmCtl->cid.cardid);
goto done;
}
- AFB_ApiDebug(mixer->api, "%s: Closing %s",__func__, pcmCtl->cid.cardid);
+ AFB_ApiDebug(mixer->api, "%s: Closing %s", __func__, pcmCtl->cid.cardid);
error = snd_pcm_close(pcmCtl->handle);
if (error) {
// It's safe to ignore this error. In case of ioplug PCM, the device may have already disappeared
@@ -109,8 +112,13 @@ PUBLIC void AlsaPcmCtlDelete(SoftMixerT* mixer, void * arg) {
done:
+ ApiPcmDelParams(mixer, pcmCtl->params);
+
free((char*) pcmCtl->cid.cardid);
free(pcmCtl);
+
+ AFB_ApiDebug(mixer->api, "%s DONE", __func__);
+
}
PUBLIC AlsaPcmCtlT *AlsaByPathOpenPcmCtl(SoftMixerT *mixer, AlsaDevInfoT *pcmDev, snd_pcm_stream_t direction) {
@@ -156,7 +164,6 @@ PUBLIC AlsaPcmCtlT *AlsaByPathOpenPcmCtl(SoftMixerT *mixer, AlsaDevInfoT *pcmDev
goto fail_cardid;
}
-
// inherit CID from pcmDev
pcmCtl->cid.cardid = pcmDev->cardid;
pcmCtl->cid.cardidx = pcmDev->cardidx;
@@ -165,6 +172,9 @@ PUBLIC AlsaPcmCtlT *AlsaByPathOpenPcmCtl(SoftMixerT *mixer, AlsaDevInfoT *pcmDev
pcmCtl->cid.name=NULL;
pcmCtl->cid.longname=NULL;
+ if (pcmDev->pcmplug_params)
+ pcmCtl->isPcmPlug = true;
+
AFB_ApiDebug(mixer->api,
"%s OPEN PCM '%s', direction %s",
__func__, pcmDev->cardid, direction==SND_PCM_STREAM_PLAYBACK?"playback":"capture");