aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/alsa/alsa-api-streams.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/alsa/alsa-api-streams.c')
-rw-r--r--plugins/alsa/alsa-api-streams.c325
1 files changed, 250 insertions, 75 deletions
diff --git a/plugins/alsa/alsa-api-streams.c b/plugins/alsa/alsa-api-streams.c
index 9a5c5c2..e35a8b7 100644
--- a/plugins/alsa/alsa-api-streams.c
+++ b/plugins/alsa/alsa-api-streams.c
@@ -19,7 +19,6 @@
#define _GNU_SOURCE // needed for vasprintf
#include "alsa-softmixer.h"
-#include "alsa-bluez.h"
#include <string.h>
#include <stdbool.h>
@@ -184,6 +183,34 @@ OnErrorExit:
return;
}
+static void paramsOverride(SoftMixerT *mixer, AlsaStreamAudioT * destStream, const AlsaPcmHwInfoT * src) {
+
+ if (!destStream->params || !src)
+ return;
+
+ AlsaPcmHwInfoT * dest = destStream->params;
+
+ /* The stream always has the same number of channels as the source */
+ dest->channels = src->channels;
+
+ 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);
+ }
+
+ if (dest->access != src->access) {
+ AFB_ApiNotice(mixer->api, "Stream %s overrides access to %d", destStream->uid, src->access);
+ dest->access = src->access;
+ }
+
+ if (dest->rate != src->rate) {
+ AFB_ApiNotice(mixer->api, "Stream %s overrides rate to %d", destStream->uid, src->rate);
+ dest->rate = src->rate;
+ }
+
+}
+
STATIC int CreateOneStream(SoftMixerT *mixer, const char * uid, AlsaStreamAudioT * stream) {
int error;
long value;
@@ -192,7 +219,7 @@ STATIC int CreateOneStream(SoftMixerT *mixer, const char * uid, AlsaStreamAudioT
AlsaSndCtlT *captureCard;
AlsaDevInfoT *captureDev = alloca(sizeof (AlsaDevInfoT));
AlsaLoopSubdevT *loopDev;
- AlsaSndZoneT *zone;
+ AlsaSndZoneT *zone = NULL;
char *volSlaveId = NULL;
char *playbackName = NULL;
char *runName = NULL;
@@ -200,9 +227,9 @@ STATIC int CreateOneStream(SoftMixerT *mixer, const char * uid, AlsaStreamAudioT
int pauseNumid = 0;
int volNumid = 0;
- AFB_ApiInfo(mixer->api,
- "%s, stream %s %s, source %s, sink %s, mute %d",
- __func__,uid, stream->uid, stream->source, stream->sink, stream->mute);
+ AFB_ApiDebug(mixer->api,
+ "NEW STREAM stream %s %s, source %s, sink %s, mute %d",
+ uid, stream->uid, stream->source, stream->sink, stream->mute);
loopDev = ApiLoopFindSubdev(mixer, stream->uid, stream->source, &loop);
if (loopDev) {
@@ -215,13 +242,13 @@ STATIC int CreateOneStream(SoftMixerT *mixer, const char * uid, AlsaStreamAudioT
captureDev->pcmplug_params = NULL;
captureCard = loop->sndcard;
- AFB_ApiInfo(mixer->api,
+ AFB_ApiDebug(mixer->api,
"%s: found loopdev %d,%d",
__func__, loop->capture, loopDev->index);
} else {
- // if capture UID is not present in loop search on sources
- AFB_ApiInfo(mixer->api,"%s: %s not found in loop, look in sources", __func__, uid);
+ // if capture UID is not present in loop search on known sources
+ AFB_ApiDebug(mixer->api,"%s: %s not found in loop, look in sources", __func__, uid);
AlsaSndCtlT *sourceDev = ApiSourceFindSubdev(mixer, stream->source);
if (sourceDev) {
@@ -232,7 +259,8 @@ STATIC int CreateOneStream(SoftMixerT *mixer, const char * uid, AlsaStreamAudioT
captureDev->subdev = sourceDev->cid.subdev;
captureDev->pcmplug_params = sourceDev->cid.pcmplug_params;
captureCard = sourceDev;
- AFB_ApiInfo(mixer->api, "%s found capture %s", __func__, uid);
+ AFB_ApiDebug(mixer->api, "%s found capture for %s (plug %s, card %s)",
+ __func__, uid, captureDev->pcmplug_params, sourceDev->cid.cardid);
} else {
AFB_ApiError(mixer->api,
"%s: mixer=%s stream=%s not found in loops/sources",
@@ -242,20 +270,28 @@ STATIC int CreateOneStream(SoftMixerT *mixer, const char * uid, AlsaStreamAudioT
}
// check PCM is valid and get its full name
- AlsaPcmCtlT *capturePcm = AlsaByPathOpenPcm(mixer, captureDev, SND_PCM_STREAM_CAPTURE);
- if (!capturePcm) goto OnErrorExit;
+ AlsaPcmCtlT *capturePcm = AlsaByPathOpenPcmCtl(mixer, captureDev, SND_PCM_STREAM_CAPTURE);
+ if (!capturePcm) {
+ AFB_ApiError(mixer->api,"%s: Unable to open the capture PCM !", __func__);
+ goto OnErrorExit;
+ }
+ paramsOverride(mixer, stream, captureCard->params);
+
+ capturePcm->closeAtDeletion = true;
capturePcm->mute = stream->mute;
- AFB_ApiInfo(mixer->api,"%s: PCM opened !", __func__);
+ AFB_ApiDebug(mixer->api,"%s: Capture PCM opened !", __func__);
// Registry capturePcm PCM for active/pause event
if (loopDev && loopDev->numid) {
+ AFB_ApiDebug(mixer->api, "%s: REGISTER active/pause", __func__);
error = AlsaCtlRegister(mixer, captureCard, capturePcm, FONTEND_NUMID_RUN, loopDev->numid);
- if (error) goto OnErrorExit;
+ if (error)
+ goto OnErrorExit;
}
- if (mixer->zones[0]) {
+ if (stream->sink) {
// if zones exist then retrieve zone pcmid and channel count
zone = ApiZoneGetByUid(mixer, stream->sink);
if (!zone) {
@@ -266,11 +302,13 @@ STATIC int CreateOneStream(SoftMixerT *mixer, const char * uid, AlsaStreamAudioT
}
// route PCM should have been create during zones attach phase.
- if (asprintf(&volSlaveId, "route-%s", zone->uid) == -1)
+ if (asprintf(&volSlaveId, "route-%s", zone->uid) == -1) {
+ SOFTMIXER_NOMEM(mixer->api);
goto OnErrorExit;
+ }
- } else {
- AlsaSndPcmT *playback = ApiSinkGetByUid(mixer, stream->sink);
+ } else if (stream->playback) {
+ AlsaSndPcmT *playback = ApiSinkGetByUid(mixer, stream->playback);
if (!playback) {
AFB_ApiError(mixer->api,
"%s: mixer=%s stream=%s fail to find sink playback='%s'",
@@ -278,26 +316,37 @@ STATIC int CreateOneStream(SoftMixerT *mixer, const char * uid, AlsaStreamAudioT
goto OnErrorExit;
}
- // retrieve channel count from route and push it to stream
- if (asprintf(&volSlaveId, "dmix-%s", playback->uid) == -1)
- goto OnErrorExit;
-
+ /* there is no dmix on pcmplugs */
+ if (playback->isPcmPlug) {
+ if (asprintf(&volSlaveId, "%s", playback->sndcard->cid.pcmplug_params) == -1) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto OnErrorExit;
+ }
+ }
+ else {
+ if (asprintf(&volSlaveId, "dmix-%s", playback->uid) == -1) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto OnErrorExit;
+ }
+ }
+
+ AFB_ApiError(mixer->api, "%s: Allocate a fake ZONE", __func__);
+
// create a fake zone for rate converter selection
zone=alloca(sizeof(AlsaSndZoneT));
zone->uid= playback->uid;
zone->params = playback->sndcard->params;
- zone->ccount = playback->ccount;
- }
+ zone->ccount = playback->nbChannels;
- // retrieve channel count from route and push it to stream
-
- stream->params->channels = zone->ccount;
+ }
// create mute control and Registry it as pause/resume ctl)
- if (asprintf(&runName, "pause-%s", stream->uid) == -1)
+ if (asprintf(&runName, "pause-%s", stream->uid) == -1) {
+ SOFTMIXER_NOMEM(mixer->api);
goto OnErrorExit;
+ }
- AFB_ApiInfo(mixer->api,"%s: create mute control...", __func__);
+ AFB_ApiDebug(mixer->api,"%s: create mute control...", __func__);
pauseNumid = AlsaCtlCreateControl(mixer, captureCard, runName, 1, 0, 1, 1, stream->mute);
if (pauseNumid <= 0) {
@@ -305,7 +354,7 @@ STATIC int CreateOneStream(SoftMixerT *mixer, const char * uid, AlsaStreamAudioT
goto OnErrorExit;
}
- AFB_ApiInfo(mixer->api,"%s: register mute control...", __func__);
+ AFB_ApiDebug(mixer->api,"%s: register mute control...", __func__);
// Registry stop/play as a pause/resume control
error = AlsaCtlRegister(mixer, captureCard, capturePcm, FONTEND_NUMID_PAUSE, pauseNumid);
@@ -314,10 +363,12 @@ STATIC int CreateOneStream(SoftMixerT *mixer, const char * uid, AlsaStreamAudioT
goto OnErrorExit;
}
- if (asprintf(&volName, "vol-%s", stream->uid) == -1)
+ if (asprintf(&volName, "vol-%s", stream->uid) == -1) {
+ SOFTMIXER_NOMEM(mixer->api);
goto OnErrorExit;
+ }
- AFB_ApiInfo(mixer->api,"%s: create softvol", __func__);
+ AFB_ApiDebug(mixer->api,"%s: create softvol", __func__);
// create stream and delay pcm opening until vol control is created
streamPcm = AlsaCreateSoftvol(mixer, stream, volSlaveId, captureCard, volName, VOL_CONTROL_MAX, 0);
@@ -326,7 +377,7 @@ STATIC int CreateOneStream(SoftMixerT *mixer, const char * uid, AlsaStreamAudioT
goto OnErrorExit;
}
- AFB_ApiInfo(mixer->api,"%s: create softvol control", __func__);
+ AFB_ApiDebug(mixer->api,"%s: create softvol control", __func__);
// create volume control before softvol pcm is opened
volNumid = AlsaCtlCreateControl(mixer,
@@ -345,19 +396,23 @@ 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)], zone [%d,%s(%d)])",
+ "%s: Instanciate a RATE CONVERTER (stream [%d,%s(%d),%d channels], zone [%d,%s(%d), %d channels])",
__func__,
stream->params->rate,
stream->params->formatS,
stream->params->format,
+ stream->params->channels,
zone->params->rate,
zone->params->formatS,
- zone->params->format);
+ zone->params->format,
+ zone->params->channels);
char *rateName;
- if (asprintf(&rateName, "rate-%s", stream->uid) == -1)
+ if (asprintf(&rateName, "rate-%s", stream->uid) == -1) {
+ SOFTMIXER_NOMEM(mixer->api);
goto OnErrorExit;
- streamPcm = AlsaCreateRate(mixer, rateName, streamPcm, zone->params, 0);
+ }
+ streamPcm = AlsaCreateRate(mixer, stream, rateName, streamPcm, zone->params, 0);
if (!streamPcm) {
AFB_ApiError(mixer->api, "%s: fail to create rate converter", __func__);
goto OnErrorExit;
@@ -368,7 +423,9 @@ STATIC int CreateOneStream(SoftMixerT *mixer, const char * uid, AlsaStreamAudioT
playbackName = (char*) streamPcm->cid.cardid;
}
- AFB_ApiInfo(mixer->api, "%s: Opening PCM PLAYBACK name %s", __func__, playbackName);
+ streamPcm->isPcmPlug = zone->isPcmPlug;
+
+ 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*/ );
@@ -379,13 +436,15 @@ STATIC int CreateOneStream(SoftMixerT *mixer, const char * uid, AlsaStreamAudioT
goto OnErrorExit;
}
+ streamPcm->closeAtDeletion = true;
+
// start stream pcm copy (at this both capturePcm & sink pcm should be open, we use output params to configure both in+outPCM)
- error = AlsaPcmCopy(mixer, stream, capturePcm, streamPcm, stream->params);
+ error = AlsaPcmCopyStart(mixer, stream, capturePcm, streamPcm, stream->params);
if (error) {
AFB_ApiError(mixer->api, "%s: Failed to launch copy", __func__);
goto OnErrorExit;
}
-
+ AFB_ApiDebug(mixer->api, "%s: register VOL ctrl", __func__);
error = AlsaCtlRegister(mixer, captureCard, capturePcm, FONTEND_NUMID_IGNORE, volNumid);
if (error) {
AFB_ApiError(mixer->api, "%s: register control on capture", __func__);
@@ -396,7 +455,8 @@ STATIC int CreateOneStream(SoftMixerT *mixer, const char * uid, AlsaStreamAudioT
if (loopDev && loopDev->numid) {
// retrieve active/pause control and set PCM status accordingly
error = AlsaCtlNumidGetLong(mixer, captureCard, loopDev->numid, &value);
- if (error) goto OnErrorExit;
+ if (error)
+ goto OnErrorExit;
// toggle pause/resume (should be done after pcm_start)
if ((error = snd_pcm_pause(capturePcm->handle, !value)) < 0) {
@@ -405,21 +465,33 @@ STATIC int CreateOneStream(SoftMixerT *mixer, const char * uid, AlsaStreamAudioT
}
if (loop) {
- if (asprintf((char**) &stream->source, "hw:%d,%d,%d", captureDev->cardidx, loop->playback, capturePcm->cid.subdev) == -1)
- goto OnErrorExit;
+ if (asprintf((char**) &stream->source, "hw:%d,%d,%d", captureDev->cardidx, loop->playback, capturePcm->cid.subdev) == -1) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto OnErrorExit;
+ }
+
} else {
- if (asprintf((char**) &stream->source, "hw:%d,%d,%d", captureDev->cardidx, captureDev->device, captureDev->subdev) == -1)
+ if (asprintf((char**) &stream->source, "hw:%d,%d,%d", captureDev->cardidx, captureDev->device, captureDev->subdev) == -1) {
+ SOFTMIXER_NOMEM(mixer->api);
goto OnErrorExit;
+ }
}
// create a dedicated verb for this stream
apiHandleT *apiHandle = calloc(1, sizeof (apiHandleT));
+ if (apiHandle == NULL) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto OnErrorExit;
+ }
apiHandle->mixer = mixer;
apiHandle->stream = stream;
apiHandle->sndcard = captureCard;
apiHandle->pcm = capturePcm->handle;
+ // keep a reference for future cleanup
+ stream->verbApiHandle = apiHandle;
+
// replace stream volume/mute values with corresponding ctl control
stream->volume = volNumid;
stream->mute = pauseNumid;
@@ -437,7 +509,7 @@ STATIC int CreateOneStream(SoftMixerT *mixer, const char * uid, AlsaStreamAudioT
//AlsaDumpPcmInfo(source, "\n\nPcm_config\n-----------\n", streamPcm->handle);
AFB_ApiNotice(mixer->api,
- "%s: mixer=%s stream=%s done",
+ "%s: mixer=%s stream=%s CREATED",
__func__, mixer->uid, stream->uid);
return 0;
@@ -450,34 +522,52 @@ OnErrorExit:
}
STATIC AlsaStreamAudioT * AttachOneStream(SoftMixerT *mixer, const char *uid, const char *prefix, json_object * streamJ) {
- AlsaStreamAudioT *stream = calloc(1, sizeof (AlsaStreamAudioT));
int error;
json_object *paramsJ = NULL;
+ AlsaStreamAudioT *stream = calloc(1, sizeof (AlsaStreamAudioT));
+ if (stream == NULL) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto OnErrorExit;
+ }
+
// Make sure default runs
stream->volume = ALSA_DEFAULT_PCM_VOLUME;
stream->mute = 0;
stream->info = NULL;
+ stream->delayms = SMIXER_DEFLT_DELAYMS;
- error = wrap_json_unpack(streamJ, "{ss,s?s,s?s,ss,s?s,s?i,s?b,s?o,s?s !}"
+ error = wrap_json_unpack(streamJ, "{ss,s?s,s?s,s?s,s?s,s?s,s?i,s?b,s?o,s?s,s?i !}"
, "uid", &stream->uid
, "verb", &stream->verb
, "info", &stream->info
, "zone", &stream->sink
+ , "playback", &stream->playback
, "source", &stream->source
, "volume", &stream->volume
, "mute", &stream->mute
, "params", &paramsJ
, "ramp", &stream->ramp
+ , "delayms", &stream->delayms
);
if (error) {
- AFB_ApiNotice(mixer->api,
+ AFB_ApiError(mixer->api,
"%s: hal=%s missing 'uid|[info]|zone|source||[volume]|[mute]|[params]' error=%s stream=%s",
__func__, uid, wrap_json_get_error_string(error), json_object_get_string(streamJ));
goto OnErrorExit;
}
+ if (!stream->sink && !stream->playback) {
+ AFB_ApiError(mixer->api, "%s: A stream must have a zone or a playback", __func__);
+ goto OnErrorExit;
+ }
+
+ if (stream->sink && stream->playback) {
+ AFB_ApiError(mixer->api, "%s: both a playback and a zone cannot be defined at the same time", __func__);
+ goto OnErrorExit;
+ }
+
stream->params = ApiPcmSetParams(mixer, stream->uid, paramsJ);
if (!stream->params) {
AFB_ApiError(mixer->api,
@@ -488,22 +578,54 @@ STATIC AlsaStreamAudioT * AttachOneStream(SoftMixerT *mixer, const char *uid, co
// make sure remain valid even when json object is removed
stream->uid = strdup(stream->uid);
- if (stream->sink)stream->sink = strdup(stream->sink);
- if (stream->source)stream->source = strdup(stream->source);
+ if (stream->uid == NULL) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto OnErrorExit;
+ }
+ if (stream->sink) {
+ stream->sink = strdup(stream->sink);
+ if (stream->sink == NULL) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto OnErrorExit;
+ }
+ }
+ if (stream->source) {
+ stream->source = strdup(stream->source);
+ if (stream->source == NULL) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto OnErrorExit;
+ }
+ }
+ if (stream->playback) {
+ stream->playback = strdup(stream->playback);
+ if (stream->playback == NULL) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto OnErrorExit;
+ }
+ }
// Prefix verb with uid|prefix
if (prefix) {
if (stream->verb) {
- if (asprintf((char**) &stream->verb, "%s#%s", prefix, stream->verb) == -1)
+ if (asprintf((char**) &stream->verb, "%s#%s", prefix, stream->verb) == -1) {
+ SOFTMIXER_NOMEM(mixer->api);
goto OnErrorExit;
+ }
}
else {
- if (asprintf((char**) &stream->verb, "%s#%s", prefix, stream->uid) == -1)
+ if (asprintf((char**) &stream->verb, "%s#%s", prefix, stream->uid) == -1) {
+ SOFTMIXER_NOMEM(mixer->api);
goto OnErrorExit;
+ }
}
} else {
- if (!stream->verb)
+ if (!stream->verb) {
stream->verb = strdup(stream->uid);
+ if (stream->verb == NULL) {
+ SOFTMIXER_NOMEM(mixer->api);
+ goto OnErrorExit;
+ }
+ }
}
// implement stream PCM with corresponding thread and controls
@@ -512,7 +634,6 @@ STATIC AlsaStreamAudioT * AttachOneStream(SoftMixerT *mixer, const char *uid, co
AFB_ApiError(mixer->api, "%s: failed to create stream", __func__);
goto OnErrorExit;
}
-
return stream;
OnErrorExit:
@@ -521,55 +642,109 @@ OnErrorExit:
return NULL;
}
-PUBLIC int ApiStreamAttach(SoftMixerT *mixer, AFB_ReqT request, const char *uid, const char *prefix, json_object * argsJ) {
+static void streamDestroy(SoftMixerT * mixer, void * arg) {
+ AlsaStreamAudioT * stream = (AlsaStreamAudioT*) arg;
+ int error = 0;
+ AFB_ApiDebug(mixer->api, "%s... %s", __func__, stream->uid);
- AFB_ApiInfo(mixer->api, "%s: %s prefix %s", __func__, uid, prefix);
-
- if (!mixer->loops) {
- AFB_ApiError(mixer->api, "%s: mixer=%s No Loop found [should Registry snd_loop first]", __func__, mixer->uid);
- goto OnErrorExit;
+ error = afb_api_del_verb(mixer->api, stream->uid, (void**)stream->verbApiHandle);
+ if (error) {
+ AFB_ApiDebug(mixer->api, "%s: failed to remove verb %s", __func__, stream->uid);
}
- int index;
- for (index = 0; index < mixer->max.streams; index++) {
- if (!mixer->streams[index]) break;
+ AlsaPcmCopyStop(mixer, stream->copy);
+
+ if (stream->softvolConfig) {
+ AFB_ApiDebug(mixer->api, "%s... %s delete softvol config", __func__, stream->uid);
+ snd_config_delete(stream->softvolConfig);
+ snd_config_update();
+ stream->softvolConfig = NULL;
+ }
+
+ if (stream->rateConfig) {
+ AFB_ApiDebug(mixer->api, "%s... %s delete rate config", __func__, stream->uid);
+ snd_config_delete(stream->rateConfig);
+ snd_config_update();
+ stream->rateConfig = NULL;
+ }
+
+ free((char*)stream->uid);
+ free((char*)stream->playback);
+ free((char*)stream->ramp);
+ free((char*)stream->sink);
+ free((char*)stream->source);
+ free((char*)stream->verb);
+
+ ApiPcmDelParams(mixer, stream->params);
+
+ cds_list_del(&stream->list);
+ mixer->nbStreams--;
+
+ free(stream);
+ // uid is no available anymore at this position
+ AFB_ApiDebug(mixer->api, "%s... DONE !", __func__);
+}
+
+static AlsaStreamAudioT * streamCreate(SoftMixerT * mixer, const char * uid, const char * prefix, json_object * argsJ) {
+ AlsaStreamAudioT * newStream = AttachOneStream(mixer, uid, prefix, argsJ);
+ if (!newStream) {
+ goto fail;
+ }
+ mixer->nbStreams++;
+ cds_list_add_tail(&newStream->list, &mixer->streams.list);
+
+ AlsaMixerTransactionObjectAdd(mixer->transaction, newStream, streamDestroy);
+fail:
+ return newStream;
+}
+
+PUBLIC int ApiStreamAttach(SoftMixerT *mixer, AFB_ReqT request, const char * uid, const char *prefix, json_object * argsJ) {
+
+ AFB_ApiDebug(mixer->api, "%s: %s prefix %s", __func__, uid, prefix);
+
+ AlsaStreamAudioT * newStream = NULL;
+
+ if (mixer->nbLoops == 0) {
+ AFB_ApiError(mixer->api, "%s: mixer=%s No Loop found [should Registry snd_loop first]", __func__, mixer->uid);
+ goto fail;
}
- if (index == mixer->max.streams) {
- AFB_ReqFailF(request, "too-small", "mixer=%s max stream=%d", mixer->uid, mixer->max.streams);
- goto OnErrorExit;
+ if (mixer->nbStreams >= mixer->max.streams) {
+ AFB_ReqFailF(request, "too-small", "mixer=%s max stream=%d", mixer->uid, mixer->max.streams);
+ goto fail;
}
switch (json_object_get_type(argsJ)) {
long count;
case json_type_object:
- mixer->streams[index] = AttachOneStream(mixer, uid, prefix, argsJ);
- if (!mixer->streams[index]) {
+ newStream = streamCreate(mixer, uid, prefix, argsJ);
+ if (!newStream) {
AFB_ReqFailF(request, "bad-stream", "mixer=%s invalid stream= %s", mixer->uid, json_object_get_string(argsJ));
- goto OnErrorExit;
+ goto fail;
}
+
break;
case json_type_array:
count = json_object_array_length(argsJ);
- if (count > (mixer->max.streams - index)) {
+ if (count > (mixer->max.streams - mixer->nbStreams)) {
AFB_ReqFailF(request,
"too-small",
"mixer=%s max stream=%d", mixer->uid, mixer->max.streams);
- goto OnErrorExit;
+ goto fail;
}
for (int idx = 0; idx < count; idx++) {
json_object *streamJ = json_object_array_get_idx(argsJ, idx);
- mixer->streams[index + idx] = AttachOneStream(mixer, uid, prefix, streamJ);
- if (!mixer->streams[index + idx]) {
+ newStream = streamCreate(mixer, uid, prefix, streamJ);
+ if (!newStream) {
AFB_ReqFailF(request,
"bad-stream",
"%s: mixer=%s invalid stream= %s",
__func__, mixer->uid, json_object_get_string(streamJ));
- goto OnErrorExit;
+ goto fail;
}
}
break;
@@ -577,12 +752,12 @@ PUBLIC int ApiStreamAttach(SoftMixerT *mixer, AFB_ReqT request, const char *uid,
AFB_ReqFailF(request,
"invalid-syntax",
"mixer=%s streams invalid argsJ= %s", mixer->uid, json_object_get_string(argsJ));
- goto OnErrorExit;
+ goto fail;
}
return 0;
-OnErrorExit:
+fail:
AFB_ApiError(mixer->api, "%s FAILED\n", __func__);
return -1;
}