aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFulup Ar Foll <fulup@iot.bzh>2018-05-18 17:08:24 +0200
committerFulup Ar Foll <fulup@iot.bzh>2018-05-18 17:08:24 +0200
commita2ea0dd94d803ee8e5eb79c6494f0d4c76cbcc90 (patch)
tree3af0d287681113e4155a679c5eac1e9cd410e822
parent7454d66bb47349418f8f65b8d7bec79039a2be32 (diff)
Added create/close mixer API
-rw-r--r--conf.d/project/etc/4a-softmixer-test.json44
-rw-r--r--conf.d/project/htdocs/index.html175
-rw-r--r--plugins/alsa/alsa-api-frontend.c18
-rw-r--r--plugins/alsa/alsa-api-mixer.c123
-rw-r--r--plugins/alsa/alsa-api-streams.c52
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: