diff options
-rw-r--r-- | conf.d/cmake/config.cmake | 2 | ||||
-rw-r--r-- | conf.d/project/htdocs/index.html | 5 | ||||
-rw-r--r-- | plugins/alsa/alsa-api-frontend.c | 21 | ||||
-rw-r--r-- | plugins/alsa/alsa-api-mixer.c | 60 | ||||
-rw-r--r-- | plugins/alsa/alsa-api-streams.c | 38 | ||||
-rw-r--r-- | plugins/alsa/alsa-core-ctl.c | 2 | ||||
-rw-r--r-- | plugins/alsa/alsa-softmixer.h | 1 |
7 files changed, 104 insertions, 25 deletions
diff --git a/conf.d/cmake/config.cmake b/conf.d/cmake/config.cmake index 5f5bc23..536d4b5 100644 --- a/conf.d/cmake/config.cmake +++ b/conf.d/cmake/config.cmake @@ -199,7 +199,7 @@ set(AFB_REMPORT "1234" CACHE PATH "Default binder listening port") # Print a helper message when every thing is finished # ---------------------------------------------------- -set(CLOSING_MESSAGE "Typical binding launch: afb-daemon --name ${PROJECT_NAME}-afbd --port=${AFB_REMPORT} --workdir=${CMAKE_BINARY_DIR} --binding=package/lib/softmixer-binding.so --roothttp=package/htdocs --token=\"${AFB_TOKEN}\" --tracereq=common --verbose") +set(CLOSING_MESSAGE "Typical binding launch: afb-daemon --name ${PROJECT_NAME}-afbd --port=${AFB_REMPORT} --workdir=${CMAKE_BINARY_DIR} --ldpath=/dev/null --binding=package/lib/softmixer-binding.so --roothttp=package/htdocs --token=\"${AFB_TOKEN}\" --tracereq=common --verbose") set(PACKAGE_MESSAGE "Install widget file using in the target : afm-util install ${PROJECT_NAME}.wgt") # Optional schema validator about now only XML, LUA and JSON diff --git a/conf.d/project/htdocs/index.html b/conf.d/project/htdocs/index.html index 600f7e0..22ec2a2 100644 --- a/conf.d/project/htdocs/index.html +++ b/conf.d/project/htdocs/index.html @@ -8,14 +8,15 @@ <body onload="init('hal_registry','alsacore', 'hallist')"> - <h1>Simple Control Test</h1> + <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','mixer-config');">Mixer Config</button></li> + <li><button onclick="callbinder('softmixer','simple_mixer',{list:{streams:true}});">Streams List</button></li> + <li><button onclick="callbinder('softmixer','simple_mixer/multimedia',{toggle: true});">Stream Multimedia pause/resume</button></li> </ol> <div id="main" style="visibility:hidden"> diff --git a/plugins/alsa/alsa-api-frontend.c b/plugins/alsa/alsa-api-frontend.c index c01a88b..91ce63f 100644 --- a/plugins/alsa/alsa-api-frontend.c +++ b/plugins/alsa/alsa-api-frontend.c @@ -92,10 +92,23 @@ STATIC int ProcessOneLoop(CtlSourceT *source, json_object *loopJ, AlsaSndLoopT * loopDefParams->sampleSize=0; } - // make sure useful information will not be removed - loop->uid = strdup(loop->uid); - if (loop->cardid) loop->cardid = strdup(loop->cardid); - if (loop->devpath) loop->cardid = strdup(loop->devpath); + // Fake a sound card to check if loop is a valid Alsa snd driver + AlsaPcmInfoT sndLoop; + sndLoop.uid = loop->uid; + sndLoop.devpath = loop->devpath; + sndLoop.cardid = loop->cardid; + sndLoop.device = 0; + sndLoop.subdev = 0; + error = AlsaByPathDevid(source, &sndLoop); + if (error) { + AFB_ApiError(source->api, "ProcessOneLoop: loop=%s not found config=%s", loop->uid, json_object_get_string(loopJ)); + goto OnErrorExit; + } + loop->uid= sndLoop.uid; + loop->devpath= sndLoop.devpath; + loop->cardid=sndLoop.cardid; + loop->cardidx=sndLoop.cardidx; + // Default devices is payback=0 capture=1 if (!devicesJ) { diff --git a/plugins/alsa/alsa-api-mixer.c b/plugins/alsa/alsa-api-mixer.c index f1619c2..31854b0 100644 --- a/plugins/alsa/alsa-api-mixer.c +++ b/plugins/alsa/alsa-api-mixer.c @@ -27,9 +27,11 @@ extern Lua2cWrapperT Lua2cWrap; // API static void MixerApiVerbCB(AFB_ReqT request) { - json_object *responseJ, *backendJ = NULL, *frontendJ = NULL, *zonesJ = NULL, *streamsJ = NULL; + json_object *valueJ, *backendJ = NULL, *frontendJ = NULL, *zonesJ = NULL, *streamsJ = NULL, *listJ = NULL; // retrieve action handle from request and execute the request json_object *argsJ = afb_request_json(request); + json_object *responseJ = json_object_new_object(); + SoftMixerHandleT *mixerHandle = (SoftMixerHandleT*) afb_request_get_vcbdata(request); int error; int close = 0; @@ -40,24 +42,74 @@ static void MixerApiVerbCB(AFB_ReqT request) { source->request = request; source->context = mixerHandle; - error = wrap_json_unpack(argsJ, "{s?b s?o,s?o,s?o,s?o !}" + error = wrap_json_unpack(argsJ, "{s?b,s?o,s?o,s?o,s?o,s?o !}" , "close", &close + , "list", &listJ , "backend", &backendJ , "frontend", &frontendJ , "zones", &zonesJ , "streams", &streamsJ ); if (error) { - AFB_ReqFailF(request, "MixerApiVerbCB", "missing 'uid|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, "MixerApiVerbCB", "(Fulup) Close action still to be done mixer=%s", json_object_get_string(argsJ)); + AFB_ReqFailF(request, "not implemented", "(Fulup) Close action still to be done mixer=%s", json_object_get_string(argsJ)); goto OnErrorExit; } + if (listJ) { + int streams = 0, quiet = 0, backend = 0, frontend = 0, zones = 0; + + error = wrap_json_unpack(listJ, "{s?b,s?b,s?b,s?b,s?b !}" + , "quiet", &quiet + , "streams", &streams + , "backend", &backend + , "frontend", &frontend + , "zones", &zones + ); + if (error) { + 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(); + + AlsaSndStreamT *streams = mixerHandle->streams; + for (int idx = 0; streams[idx].uid; idx++) { + if (quiet) { + json_object_array_add(streamsJ, json_object_new_string(streams[idx].uid)); + } else { + json_object *numidJ; + wrap_json_pack(&numidJ, "{si,si}" + , "volume", streams[idx].volume + , "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)); + } + + } + 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; + } + + AFB_ReqSucess(request, responseJ, NULL); + return; + } + if (backendJ) { error = SndBackend(source, backendJ); if (error) goto OnErrorExit; diff --git a/plugins/alsa/alsa-api-streams.c b/plugins/alsa/alsa-api-streams.c index 42d8ade..bc5008b 100644 --- a/plugins/alsa/alsa-api-streams.c +++ b/plugins/alsa/alsa-api-streams.c @@ -36,8 +36,8 @@ typedef struct { } apiHandleT; static void StreamApiVerbCB(AFB_ReqT request) { - int close=0, error=0, quiet=0; - long volume=-1, mute=-1; + int error, doClose=0, doQuiet=0, doToggle=0, doMute=-1; + long mute, volume=-1; json_object *responseJ, *argsJ= afb_request_json(request); apiHandleT *handle = (apiHandleT*) afb_request_get_vcbdata(request); @@ -47,10 +47,11 @@ static void StreamApiVerbCB(AFB_ReqT request) { source->request = NULL; source->context = NULL; - error = wrap_json_unpack(argsJ, "{s?b s?b,s?b, s?i !}" - , "quiet", &quiet - , "close", &close - , "mute", &mute + error = wrap_json_unpack(argsJ, "{s?b s?b,s?b,s?b,s?i !}" + , "quiet", &doQuiet + , "close", &doClose + , "mute", &doMute + , "toggle", &doToggle , "volume", &volume ); if (error) { @@ -64,11 +65,16 @@ static void StreamApiVerbCB(AFB_ReqT request) { goto OnErrorExit; } - if (close) { + if (doClose) { AFB_ReqFailF(request, "StreamApiVerbCB", "(Fulup) Close action still to be done mixer=%s", json_object_get_string(argsJ)); goto OnErrorExit; } + if (doToggle) { + error+= AlsaCtlNumidGetLong (source, ctlDev, handle->streams->mute, &mute); + error+= AlsaCtlNumidSetLong (source, ctlDev, handle->streams->mute, !mute); + } + if (volume != -1) { error= AlsaCtlNumidSetLong (source, ctlDev, handle->streams->volume, volume); if (error) { @@ -77,8 +83,8 @@ static void StreamApiVerbCB(AFB_ReqT request) { } } - if (mute != -1) { - error= AlsaCtlNumidSetLong (source, ctlDev, handle->streams->volume, !mute); + if (doMute != -1) { + error= AlsaCtlNumidSetLong (source, ctlDev, handle->streams->mute, !mute); if (error) { AFB_ReqFailF(request, "StreamApiVerbCB", "Fail to set stream volume numid=%d value=%d", handle->streams->volume, !mute); goto OnErrorExit; @@ -86,7 +92,7 @@ static void StreamApiVerbCB(AFB_ReqT request) { } // if not in quiet mode return effective selected control values - if (quiet) responseJ=NULL; + if (doQuiet) responseJ=NULL; else { error+= AlsaCtlNumidGetLong (source, ctlDev, handle->streams->volume, &volume); error+= AlsaCtlNumidGetLong (source, ctlDev, handle->streams->mute, &mute); @@ -94,13 +100,15 @@ static void StreamApiVerbCB(AFB_ReqT request) { AFB_ReqFailF(request, "StreamApiVerbCB", "Fail to get stream numids volume=%ld mute=%ld",volume, mute); goto OnErrorExit; } - wrap_json_pack (&responseJ,"{volume:si, mute:sb}", volume, mute); + wrap_json_pack (&responseJ,"{si,sb}", "volume",volume, "mute",!mute); } + snd_ctl_close (ctlDev); AFB_ReqSucess(request, responseJ, handle->verb); return; OnErrorExit: + if(ctlDev) snd_ctl_close (ctlDev); return; } @@ -317,14 +325,16 @@ PUBLIC int SndStreams(CtlSourceT *source, json_object *argsJ, json_object **resp apiHandle->mixer = mixerHandle; apiHandle->streams = &sndStream[idx]; apiHandle->verb = strdup(apiVerb); - error = afb_dynapi_add_verb(source->api, apiHandle->verb, sndStream[idx].info, StreamApiVerbCB, mixerHandle, NULL, 0); + error = afb_dynapi_add_verb(source->api, apiHandle->verb, sndStream[idx].info, StreamApiVerbCB, apiHandle, NULL, 0); if (error) { AFB_ApiError(source->api, "SndStreams mixer=%s fail to register API verb=%s", mixerHandle->uid, apiHandle->verb); return -1; } - // free tempry resource + // free temporary resources snd_ctl_close(ctlDev); + sndStream[idx].volume= volNumid; + sndStream[idx].mute= runNumid; // Debug Alsa Config //AlsaDumpElemConfig (source, "\n\nAlsa_Config\n------------\n", "pcm"); @@ -333,6 +343,8 @@ PUBLIC int SndStreams(CtlSourceT *source, json_object *argsJ, json_object **resp AFB_ApiNotice(source->api, "SndStreams: mixer=%s stream=%s OK reponse=%s\n", mixerHandle->uid, streamPcm->uid, json_object_get_string(streamJ)); } + // save handle for further use + mixerHandle->streams = sndStream; return 0; OnErrorExit: diff --git a/plugins/alsa/alsa-core-ctl.c b/plugins/alsa/alsa-core-ctl.c index f224f92..1749679 100644 --- a/plugins/alsa/alsa-core-ctl.c +++ b/plugins/alsa/alsa-core-ctl.c @@ -156,7 +156,7 @@ PUBLIC snd_ctl_t *AlsaCtlOpenCtl(CtlSourceT *source, const char *cardid) { int error; snd_ctl_t *ctlDev; - if (cardid) goto OnErrorExit; + if (!cardid) goto OnErrorExit; if ((error = snd_ctl_open(&ctlDev, cardid, SND_CTL_READONLY)) < 0) { cardid = "Not Defined"; diff --git a/plugins/alsa/alsa-softmixer.h b/plugins/alsa/alsa-softmixer.h index 7146e78..f5a82f0 100644 --- a/plugins/alsa/alsa-softmixer.h +++ b/plugins/alsa/alsa-softmixer.h @@ -122,6 +122,7 @@ typedef struct { AlsaPcmInfoT *backend; AlsaPcmInfoT *multiPcm; AlsaPcmInfoT **routes; + AlsaSndStreamT *streams; } SoftMixerHandleT; // alsa-utils-bypath.c |