diff options
author | Fulup Ar Foll <fulup@iot.bzh> | 2018-05-18 17:08:24 +0200 |
---|---|---|
committer | Fulup Ar Foll <fulup@iot.bzh> | 2018-05-18 17:08:24 +0200 |
commit | a2ea0dd94d803ee8e5eb79c6494f0d4c76cbcc90 (patch) | |
tree | 3af0d287681113e4155a679c5eac1e9cd410e822 | |
parent | 7454d66bb47349418f8f65b8d7bec79039a2be32 (diff) |
Added create/close mixer API
-rw-r--r-- | conf.d/project/etc/4a-softmixer-test.json | 44 | ||||
-rw-r--r-- | conf.d/project/htdocs/index.html | 175 | ||||
-rw-r--r-- | plugins/alsa/alsa-api-frontend.c | 18 | ||||
-rw-r--r-- | plugins/alsa/alsa-api-mixer.c | 123 | ||||
-rw-r--r-- | plugins/alsa/alsa-api-streams.c | 52 |
5 files changed, 281 insertions, 131 deletions
diff --git a/conf.d/project/etc/4a-softmixer-test.json b/conf.d/project/etc/4a-softmixer-test.json index f363a55..d646e3b 100644 --- a/conf.d/project/etc/4a-softmixer-test.json +++ b/conf.d/project/etc/4a-softmixer-test.json @@ -28,48 +28,8 @@ ], "controls": [ { - "uid": "new", - "action": "plugin://softmixer#_mixer_new_", - "args": { - "devices": { - "playback": 0, - "capture": 1 - }, - "subdevs": [ - { - "subdev": 0, - "numid": 51 - }, - { - "subdev": 1, - "numid": 57 - }, - { - "subdev": 2, - "numid": 63 - }, - { - "subdev": 3, - "numid": 69 - }, - { - "subdev": 4, - "numid": 75 - }, - { - "subdev": 5, - "numid": 81 - }, - { - "subdev": 6, - "numid": 87 - }, - { - "subdev": 7, - "numid": 93 - } - ] - } + "uid": "create", + "action": "plugin://softmixer#mixer_new" } ] } diff --git a/conf.d/project/htdocs/index.html b/conf.d/project/htdocs/index.html index 67a4a26..3b2b4ad 100644 --- a/conf.d/project/htdocs/index.html +++ b/conf.d/project/htdocs/index.html @@ -1,36 +1,157 @@ <html> -<head> - <title>Simple COntroller Test</title> - <link rel="stylesheet" href="AudioBinding.css"> - <script type="text/javascript" src="AFB-websock.js"></script> - <script type="text/javascript" src="AudioBinding.js"></script> -</head> - -<body onload="init('hal_registry','alsacore', 'hallist')"> - - <h1>Simple Mixer Test</h1> - <button id="connected" onclick="init()">Binder WS Fail</button> - <button id="mnitoring" onclick="window.open('/monitoring/monitor.html','_monitor_ctl')">Debug/Monitoring</a></button> + <head> + <title>Simple COntroller Test</title> + <link rel="stylesheet" href="AudioBinding.css"> + <script type="text/javascript" src="AFB-websock.js"></script> + <script type="text/javascript" src="AudioBinding.js"></script> + <script type="text/javascript"> + + var frontend = { + "devices": { + "playback": 0, + "capture": 1 + }, + "ramps": [ + { + "uid": "ramp-fast", + "delay": 50, + "up": 10, + "down": 3 + }, + { + "uid": "ramp-slow", + "delay": 250, + "up": 3, + "down": 1 + }, + { + "uid": "ramp-normal", + "delay": 100, + "up": 6, + "down": 2 + } + ], + "subdevs": [ + { + "subdev": 0, + "numid": 51 + }, + { + "subdev": 1, + "numid": 57 + }, + { + "subdev": 2, + "numid": 63 + }, + { + "subdev": 3, + "numid": 69 + }, + { + "subdev": 4, + "numid": 75 + }, + { + "subdev": 5, + "numid": 81 + }, + { + "subdev": 6, + "numid": 87 + }, + { + "subdev": 7, + "numid": 93 + } + ] + }; + var audio_defaults = { + "rate": 48000 + }; + var usb_yamaha = { + uid: "YAMAHA-APU70", + devpath: "/dev/snd/by-id/usb-YAMAHA_Corporation_YAMAHA_AP-U70_USB_Audio_00-00", + params: snd_params, + sink: [ + {uid: "front-right", port: 0}, + {uid: "front-left", port: 1} + ] + }; + var zone_front = { + uid: "front-seats", + type: "playback", + mapping: [ + {target: "front-right", channel: 0}, + {target: "front-left", channel: 1} + ] + }; + + var stream_music = { + uid: "multimedia", + zone: "front-seats", + ramp: "ramp-slow", + volume: 60, + mute: false + }; + + var stream_navigation = { + uid: "navigation", + zone: "front-seats", + ramp: "ramp-normal", + volume: 70, + mute: false + }; + + var stream_emergency = { + uid: "emergency", + zone: "front-seats", + ramp: "ramp-fast", + volume: 80, + mute: false + }; + + var my_test_mixer = { + uid: 'simple_mixer', + backend: usb_yamaha, + frontend: frontend, + zones: zone_front, + streams: [stream_music, stream_navigation, stream_emergency] + }; + + </script> + + </head> + + <body onload="init('hal_registry', 'alsacore', 'hallist')"> + + <h1>Simple Mixer Test</h1> + <button id="connected" onclick="init()">Binder WS Fail</button> + <button id="mnitoring" onclick="window.open('/monitoring/monitor.html', '_monitor_ctl')">Debug/Monitoring</a></button> <br><br> <h2>V3 API CALL</h2> <ol> - <li><button onclick="callbinder('softmixer','simple_mixer',{list:{streams:true}});">Streams List</button></li> - <br> - <li><button onclick="callbinder('softmixer','simple_mixer/multimedia',{toggle: true});">Stream Multimedia pause/resume</button></li> - <li><button onclick="callbinder('softmixer','simple_mixer/navigation',{toggle: true});">Stream Navigation pause/resume</button></li> - <br> - <li><button onclick="callbinder('softmixer','simple_mixer/multimedia',{volume: '+10'});">Stream Multimedia volume=+10"</button></li> - <li><button onclick="callbinder('softmixer','simple_mixer/multimedia',{volume: '-10'});">Stream Multimedia volume=-10"</button></li> - <br> - <li><button onclick="callbinder('softmixer','simple_mixer/multimedia',{ramp: 30});">Stream Multimedia ramp=30"</button></li> - <li><button onclick="callbinder('softmixer','simple_mixer/multimedia',{ramp: 80});">Stream Multimedia ramp=80"</button></li> + <li><button onclick="callbinder('softmixer', 'simple_mixer', {list: {streams: true}});">Streams List</button></li> + <br> + <li><button onclick="callbinder('softmixer', 'simple_mixer/multimedia', {toggle: true});">Stream Multimedia pause/resume</button></li> + <li><button onclick="callbinder('softmixer', 'simple_mixer/navigation', {toggle: true});">Stream Navigation pause/resume</button></li> + <br> + <li><button onclick="callbinder('softmixer', 'simple_mixer/multimedia', {volume: '+10'});">Stream Multimedia volume=+10"</button></li> + <li><button onclick="callbinder('softmixer', 'simple_mixer/multimedia', {volume: '-10'});">Stream Multimedia volume=-10"</button></li> + <br> + <li><button onclick="callbinder('softmixer', 'simple_mixer/multimedia', {ramp: 30});">Stream Multimedia ramp=30"</button></li> + <li><button onclick="callbinder('softmixer', 'simple_mixer/multimedia', {ramp: 80});">Stream Multimedia ramp=80"</button></li> + <br> + <li><button onclick="callbinder('softmixer', 'simple_mixer', {delete: true});">Close Mixer"</button></li> + <li><button onclick="callbinder('softmixer', 'create',my_test_mixer = {uid:'simple_mixer', backend: usb_yamaha, frontend: frontend, + zones: [zone_front],streams: [stream_music, stream_navigation, stream_emergency]});">New Mixer"</button></li> </ol> <div id="main" style="visibility:hidden"> - <ol> - <li>Question <pre id="question"></pre> - <li>Response <pre id="output"></pre> - <li>Events: <pre id="outevt"></pre> - </ol> + <ol> + <li>Question <pre id="question"></pre> + <li>Response <pre id="output"></pre> + <li>Events: <pre id="outevt"></pre> + </ol> </div> diff --git a/plugins/alsa/alsa-api-frontend.c b/plugins/alsa/alsa-api-frontend.c index d39c92e..11b8a7e 100644 --- a/plugins/alsa/alsa-api-frontend.c +++ b/plugins/alsa/alsa-api-frontend.c @@ -203,24 +203,24 @@ OnErrorExit: } PUBLIC int SndFrontend(CtlSourceT *source, json_object *argsJ) { - SoftMixerHandleT *mixerHandle = (SoftMixerHandleT*) source->context; + SoftMixerHandleT *mixer = (SoftMixerHandleT*) source->context; int error; - assert(mixerHandle); + assert(mixer); - if (mixerHandle->frontend) { - AFB_ApiError(source->api, "SndFrontend: mixer=%s SndFrontend already declared %s", mixerHandle->uid, json_object_get_string(argsJ)); + if (mixer->frontend) { + AFB_ApiError(source->api, "SndFrontend: mixer=%s SndFrontend already declared %s", mixer->uid, json_object_get_string(argsJ)); goto OnErrorExit; } - mixerHandle->frontend = calloc(1, sizeof (AlsaSndLoopT)); + mixer->frontend = calloc(1, sizeof (AlsaSndLoopT)); // or syntax purpose array is accepted but frontend should have a single driver entry json_type type = json_object_get_type(argsJ); if (type == json_type_array) { size_t count = json_object_array_length(argsJ); if (count != 1) { - AFB_ApiError(source->api, "SndFrontend: mixer=%s frontend only support on input driver args=%s", mixerHandle->uid, json_object_get_string(argsJ)); + AFB_ApiError(source->api, "SndFrontend: mixer=%s frontend only support on input driver args=%s", mixer->uid, json_object_get_string(argsJ)); goto OnErrorExit; } argsJ = json_object_array_get_idx(argsJ, 0); @@ -228,13 +228,13 @@ PUBLIC int SndFrontend(CtlSourceT *source, json_object *argsJ) { type = json_object_get_type(argsJ); if (type != json_type_object) { - AFB_ApiError(source->api, "SndFrontend: mixer=%s invalid object type= %s", mixerHandle->uid, json_object_get_string(argsJ)); + AFB_ApiError(source->api, "SndFrontend: mixer=%s invalid object type= %s", mixer->uid, json_object_get_string(argsJ)); goto OnErrorExit; } - error = ProcessOneLoop(source, argsJ, mixerHandle->frontend); + error = ProcessOneLoop(source, argsJ, mixer->frontend); if (error) { - AFB_ApiError(source->api, "SndFrontend: mixer=%s invalid object= %s", mixerHandle->uid, json_object_get_string(argsJ)); + AFB_ApiError(source->api, "SndFrontend: mixer=%s invalid object= %s", mixer->uid, json_object_get_string(argsJ)); goto OnErrorExit; } diff --git a/plugins/alsa/alsa-api-mixer.c b/plugins/alsa/alsa-api-mixer.c index db5f129..b910b9f 100644 --- a/plugins/alsa/alsa-api-mixer.c +++ b/plugins/alsa/alsa-api-mixer.c @@ -20,6 +20,8 @@ #include "alsa-softmixer.h" #include <string.h> +#include <pthread.h> + // Fulup need to be cleanup with new controller version extern Lua2cWrapperT Lua2cWrap; @@ -32,18 +34,18 @@ static void MixerApiVerbCB(AFB_ReqT request) { json_object *argsJ = afb_request_json(request); json_object *responseJ = json_object_new_object(); - SoftMixerHandleT *mixerHandle = (SoftMixerHandleT*) afb_request_get_vcbdata(request); + SoftMixerHandleT *mixer = (SoftMixerHandleT*) afb_request_get_vcbdata(request); int error; - int close = 0; + int delete = 0; CtlSourceT *source = alloca(sizeof (CtlSourceT)); - source->uid = mixerHandle->uid; + source->uid = mixer->uid; source->api = request->dynapi; source->request = request; - source->context = mixerHandle; + source->context = mixer; error = wrap_json_unpack(argsJ, "{s?b,s?o,s?o,s?o,s?o,s?o !}" - , "close", &close + , "delete", &delete , "list", &listJ , "backend", &backendJ , "frontend", &frontendJ @@ -51,14 +53,57 @@ static void MixerApiVerbCB(AFB_ReqT request) { , "streams", &streamsJ ); if (error) { - AFB_ReqFailF(request, "invalid syntax", "request missing 'uid|list|backend|frontend|zones|streams' mixer=%s", json_object_get_string(argsJ)); + AFB_ReqFailF(request, "invalid-syntax", "request missing 'uid|list|backend|frontend|zones|streams' mixer=%s", json_object_get_string(argsJ)); goto OnErrorExit; } // Free attached resources and free mixer - if (close) { - AFB_ReqFailF(request, "not implemented", "(Fulup) Close action still to be done mixer=%s", json_object_get_string(argsJ)); - goto OnErrorExit; + if (delete) { + for (int idx; mixer->streams[idx].uid; idx++) { + AlsaLoopStreamT *stream = &mixer->streams[idx]; + + AFB_ApiNotice(source->api, "cleaning mixer=%s stream=%s", mixer->uid, stream->uid); + + error = pthread_cancel(stream->copy.thread); + if (error) { + AFB_ReqFailF(request, "internal-error", "Fail to kill audio-stream threads mixer=%s", mixer->uid); + goto OnErrorExit; + } + + char apiStreamVerb[128]; + error = snprintf(apiStreamVerb, sizeof (apiStreamVerb), "%s/%s", mixer->uid, stream->uid); + if (error == sizeof (apiStreamVerb)) { + AFB_ApiError(source->api, "LoopStreams mixer=%s fail to Registry Stream API too long %s/%s", mixer->uid, mixer->uid, stream->uid); + goto OnErrorExit; + } + + error = afb_dynapi_sub_verb(source->api, apiStreamVerb); + if (error) { + AFB_ApiError(source->api, "fail to Clean API verb=%s", apiStreamVerb); + goto OnErrorExit; + } + + // free audio-stream dynamic structures + snd_pcm_close(mixer->streams[idx].copy.pcmIn); + snd_pcm_close(mixer->streams[idx].copy.pcmOut); + if (stream->copy.evtsrc) sd_event_source_unref(stream->copy.evtsrc); + if (stream->copy.sdLoop) sd_event_unref(stream->copy.sdLoop); + + } + + // registry is attached to frontend + if (mixer->frontend->registry)free(mixer->frontend->registry); + + error = afb_dynapi_sub_verb(source->api, mixer->uid); + if (error) { + AFB_ApiError(source->api, "fail to Clean API verb=%s", mixer->uid); + goto OnErrorExit; + } + + // finally free mixer handle + free(mixer); + responseJ = json_object_new_string("Fulup: delete might not clean everything properly"); + goto OnSuccessExit; } if (listJ) { @@ -72,14 +117,14 @@ static void MixerApiVerbCB(AFB_ReqT request) { , "zones", &zones ); if (error) { - AFB_ReqFailF(request, "invalid syntax", "list missing 'uid|backend|frontend|zones|streams' list=%s", json_object_get_string(listJ)); + AFB_ReqFailF(request, "invalid-syntax", "list missing 'uid|backend|frontend|zones|streams' list=%s", json_object_get_string(listJ)); goto OnErrorExit; } if (streams) { streamsJ = json_object_new_array(); - AlsaLoopStreamT *streams = mixerHandle->streams; + AlsaLoopStreamT *streams = mixer->streams; for (int idx = 0; streams[idx].uid; idx++) { if (quiet) { json_object_array_add(streamsJ, json_object_new_string(streams[idx].uid)); @@ -87,20 +132,20 @@ static void MixerApiVerbCB(AFB_ReqT request) { json_object *numidJ; wrap_json_pack(&numidJ, "{si,si}" , "volume", streams[idx].volume - , "mute", streams[idx].mute + , "mute", streams[idx].mute ); wrap_json_pack(&valueJ, "{ss,so}" , "uid", streams[idx].uid , "numid", numidJ ); json_object_array_add(streamsJ, valueJ); - AFB_ApiWarning (request->dynapi, "stream=%s", json_object_get_string(streamsJ)); + AFB_ApiWarning(request->dynapi, "stream=%s", json_object_get_string(streamsJ)); } - + } json_object_object_add(responseJ, "streams", streamsJ); } - + if (backend || frontend || zones) { AFB_ReqFailF(request, "not implemented", "(Fulup) list action Still To Be Done"); goto OnErrorExit; @@ -109,7 +154,7 @@ static void MixerApiVerbCB(AFB_ReqT request) { AFB_ReqSucess(request, responseJ, NULL); return; } - + if (backendJ) { error = SndBackend(source, backendJ); if (error) goto OnErrorExit; @@ -130,8 +175,8 @@ static void MixerApiVerbCB(AFB_ReqT request) { if (error) goto OnErrorExit; } - - AFB_ReqSucess(request, responseJ, mixerHandle->uid); +OnSuccessExit: + AFB_ReqSucess(request, responseJ, mixer->uid); return; OnErrorExit: @@ -139,7 +184,7 @@ OnErrorExit: } CTLP_LUA2C(_mixer_new_, source, argsJ, responseJ) { - SoftMixerHandleT *mixerHandle = calloc(1, sizeof (SoftMixerHandleT)); + SoftMixerHandleT *mixer = calloc(1, sizeof (SoftMixerHandleT)); json_object *backendJ = NULL, *frontendJ = NULL, *zonesJ = NULL, *streamsJ = NULL; int error; assert(source->api); @@ -150,8 +195,8 @@ CTLP_LUA2C(_mixer_new_, source, argsJ, responseJ) { } error = wrap_json_unpack(argsJ, "{ss,s?s,s?o,s?o,s?o,s?o !}" - , "uid", &mixerHandle->uid - , "info", &mixerHandle->info + , "uid", &mixer->uid + , "info", &mixer->info , "backend", &backendJ , "frontend", &frontendJ , "zones", &zonesJ @@ -162,18 +207,18 @@ CTLP_LUA2C(_mixer_new_, source, argsJ, responseJ) { } // make sure string do not get deleted - mixerHandle->uid = strdup(mixerHandle->uid); - if (mixerHandle->info)mixerHandle->info = strdup(mixerHandle->info); + mixer->uid = strdup(mixer->uid); + if (mixer->info)mixer->info = strdup(mixer->info); // create mixer verb within API. - error = afb_dynapi_add_verb(source->api, mixerHandle->uid, mixerHandle->info, MixerApiVerbCB, mixerHandle, NULL, 0); + error = afb_dynapi_add_verb(source->api, mixer->uid, mixer->info, MixerApiVerbCB, mixer, NULL, 0); if (error) { - AFB_ApiError(source->api, "_mixer_new_ mixer=%s fail to Registry API verb", mixerHandle->uid); + AFB_ApiError(source->api, "_mixer_new_ mixer=%s fail to Registry API verb", mixer->uid); return -1; } // make sure sub command get access to mixer handle - source->context = mixerHandle; + source->context = mixer; if (backendJ) { error = SndBackend(source, backendJ); @@ -199,4 +244,28 @@ CTLP_LUA2C(_mixer_new_, source, argsJ, responseJ) { OnErrorExit: return -1; -}
\ No newline at end of file +} + +// provide a similar command but for API + +CTLP_CAPI(mixer_new, source, argsJ, queryJ) { + json_object * responseJ; + + // merge static config args with dynamic one coming from the request + if (argsJ && json_object_get_type(argsJ) == json_type_object) { + + json_object_object_foreach(argsJ, key, val) { + json_object_get(val); + json_object_object_add(queryJ, key, val); + } + } + + int error = _mixer_new_(source, queryJ, &responseJ); + + if (error) + AFB_ReqFailF(source->request, "fail-create", "invalid arguments"); + else + AFB_ReqSucess(source->request, responseJ, NULL); + + return error; +} diff --git a/plugins/alsa/alsa-api-streams.c b/plugins/alsa/alsa-api-streams.c index 56d3cf8..3923048 100644 --- a/plugins/alsa/alsa-api-streams.c +++ b/plugins/alsa/alsa-api-streams.c @@ -221,18 +221,18 @@ OnErrorExit: } PUBLIC int LoopStreams(CtlSourceT *source, json_object *argsJ, json_object **responseJ) { - SoftMixerHandleT *mixerHandle = (SoftMixerHandleT*) source->context; + SoftMixerHandleT *mixer = (SoftMixerHandleT*) source->context; AlsaLoopStreamT *loopStream; int error; long value; size_t count; - assert(mixerHandle); + assert(mixer); // assert static/global softmixer handle get requited info - AlsaSndLoopT *ctlLoop = mixerHandle->frontend; + AlsaSndLoopT *ctlLoop = mixer->frontend; if (!ctlLoop) { - AFB_ApiError(source->api, "LoopStreams: mixer=%s No Loop found [should Registry snd_loop first]", mixerHandle->uid); + AFB_ApiError(source->api, "LoopStreams: mixer=%s No Loop found [should Registry snd_loop first]", mixer->uid); goto OnErrorExit; } @@ -242,7 +242,7 @@ PUBLIC int LoopStreams(CtlSourceT *source, json_object *argsJ, json_object **res loopStream = calloc(count + 1, sizeof (AlsaLoopStreamT)); error = ProcessOneStream(source, argsJ, &loopStream[0]); if (error) { - AFB_ApiError(source->api, "LoopStreams: mixer=%s invalid stream= %s", mixerHandle->uid, json_object_get_string(argsJ)); + AFB_ApiError(source->api, "LoopStreams: mixer=%s invalid stream= %s", mixer->uid, json_object_get_string(argsJ)); goto OnErrorExit; } break; @@ -254,13 +254,13 @@ PUBLIC int LoopStreams(CtlSourceT *source, json_object *argsJ, json_object **res json_object *loopStreamJ = json_object_array_get_idx(argsJ, idx); error = ProcessOneStream(source, loopStreamJ, &loopStream[idx]); if (error) { - AFB_ApiError(source->api, "loopstreams: mixer=%s invalid stream= %s", mixerHandle->uid, json_object_get_string(loopStreamJ)); + AFB_ApiError(source->api, "loopstreams: mixer=%s invalid stream= %s", mixer->uid, json_object_get_string(loopStreamJ)); goto OnErrorExit; } } break; default: - AFB_ApiError(source->api, "LoopStreams: mixer=%s invalid argsJ= %s", mixerHandle->uid, json_object_get_string(argsJ)); + AFB_ApiError(source->api, "LoopStreams: mixer=%s invalid argsJ= %s", mixer->uid, json_object_get_string(argsJ)); goto OnErrorExit; } @@ -272,10 +272,10 @@ PUBLIC int LoopStreams(CtlSourceT *source, json_object *argsJ, json_object **res json_object *streamJ, *paramsJ; // Search for a free loop capture device - AFB_ApiNotice(source->api, "LoopStreams: mixer=%s stream=%s Start", mixerHandle->uid, (char*) loopStream[idx].uid); + AFB_ApiNotice(source->api, "LoopStreams: mixer=%s stream=%s Start", mixer->uid, (char*) loopStream[idx].uid); ctlLoop->scount--; if (ctlLoop->scount < 0) { - AFB_ApiError(source->api, "LoopStreams: mixer=%s stream=%s no more subdev avaliable in loopback=%s", mixerHandle->uid, loopStream[idx].uid, ctlLoop->uid); + AFB_ApiError(source->api, "LoopStreams: mixer=%s stream=%s no more subdev avaliable in loopback=%s", mixer->uid, loopStream[idx].uid, ctlLoop->uid); goto OnErrorExit; } @@ -293,14 +293,14 @@ PUBLIC int LoopStreams(CtlSourceT *source, json_object *argsJ, json_object **res // Registry capture PCM for active/pause event if (captureDev->numid) { - error = AlsaCtlRegister(source, mixerHandle, captureDev, FONTEND_NUMID_RUN, captureDev->numid); + error = AlsaCtlRegister(source, mixer, captureDev, FONTEND_NUMID_RUN, captureDev->numid); if (error) goto OnErrorExit; } // Try to create/setup volume control. snd_ctl_t* ctlDev = AlsaCrlFromPcm(source, captureDev->handle); if (!ctlDev) { - AFB_ApiError(source->api, "LoopStreams: mixer=%s [pcm=%s] fail attache sndcard", mixerHandle->uid, captureDev->cardid); + AFB_ApiError(source->api, "LoopStreams: mixer=%s [pcm=%s] fail attache sndcard", mixer->uid, captureDev->cardid); goto OnErrorExit; } @@ -313,7 +313,7 @@ PUBLIC int LoopStreams(CtlSourceT *source, json_object *argsJ, json_object **res if (pauseNumid <= 0) goto OnErrorExit; // Registry mute/unmute as a pause/resume control - error = AlsaCtlRegister(source, mixerHandle, captureDev, FONTEND_NUMID_PAUSE, pauseNumid); + error = AlsaCtlRegister(source, mixer, captureDev, FONTEND_NUMID_PAUSE, pauseNumid); if (error) goto OnErrorExit; // create stream and delay pcm openning until vol control is created @@ -321,7 +321,7 @@ PUBLIC int LoopStreams(CtlSourceT *source, json_object *argsJ, json_object **res snprintf(volName, sizeof (volName), "vol-%s", loopStream[idx].uid); AlsaPcmInfoT *streamPcm = AlsaCreateSoftvol(source, &loopStream[idx], captureDev, volName, VOL_CONTROL_MAX, 0); if (!streamPcm) { - AFB_ApiError(source->api, "LoopStreams: mixer=%s%s(pcm) fail to create stream", mixerHandle->uid, loopStream[idx].uid); + AFB_ApiError(source->api, "LoopStreams: mixer=%s%s(pcm) fail to create stream", mixer->uid, loopStream[idx].uid); goto OnErrorExit; } @@ -342,7 +342,7 @@ PUBLIC int LoopStreams(CtlSourceT *source, json_object *argsJ, json_object **res // everything is not ready to open capture pcm error = snd_pcm_open(&streamPcm->handle, loopStream[idx].uid, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); if (error) { - AFB_ApiError(source->api, "LoopStreams: mixer=%s%s(pcm) fail to open capture", mixerHandle->uid, loopStream[idx].uid); + AFB_ApiError(source->api, "LoopStreams: mixer=%s%s(pcm) fail to open capture", mixer->uid, loopStream[idx].uid); goto OnErrorExit; } @@ -354,7 +354,7 @@ PUBLIC int LoopStreams(CtlSourceT *source, json_object *argsJ, json_object **res error = AlsaPcmCopy(source, &loopStream[idx], captureDev, streamPcm, &streamPcm->params); if (error) goto OnErrorExit; - error = AlsaCtlRegister(source, mixerHandle, captureDev, FONTEND_NUMID_IGNORE, volNumid); + error = AlsaCtlRegister(source, mixer, captureDev, FONTEND_NUMID_IGNORE, volNumid); if (error) goto OnErrorExit; // retrieve active/pause control and set PCM status accordingly @@ -363,7 +363,7 @@ PUBLIC int LoopStreams(CtlSourceT *source, json_object *argsJ, json_object **res // toggle pause/resume (should be done after pcm_start) if ((error = snd_pcm_pause(captureDev->handle, !value)) < 0) { - AFB_ApiWarning(source->api, "LoopStreams: mixer=%s [capture=%s] fail to pause error=%s", mixerHandle->uid, captureDev->cardid, snd_strerror(error)); + AFB_ApiWarning(source->api, "LoopStreams: mixer=%s [capture=%s] fail to pause error=%s", mixer->uid, captureDev->cardid, snd_strerror(error)); } // prepare response for application @@ -374,35 +374,35 @@ PUBLIC int LoopStreams(CtlSourceT *source, json_object *argsJ, json_object **res error += wrap_json_pack(&streamJ, "{ss ss si si so}", "uid", streamPcm->uid, "alsa", playbackDev->cardid, "volid", volNumid, "runid", pauseNumid, "params", paramsJ); error += json_object_array_add(*responseJ, streamJ); if (error) { - AFB_ApiError(source->api, "LoopStreams: mixer=%s stream=%s fail to prepare response", mixerHandle->uid, captureDev->cardid); + AFB_ApiError(source->api, "LoopStreams: mixer=%s stream=%s fail to prepare response", mixer->uid, captureDev->cardid); goto OnErrorExit; } // create a dedicated verb for this stream compose of mixeruid/streamuid apiHandleT *apiHandle = calloc(1, sizeof (apiHandleT)); char apiVerb[128]; - error = snprintf(apiVerb, sizeof (apiVerb), "%s/%s", mixerHandle->uid, loopStream[idx].uid); + error = snprintf(apiVerb, sizeof (apiVerb), "%s/%s", mixer->uid, loopStream[idx].uid); if (error == sizeof (apiVerb)) { - AFB_ApiError(source->api, "LoopStreams mixer=%s fail to Registry Stream API too long %s/%s", mixerHandle->uid, mixerHandle->uid, loopStream[idx].uid); - return -1; + AFB_ApiError(source->api, "LoopStreams mixer=%s fail to Registry Stream API too long %s/%s", mixer->uid, mixer->uid, loopStream[idx].uid); + goto OnErrorExit; } // if set get stream attached volramp if (loopStream->ramp) { apiHandle->ramp = RampGetByUid(source, ctlLoop->ramps, loopStream->ramp); if (!apiHandle->ramp) { - AFB_ApiError(source->api, "LoopStreams: mixer=%s%s(pcm) fail to find ramp=%s", mixerHandle->uid, loopStream[idx].uid, loopStream->ramp); + AFB_ApiError(source->api, "LoopStreams: mixer=%s%s(pcm) fail to find ramp=%s", mixer->uid, loopStream[idx].uid, loopStream->ramp); goto OnErrorExit; } } - apiHandle->mixer = mixerHandle; + apiHandle->mixer = mixer; apiHandle->stream= &loopStream[idx]; apiHandle->verb = strdup(apiVerb); error = afb_dynapi_add_verb(source->api, apiHandle->verb, loopStream[idx].info, StreamApiVerbCB, apiHandle, NULL, 0); if (error) { - AFB_ApiError(source->api, "LoopStreams mixer=%s fail to Registry API verb=%s", mixerHandle->uid, apiHandle->verb); - return -1; + AFB_ApiError(source->api, "LoopStreams mixer=%s fail to Registry API verb=%s", mixer->uid, apiHandle->verb); + goto OnErrorExit; } // free temporary resources @@ -414,11 +414,11 @@ PUBLIC int LoopStreams(CtlSourceT *source, json_object *argsJ, json_object **res //AlsaDumpElemConfig (source, "\n\nAlsa_Config\n------------\n", "pcm"); //AlsaDumpPcmInfo(source, "\n\nPcm_config\n-----------\n", streamPcm->handle); - AFB_ApiNotice(source->api, "LoopStreams: mixer=%s stream=%s OK reponse=%s\n", mixerHandle->uid, streamPcm->uid, json_object_get_string(streamJ)); + AFB_ApiNotice(source->api, "LoopStreams: mixer=%s stream=%s OK reponse=%s\n", mixer->uid, streamPcm->uid, json_object_get_string(streamJ)); } // save handle for further use - mixerHandle->streams = loopStream; + mixer->streams = loopStream; return 0; OnErrorExit: |