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.c375
1 files changed, 281 insertions, 94 deletions
diff --git a/plugins/alsa/alsa-api-pcm.c b/plugins/alsa/alsa-api-pcm.c
index 1bba75c..85e3c3a 100644
--- a/plugins/alsa/alsa-api-pcm.c
+++ b/plugins/alsa/alsa-api-pcm.c
@@ -51,17 +51,31 @@ typedef struct {
AlsaSndPcmT* pcm;
} apiVerbHandleT;
-STATIC AlsaPcmChannelT *ProcessOneChannel(SoftMixerT *mixer, const char *uid, json_object *argsJ) {
+STATIC AlsaPcmChannelT * ProcessOneChannel(SoftMixerT *mixer, const char *uid, json_object *argsJ) {
AlsaPcmChannelT *channel = calloc(1, sizeof (AlsaPcmChannelT));
+ if (channel == NULL) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto fail;
+ }
int error = wrap_json_unpack(argsJ, "{ss,si !}", "uid", &channel->uid, "port", &channel->port);
- if (error) goto OnErrorExit;
+ if (error) {
+ AFB_ApiError(mixer->api, "%s: sndcard=%s channel: missing (uid||port) error=%s json=%s",
+ __func__, uid, wrap_json_get_error_string(error), json_object_get_string(argsJ));
+ goto fail_channel;
+ }
+
+ CDS_INIT_LIST_HEAD(&channel->list);
channel->uid = strdup(channel->uid);
+ if (channel->uid == NULL) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto fail_channel;
+ }
return channel;
-OnErrorExit:
- AFB_ApiError(mixer->api, "ProcessOneChannel: sndcard=%s channel: missing (uid||port) error=%s json=%s", uid, wrap_json_get_error_string(error), json_object_get_string(argsJ));
+fail_channel:
free(channel);
+fail:
return NULL;
}
@@ -81,37 +95,45 @@ STATIC int PcmAttachOneCtl(SoftMixerT *mixer, AlsaSndCtlT *sndcard, json_object
AFB_ApiError(mixer->api,
"%s: cardid=%s channel: missing (numid|name|value) error=%s json=%s",
__func__, sndcard->cid.name, wrap_json_get_error_string(error), json_object_get_string(argsJ));
- goto OnErrorExit;
+ goto fail;
}
if (numid > 0) {
elemId = AlsaCtlGetNumidElemId(mixer, sndcard, numid);
if (!elemId) {
- AFB_ApiError(mixer->api, "PcmAttachOneCtl sndard=%s fail to find control numid=%d", sndcard->cid.cardid, numid);
- goto OnErrorExit;
+ AFB_ApiError(mixer->api, "%s sndard=%s fail to find control numid=%d",
+ __func__, sndcard->cid.cardid, numid);
+ goto fail;
}
} else {
elemId = AlsaCtlGetNameElemId(mixer, sndcard, name);
if (!elemId) {
- AFB_ApiError(mixer->api, "PcmAttachOneCtl sndard=%s fail to find control name=%s", sndcard->cid.cardid, name);
- goto OnErrorExit;
+ AFB_ApiError(mixer->api, "%s sndard=%s fail to find control name=%s",
+ __func__, sndcard->cid.cardid, name);
+ goto fail;
}
}
snd_ctl_elem_info_alloca(&elemInfo);
snd_ctl_elem_info_set_id(elemInfo, elemId);
control->name = strdup(snd_ctl_elem_info_get_name(elemInfo));
+ if (!control->name) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto fail_elemId;
+ }
control->numid = snd_ctl_elem_info_get_numid(elemInfo);
if (snd_ctl_elem_info(sndcard->ctl, elemInfo) < 0) {
- AFB_ApiError(mixer->api, "PcmAttachOneCtl: sndard=%s numid=%d name='%s' not loadable", sndcard->cid.cardid, control->numid, control->name);
- goto OnErrorExit;
+ AFB_ApiError(mixer->api, "%s: sndard=%s numid=%d name='%s' not loadable",
+ __func__, sndcard->cid.cardid, control->numid, control->name);
+ goto fail_control_name;
}
if (!snd_ctl_elem_info_is_writable(elemInfo)) {
- AFB_ApiError(mixer->api, "PcmAttachOneCtl: sndard=%s numid=%d name='%s' not writable", sndcard->cid.cardid, control->numid, control->name);
- goto OnErrorExit;
+ AFB_ApiError(mixer->api, "%s: sndard=%s numid=%d name='%s' not writable",
+ __func__, sndcard->cid.cardid, control->numid, control->name);
+ goto fail_control_name;
}
control->count = snd_ctl_elem_info_get_count(elemInfo);
@@ -132,22 +154,25 @@ STATIC int PcmAttachOneCtl(SoftMixerT *mixer, AlsaSndCtlT *sndcard, json_object
break;
default:
- AFB_ApiError(mixer->api, "PcmAttachOneCtl: sndard=%s numid=%d name='%s' invalid/unsupported type=%d",
- sndcard->cid.cardid, control->numid, control->name, snd_ctl_elem_info_get_type(elemInfo));
- goto OnErrorExit;
+ AFB_ApiError(mixer->api, "%s: sndard=%s numid=%d name='%s' invalid/unsupported type=%d",
+ __func__, sndcard->cid.cardid, control->numid, control->name, snd_ctl_elem_info_get_type(elemInfo));
+ goto fail_control_name;
}
if (error) {
- AFB_ApiError(mixer->api, "PcmAttachOneCtl: sndard=%s numid=%d name='%s' not writable", sndcard->cid.cardid, control->numid, control->name);
- goto OnErrorExit;
+ AFB_ApiError(mixer->api, "%s: sndard=%s numid=%d name='%s' not writable",
+ __func__, sndcard->cid.cardid, control->numid, control->name);
+ goto fail_control_name;
}
free(elemId);
-
return 0;
-OnErrorExit:
- if (elemId)free(elemId);
+fail_control_name:
+ free((char*)control->name);
+fail_elemId:
+ free(elemId);
+fail:
return -1;
}
@@ -161,7 +186,7 @@ STATIC int PcmSetControl(SoftMixerT *mixer, AlsaSndCtlT *sndcard, AlsaSndControl
elemId = AlsaCtlGetNumidElemId(mixer, sndcard, control->numid);
if (!elemId) {
- AFB_ApiError(mixer->api, "PcmSetControl sndard=%s fail to find control numid=%d", sndcard->cid.cardid, control->numid);
+ AFB_ApiError(mixer->api, "%s sndard=%s fail to find control numid=%d", __func__, sndcard->cid.cardid, control->numid);
goto OnErrorExit;
}
@@ -169,18 +194,18 @@ STATIC int PcmSetControl(SoftMixerT *mixer, AlsaSndCtlT *sndcard, AlsaSndControl
snd_ctl_elem_info_set_id(elemInfo, elemId);
if (snd_ctl_elem_info(sndcard->ctl, elemInfo) < 0) {
- AFB_ApiError(mixer->api, "PcmSetControl: sndard=%s numid=%d name='%s' not loadable", sndcard->cid.cardid, control->numid, control->name);
+ AFB_ApiError(mixer->api, "%s: sndard=%s numid=%d name='%s' not loadable", __func__, sndcard->cid.cardid, control->numid, control->name);
goto OnErrorExit;
}
if (!snd_ctl_elem_info_is_writable(elemInfo)) {
- AFB_ApiError(mixer->api, "PcmSetControl: sndard=%s numid=%d name='%s' not writable", sndcard->cid.cardid, control->numid, control->name);
+ AFB_ApiError(mixer->api, "%s: sndard=%s numid=%d name='%s' not writable", __func__, sndcard->cid.cardid, control->numid, control->name);
goto OnErrorExit;
}
error = CtlElemIdGetLong(mixer, sndcard, elemId, &curval);
if (error) {
- AFB_ApiError(mixer->api, "PcmSetControl sndard=%s fail to read control numid=%d", sndcard->cid.cardid, control->numid);
+ AFB_ApiError(mixer->api, "%s sndcard=%s fail to read control numid=%d", __func__, sndcard->cid.cardid, control->numid);
goto OnErrorExit;
}
@@ -347,9 +372,19 @@ OnErrorExit:
return;
}
+PUBLIC void ApiPcmDelParams(SoftMixerT* mixer, AlsaPcmHwInfoT* params) {
+ free((char*)params->formatS);
+ free(params);
+}
+
PUBLIC AlsaPcmHwInfoT * ApiPcmSetParams(SoftMixerT *mixer, const char *uid, json_object * paramsJ) {
- AlsaPcmHwInfoT *params = calloc(1, sizeof (AlsaPcmHwInfoT));
+
const char *format = NULL, *access = NULL;
+ AlsaPcmHwInfoT *params = calloc(1, sizeof (AlsaPcmHwInfoT));
+ if (params == NULL) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto fail;
+ }
// some default values
params->rate = ALSA_DEFAULT_PCM_RATE;
@@ -358,23 +393,31 @@ PUBLIC AlsaPcmHwInfoT * ApiPcmSetParams(SoftMixerT *mixer, const char *uid, json
if (paramsJ) {
int error =
- wrap_json_unpack(paramsJ, "{s?i,s?i, s?s, s?s !}",
- "rate", &params->rate,
- "channels",&params->channels,
- "format", &format,
+ wrap_json_unpack(paramsJ, "{s?i,s?s,s?s !}",
+ "rate", &params->rate,
+ "format", &format,
"access", &access);
if (error) {
- AFB_ApiError(mixer->api, "ApiPcmSetParams: sndcard=%s invalid params=%s", uid, json_object_get_string(paramsJ));
- goto OnErrorExit;
+ AFB_ApiError(mixer->api, "%s: sndcard=%s invalid params=%s",
+ __func__, uid, json_object_get_string(paramsJ));
+ goto fail_params;
}
}
- if (!format) {
+ if (!format) {
params->format = SND_PCM_FORMAT_S16_LE;
- params->formatS = "S16_LE";
+ params->formatS = strdup("S16_LE");
+ if (params->formatS == NULL) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto fail_params;
+ }
goto check_access;
}
params->formatS = strdup(format);
+ if (params->formatS == NULL) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto fail_params;
+ }
#define FORMAT_CHECK(arg) if (!strcmp(format,#arg)) { params->format = SND_PCM_FORMAT_##arg; goto check_access; }
FORMAT_CHECK(S16_LE);
@@ -394,11 +437,11 @@ PUBLIC AlsaPcmHwInfoT * ApiPcmSetParams(SoftMixerT *mixer, const char *uid, json
FORMAT_CHECK(FLOAT_LE);
FORMAT_CHECK(FLOAT_BE);
- AFB_ApiError(mixer->api, "ApiPcmSetParams:%s(params) unsupported format 'S16_LE|S32_L|...' format=%s", uid, format);
- goto OnErrorExit;
+ AFB_ApiError(mixer->api, "%s: %s(params) unsupported format 'S16_LE|S32_L|...' format=%s", __func__, uid, format);
+ goto fail_params;
check_access:
- AFB_ApiNotice(mixer->api, "ApiPcmSetParams:%s format set to SND_PCM_FORMAT_%s", uid, params->formatS);
+ AFB_ApiNotice(mixer->api, "%s: %s format set to SND_PCM_FORMAT_%s", __func__, uid, params->formatS);
#define ACCESS_CHECK(arg) if (!strcmp(access,#arg)) { params->access = SND_PCM_ACCESS_##arg; goto success;}
@@ -413,25 +456,97 @@ check_access:
ACCESS_CHECK(RW_INTERLEAVED);
ACCESS_CHECK(RW_NONINTERLEAVED);
- AFB_ApiNotice(mixer->api, "ApiPcmSetParams:%s(params) unsupported access 'RW_INTERLEAVED|MMAP_INTERLEAVED|MMAP_COMPLEX' access=%s", uid, access);
- goto OnErrorExit;
+ AFB_ApiNotice(mixer->api,
+ "%s:%s(params) unsupported access 'RW_INTERLEAVED|MMAP_INTERLEAVED|MMAP_COMPLEX' access=%s",
+ __func__,uid, access);
+ goto fail_params;
success:
- AFB_ApiNotice(mixer->api, "ApiPcmSetParams:%s access set to %s", uid, access);
+ AFB_ApiNotice(mixer->api, "%s:%s access set to %s", __func__, uid, access);
return params;
-OnErrorExit:
+fail_params:
free(params);
+fail:
return NULL;
}
-PUBLIC AlsaSndPcmT * ApiPcmAttachOne(SoftMixerT *mixer, const char *uid, snd_pcm_stream_t direction, json_object * argsJ) {
+
+static void pcmChannelsDestroy(SoftMixerT * mixer, AlsaSndPcmT * pcm) {
+ AFB_ApiDebug(mixer->api, "%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);
+}
+
+PUBLIC void ApiPcmDelete(SoftMixerT * mixer, AlsaSndPcmT * pcm) {
+
+ AFB_ApiDebug(mixer->api, "%s: pcm %s", __func__, pcm->uid);
+
+ free(pcm->apiVerbHandle);
+ AlsaSndCtlT * card = pcm->sndcard;
+ if (card->cid.pcmplug_params)
+ free((char*)card->cid.pcmplug_params);
+
+ pcmChannelsDestroy(mixer, pcm);
+
+ snd_ctl_close(card->ctl);
+ free(card);
+ free ((char*)pcm->mute.name);
+ free ((char*)pcm->volume.name);
+
+ if (pcm->verb &&
+ (strcmp(pcm->verb, SOFTMIXER_VERB_NONE)!=0)) {
+ int error = afb_api_del_verb(mixer->api, pcm->verb, (void**)&pcm->apiVerbHandle);
+ if (error) {
+ AFB_ApiError(mixer->api, "Failed to remove verb %s", pcm->verb);
+ }
+ }
+
+ free((char*)pcm->uid);
+ free(pcm);
+ AFB_ApiDebug(mixer->api, "%s: done", __func__);
+}
+
+PUBLIC AlsaSndPcmT * ApiPcmNew(SoftMixerT* mixer) {
AlsaSndPcmT *pcm = calloc(1, sizeof (AlsaSndPcmT));
+ if (pcm == NULL) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto fail;
+ }
+
+ CDS_INIT_LIST_HEAD(&pcm->list);
+ CDS_INIT_LIST_HEAD(&pcm->channels.list);
+fail:
+ return pcm;
+}
+
+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;
char *apiVerb = NULL, *apiInfo = NULL;
+ apiVerbHandleT *handle = NULL;
int error;
+ AlsaSndPcmT *pcm = ApiPcmNew(mixer);
+ if (pcm == NULL) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto fail;
+ }
+
pcm->sndcard = (AlsaSndCtlT*) calloc(1, sizeof (AlsaSndCtlT));
+ if (pcm->sndcard == NULL) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto fail_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 !}"
, "uid", &pcm->uid
, "pcmplug_params", &pcm->sndcard->cid.pcmplug_params
@@ -444,42 +559,40 @@ PUBLIC AlsaSndPcmT * ApiPcmAttachOne(SoftMixerT *mixer, const char *uid, snd_pcm
, "params", &paramsJ
);
if (error) {
- AFB_ApiError(mixer->api, "ApiPcmAttachOne: hal=%s missing 'uid|path|cardid|device|sink|source|params' error=%s args=%s", uid, wrap_json_get_error_string(error), json_object_get_string(argsJ));
- goto OnErrorExit;
+ AFB_ApiError(mixer->api, "%s: hal=%s missing 'uid|path|cardid|device|sink|source|params' error=%s args=%s",
+ __func__, uid, wrap_json_get_error_string(error), json_object_get_string(argsJ));
+ goto fail_pcm_sndcard;
}
+ if (pcm->sndcard->cid.pcmplug_params)
+ pcm->isPcmPlug = true;
+ else
+ pcm->isPcmPlug = false;
+
// try to open sound card control interface
pcm->sndcard->ctl = AlsaByPathOpenCtl(mixer, pcm->uid, pcm->sndcard);
if (!pcm->sndcard->ctl) {
- AFB_ApiError(mixer->api, "ApiPcmAttachOne: hal=%s Fail to open sndcard uid=%s devpath=%s cardid=%s", uid, pcm->uid, pcm->sndcard->cid.devpath, pcm->sndcard->cid.cardid);
- goto OnErrorExit;
- }
-
- // check sndcard accepts params
- pcm->sndcard->params = ApiPcmSetParams(mixer, pcm->uid, paramsJ);
- if (!pcm->sndcard->params) {
- AFB_ApiError(mixer->api, "ApiPcmAttachOne: hal=%s Fail to set params sndcard uid=%s params=%s", uid, pcm->uid, json_object_get_string(paramsJ));
- goto OnErrorExit;
+ 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;
}
if (direction == SND_PCM_STREAM_PLAYBACK) {
if (!sinkJ) {
- AFB_ApiError(mixer->api, "ApiPcmAttachOne: hal=%s SND_PCM_STREAM_PLAYBACK require sinks args=%s", uid, json_object_get_string(argsJ));
- goto OnErrorExit;
+ AFB_ApiError(mixer->api, "%s: hal=%s SND_PCM_STREAM_PLAYBACK require sinks args=%s",
+ __func__, uid, json_object_get_string(argsJ));
+ goto fail_pcm_sndcard_ctl;
}
targetJ = sinkJ;
}
if (direction == SND_PCM_STREAM_CAPTURE) {
if (!sourceJ) {
- AFB_ApiError(mixer->api, "ApiPcmAttachOne: hal=%s SND_PCM_STREAM_CAPTURE require sources args=%s", uid, json_object_get_string(argsJ));
- goto OnErrorExit;
+ AFB_ApiError(mixer->api, "%s: hal=%s SND_PCM_STREAM_CAPTURE require sources args=%s",
+ __func__, uid, json_object_get_string(argsJ));
+ goto fail_pcm_sndcard_ctl;
}
targetJ = sourceJ;
-
- // we may have to register SMIXER_SUBDS_CTLS per subdev (Fulup ToBeDone when sndcard get multiple device/subdev)
- pcm->sndcard->registry = calloc(SMIXER_SUBDS_CTLS + 1, sizeof (RegistryEntryPcmT));
- pcm->sndcard->rcount = SMIXER_SUBDS_CTLS;
}
json_object *channelsJ = NULL, *controlsJ = NULL;
@@ -488,33 +601,56 @@ PUBLIC AlsaSndPcmT * ApiPcmAttachOne(SoftMixerT *mixer, const char *uid, snd_pcm
, "controls", &controlsJ
);
if (error) {
- AFB_ApiNotice(mixer->api, "ApiPcmAttachOne: hal=%s pcms missing channels|[controls] error=%s paybacks=%s", uid, wrap_json_get_error_string(error), json_object_get_string(argsJ));
- goto OnErrorExit;
+ AFB_ApiNotice(mixer->api, "%s: hal=%s pcms missing channels|[controls] error=%s (%s)",
+ __func__, uid, wrap_json_get_error_string(error), json_object_get_string(argsJ));
+ goto fail_pcm_sndcard_ctl;
}
+
+ AlsaPcmChannelT * channel = NULL;
+
if (channelsJ) {
switch (json_object_get_type(channelsJ)) {
case json_type_object:
- pcm->ccount = 1;
- pcm->channels = calloc(2, sizeof (void*));
- pcm->channels[0] = ProcessOneChannel(mixer, pcm->uid, channelsJ);
- if (!pcm->channels[0]) goto OnErrorExit;
+ channel = ProcessOneChannel(mixer, pcm->uid, channelsJ);
+ if (channel == NULL) {
+ goto fail_pcm_channels;
+ }
+
+ pcm->nbChannels++;
+ cds_list_add_tail(&channel->list, &pcm->channels.list);
+
break;
- case json_type_array:
- pcm->ccount = (int) json_object_array_length(channelsJ);
- pcm->channels = calloc(pcm->ccount + 1, sizeof (void*));
- for (int idx = 0; idx < pcm->ccount; idx++) {
+ case json_type_array: {
+ int nbChannels = (int) json_object_array_length(channelsJ);
+
+ for (int idx = 0; idx < nbChannels; idx++) {
json_object *channelJ = json_object_array_get_idx(channelsJ, idx);
- pcm->channels[idx] = ProcessOneChannel(mixer, pcm->uid, channelJ);
- if (!pcm->channels[idx]) goto OnErrorExit;
+ channel = ProcessOneChannel(mixer, pcm->uid, channelJ);
+ if (!channel)
+ goto fail_pcm_channels;
+
+ pcm->nbChannels++;
+ cds_list_add_tail(&channel->list, &pcm->channels.list);
}
break;
+ }
default:
- AFB_ApiError(mixer->api, "ApiPcmAttachOne:%s invalid pcm=%s", pcm->uid, json_object_get_string(channelsJ));
- goto OnErrorExit;
+ AFB_ApiError(mixer->api, "%s:%s invalid pcm=%s", pcm->uid, __func__, json_object_get_string(channelsJ));
+ goto fail_pcm_sndcard_ctl;
}
}
+ // check sndcard accepts params
+ pcm->sndcard->params = ApiPcmSetParams(mixer, pcm->uid, paramsJ);
+ if (!pcm->sndcard->params) {
+ AFB_ApiError(mixer->api, "%s: hal=%s Fail to set params sndcard uid=%s params=%s",
+ __func__, uid, pcm->uid, json_object_get_string(paramsJ));
+ goto fail_pcm_sndcard_ctl;
+ }
+
+ pcm->sndcard->params->channels = pcm->nbChannels;
+
if (controlsJ) {
json_object *volJ = NULL, *muteJ = NULL;
error = wrap_json_unpack(controlsJ, "{s?o,s?o !}"
@@ -525,50 +661,101 @@ PUBLIC AlsaSndPcmT * ApiPcmAttachOne(SoftMixerT *mixer, const char *uid, snd_pcm
AFB_ApiNotice(mixer->api,
"%s: source missing [volume]|[mute] error=%s control=%s",
__func__, wrap_json_get_error_string(error), json_object_get_string(controlsJ));
- goto OnErrorExit;
+ goto fail_pcm_channels;
}
- if (volJ) error += PcmAttachOneCtl(mixer, pcm->sndcard, volJ, &pcm->volume);
- if (muteJ) error += PcmAttachOneCtl(mixer, pcm->sndcard, muteJ, &pcm->mute);
- if (error) goto OnErrorExit;
+ if (volJ) {
+ error = PcmAttachOneCtl(mixer, pcm->sndcard, volJ, &pcm->volume);
+ if (error)
+ goto fail_pcm_channels;
+ }
+ if (muteJ) {
+ error = PcmAttachOneCtl(mixer, pcm->sndcard, muteJ, &pcm->mute);
+ if (error)
+ goto fail_pcm_channels;
+ }
// create master control for this sink
if (direction == SND_PCM_STREAM_PLAYBACK) {
- if (asprintf(&apiVerb, "%s:playback", pcm->uid) == -1)
- goto OnErrorExit;
- if (asprintf(&apiInfo, "HAL:%s SND_PCM_STREAM_PLAYBACK", uid) == -1)
- goto OnErrorExit;
+ if (asprintf(&apiVerb, "%s:playback", pcm->uid) == -1) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto fail_pcm_channels;
+ }
+ if (asprintf(&apiInfo, "HAL:%s SND_PCM_STREAM_PLAYBACK", uid) == -1) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto fail_verb_name;
+ }
+
} else {
- if (asprintf(&apiVerb, "%s:capture", pcm->uid) == -1)
- goto OnErrorExit;
- if (asprintf(&apiInfo, "HAL:%s SND_PCM_STREAM_PLAYBACK", uid) == -1)
- goto OnErrorExit;
+ if (asprintf(&apiVerb, "%s:capture", pcm->uid) == -1) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto fail_pcm_channels;
+ }
+ if (asprintf(&apiInfo, "HAL:%s SND_PCM_STREAM_PLAYBACK", uid) == -1) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto fail_verb_name;
+ }
}
apiVerbHandleT *handle = calloc(1, sizeof (apiVerbHandleT));
+ if (handle == NULL) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto fail_api_info;
+ }
+
handle->uid = uid;
handle->pcm = pcm;
handle->mixer = mixer;
pcm->verb=apiVerb;
+ pcm->apiVerbHandle = handle;
+
error = afb_api_add_verb(mixer->api, apiVerb, apiInfo, ApiPcmVerbCB, handle, NULL, 0, 0);
if (error) {
- AFB_ApiError(mixer->api, "ApiPcmAttachOne mixer=%s verb=%s fail to Register Master control ", mixer->uid, apiVerb);
- goto OnErrorExit;
+ AFB_ApiError(mixer->api, "%s mixer=%s verb=%s fail to Register Master control ",
+ __func__, mixer->uid, apiVerb);
+ goto fail_handle;
}
} else {
/* no controls -> put dummy verb */
- pcm->verb = "none";
+ pcm->verb = SOFTMIXER_VERB_NONE;
}
// free useless resource and secure others
pcm->uid = strdup(pcm->uid);
+ if (pcm->uid == NULL) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto fail_handle;
+ }
+ const char ** ppcmplug = &(pcm->sndcard->cid.pcmplug_params);
+ if (*ppcmplug) {
+ *ppcmplug = strdup(*ppcmplug);
+ if (*ppcmplug == NULL) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto fail_pcm_uid;
+ }
+ }
return pcm;
-OnErrorExit:
- free(pcm);
- free(apiVerb);
- free(apiInfo);
+fail_pcm_uid:
+ free((char*)pcm->uid);
+fail_handle:
+ free(handle);
+fail_api_info:
+ free(apiInfo);
+fail_verb_name:
+ free(apiVerb);
+fail_pcm_channels:
+ pcmChannelsDestroy(mixer, pcm);
+fail_pcm_sndcard_ctl:
+ free(pcm->sndcard->ctl);
+fail_pcm_sndcard:
+ free(pcm->sndcard);
+fail_pcm:
+ free ((char*)pcm->mute.name);
+ free ((char*)pcm->volume.name);
+ free(pcm);
+fail:
return NULL;
}