diff options
Diffstat (limited to 'plugins/alsa/alsa-api-mixer.c')
-rw-r--r-- | plugins/alsa/alsa-api-mixer.c | 262 |
1 files changed, 201 insertions, 61 deletions
diff --git a/plugins/alsa/alsa-api-mixer.c b/plugins/alsa/alsa-api-mixer.c index 8616384..ca90649 100644 --- a/plugins/alsa/alsa-api-mixer.c +++ b/plugins/alsa/alsa-api-mixer.c @@ -62,7 +62,7 @@ static void MixerRemoveVerb(AFB_ReqT request) { // finally free mixer handle free(mixer); - AFB_ReqSucess(request, NULL, "Fulup: delete might not clean everything properly"); + AFB_ReqSuccess(request, NULL, "Fulup: delete might not clean everything properly"); return; @@ -70,21 +70,124 @@ OnErrorExit: AFB_ReqFail(request, "internal-error", "fail to delete mixer"); } -STATIC void MixerInfoAction(AFB_ReqT request, json_object *argsJ) { +STATIC json_object * MixerInfoStreams(SoftMixerT *mixer, json_object *streamsJ, int verbose) { + const char * key; + json_object *valueJ; + json_object *responseJ = json_object_new_array(); + AlsaStreamAudioT **streams = mixer->streams; + + switch (json_object_get_type(streamsJ)) { + + case json_type_null: + case json_type_boolean: + + for (int idx = 0; streams[idx]; idx++) { + json_object *alsaJ; + + if (!verbose) { + wrap_json_pack(&alsaJ, "{ss}", "alsa", streams[idx]->source); + json_object_array_add(responseJ, alsaJ); + } else { + + wrap_json_pack(&alsaJ, "{ss,si,si}" + , "cardid", streams[idx]->source + , "volume", streams[idx]->volume + , "mute", streams[idx]->mute + ); + wrap_json_pack(&valueJ, "{ss,ss,so}" + , "uid", streams[idx]->uid + , "verb", streams[idx]->verb + , "alsa", alsaJ + ); + json_object_array_add(responseJ, valueJ); + } + } + break; + + case json_type_string: + + key = json_object_get_string(streamsJ); + for (int idx = 0; streams[idx]; idx++) { + json_object *alsaJ; + + if (!strcasestr(streams[idx]->uid, key)) continue; + + if (!verbose) { + wrap_json_pack(&alsaJ, "{ss}", "alsa", streams[idx]->source); + json_object_array_add(responseJ, alsaJ); + } else { + + wrap_json_pack(&alsaJ, "{ss,si,si}" + , "cardid", streams[idx]->source + , "volume", streams[idx]->volume + , "mute", streams[idx]->mute + ); + wrap_json_pack(&valueJ, "{ss,ss,so}" + , "uid", streams[idx]->uid + , "verb", streams[idx]->verb + , "alsa", alsaJ + ); + json_object_array_add(responseJ, valueJ); + } + } + break; + + case json_type_array: + + for (int idx=0; idx < json_object_array_length(streamsJ); idx++) { + json_object *streamJ = json_object_array_get_idx(streamsJ, idx); + valueJ= MixerInfoStreams (mixer, streamJ, verbose); + json_object_array_add(responseJ, valueJ); + } + + default: + goto OnErrorExit; + } + return (responseJ); + +OnErrorExit: + return NULL; +} + +STATIC json_object * MixerInfoRamps(SoftMixerT *mixer, int verbose) { + + json_object *rampsJ = json_object_new_array(); + json_object *valueJ; + + AlsaVolRampT **ramps = mixer->ramps; + for (int idx = 0; ramps[idx]; idx++) { + if (!verbose) { + json_object_array_add(rampsJ, json_object_new_string(ramps[idx]->uid)); + } else { + wrap_json_pack(&valueJ, "{ss,si,si,si}" + , "uid", ramps[idx]->uid + , "delay", ramps[idx]->delay + , "step_down", ramps[idx]->stepDown + , "step_up", ramps[idx]->stepUp + ); + json_object_array_add(rampsJ, valueJ); + } + } + + return (rampsJ); +} + +STATIC void MixerInfoAction(AFB_ReqT request, json_object * argsJ) { SoftMixerT *mixer = (SoftMixerT*) afb_request_get_vcbdata(request); - int error, streams = 0, quiet = 0, ramps = 0, zones = 0, captures = 0, playbacks = 0; + int error, verbose = 0, ramps = 0, zones = 0, captures = 0, playbacks = 0; + json_object *streamsJ = NULL; if (json_object_get_type(argsJ) == json_type_null) { - streams = 1; + streamsJ = json_object_new_boolean(1); ramps = 1; zones = 0; captures = 0; playbacks = 0; } else { - error = wrap_json_unpack(argsJ, "{s?b,s?b,s?b,s?b,s?b,s?b !}" - , "quiet", &quiet - , "streams", &streams + error = wrap_json_unpack(argsJ, "{s?b,s?o,s?b,s?b,s?b,s?b !}" + , "verbose", &verbose + , "streams", &streamsJ , "ramps", &ramps , "captures", &captures , "playbacks", &playbacks @@ -97,48 +200,17 @@ STATIC void MixerInfoAction(AFB_ReqT request, json_object *argsJ) { } json_object *responseJ = json_object_new_object(); - if (streams) { - json_object *streamsJ = json_object_new_array(); - json_object *valueJ; - - AlsaStreamAudioT **streams = mixer->streams; - for (int idx = 0; streams[idx]; idx++) { - if (quiet) { - json_object_array_add(streamsJ, json_object_new_string(streams[idx]->uid)); - } else { - wrap_json_pack(&valueJ, "{ss,ss?,s{si,si}}" - , "uid", streams[idx]->uid - , "alsa", streams[idx]->source - , "numid" - , "volume", streams[idx]->volume - , "mute", streams[idx]->mute - ); - json_object_array_add(streamsJ, valueJ); - } - + if (streamsJ) { + json_object *resultJ = MixerInfoStreams(mixer, streamsJ, verbose); + if (!resultJ) { + AFB_ReqFailF(request, "invalid-object", "streams should be boolean or string argsJ=%s", json_object_get_string(streamsJ)); + goto OnErrorExit; } - json_object_object_add(responseJ, "streams", streamsJ); + json_object_object_add(responseJ, "streams", resultJ); } if (ramps) { - json_object *rampsJ = json_object_new_array(); - json_object *valueJ; - - AlsaVolRampT **ramps = mixer->ramps; - for (int idx = 0; ramps[idx]; idx++) { - if (quiet) { - json_object_array_add(rampsJ, json_object_new_string(ramps[idx]->uid)); - } else { - wrap_json_pack(&valueJ, "{ss,si,si,si}" - , "uid", ramps[idx]->uid - , "delay", ramps[idx]->delay - , "step_down", ramps[idx]->stepDown - , "step_up", ramps[idx]->stepUp - ); - json_object_array_add(rampsJ, valueJ); - } - - } + json_object *rampsJ = MixerInfoRamps (mixer, verbose); json_object_object_add(responseJ, "ramps", rampsJ); } @@ -147,7 +219,7 @@ STATIC void MixerInfoAction(AFB_ReqT request, json_object *argsJ) { AlsaSndZoneT **zones = mixer->zones; for (int idx = 0; zones[idx]; idx++) { - if (quiet) { + if (!verbose) { json_object_array_add(zonesJ, json_object_new_string(zones[idx]->uid)); } else { json_object *zoneJ = json_object_new_object(); @@ -198,7 +270,7 @@ STATIC void MixerInfoAction(AFB_ReqT request, json_object *argsJ) { goto OnErrorExit; } - AFB_ReqSucess(request, responseJ, NULL); + AFB_ReqSuccess(request, responseJ, NULL); return; OnErrorExit: @@ -206,19 +278,21 @@ OnErrorExit: } STATIC void MixerInfoVerb(AFB_ReqT request) { - json_object *argsJ = afb_request_json(request); - MixerInfoAction (request, argsJ); + json_object *argsJ = afb_request_json(request); + MixerInfoAction(request, argsJ); } STATIC void MixerAttachVerb(AFB_ReqT request) { SoftMixerT *mixer = (SoftMixerT*) afb_request_get_vcbdata(request); - const char *uid = NULL; + const char *uid = NULL, *prefix = NULL; json_object *playbackJ = NULL, *captureJ = NULL, *zonesJ = NULL, *streamsJ = NULL, *rampsJ = NULL, *loopsJ = NULL; json_object *argsJ = afb_request_json(request); + json_object *responseJ = json_object_new_object(); int error; - error = wrap_json_unpack(argsJ, "{ss,s?o,s?o,s?o,s?o,s?o,s?o !}" + error = wrap_json_unpack(argsJ, "{ss,s?s,s?o,s?o,s?o,s?o,s?o,s?o !}" , "uid", &uid + , "prefix", &prefix , "ramps", &rampsJ , "playbacks", &playbackJ , "captures", &captureJ @@ -227,7 +301,6 @@ STATIC void MixerAttachVerb(AFB_ReqT request) { , "streams", &streamsJ ); if (error) { - AFB_ApiError(mixer->api, "MixerAttachVerb: invalid-syntax mixer=%s error=%s args=%s", mixer->uid, wrap_json_get_error_string(error), json_object_get_string(argsJ)); AFB_ReqFailF(request, "invalid-syntax", "mixer=%s missing 'uid|ramps|playbacks|captures|zones|streams' error=%s args=%s", mixer->uid, wrap_json_get_error_string(error), json_object_get_string(argsJ)); goto OnErrorExit; } @@ -255,15 +328,22 @@ STATIC void MixerAttachVerb(AFB_ReqT request) { if (rampsJ) { error = ApiRampAttach(mixer, request, uid, rampsJ); if (error) goto OnErrorExit; + + json_object *resultJ = MixerInfoStreams(mixer, streamsJ, 0); + json_object_object_add(responseJ, "ramps", resultJ); } if (streamsJ) { - error = ApiStreamAttach(mixer, request, uid, streamsJ); + error = ApiStreamAttach(mixer, request, uid, prefix, streamsJ); if (error) goto OnErrorExit; + + json_object *resultJ = MixerInfoStreams(mixer, streamsJ, 0); + json_object_object_add(responseJ, "streams", resultJ); } - // return mixer info data after attach - return (MixerInfoAction(request,NULL)); + AFB_ReqSuccess(request, responseJ, NULL); + + return; OnErrorExit: return; @@ -273,7 +353,7 @@ STATIC void MixerPingVerb(AFB_ReqT request) { static int count = 0; count++; AFB_ReqNotice(request, "Controller:ping count=%d", count); - AFB_ReqSucess(request, json_object_new_int(count), NULL); + AFB_ReqSuccess(request, json_object_new_int(count), NULL); return; } @@ -289,7 +369,7 @@ STATIC AFB_ApiVerbs CtrlApiVerbs[] = { { .verb = NULL} /* marker for end of the array */ }; -STATIC int LoadStaticVerbs(SoftMixerT *mixer, AFB_ApiVerbs *verbs) { +STATIC int LoadStaticVerbs(SoftMixerT *mixer, AFB_ApiVerbs * verbs) { int errcount = 0; for (int idx = 0; verbs[idx].verb; idx++) { @@ -299,8 +379,68 @@ STATIC int LoadStaticVerbs(SoftMixerT *mixer, AFB_ApiVerbs *verbs) { return errcount; }; -CTLP_CAPI(CreateMixer, source, argsJ, responseJ) { +CTLP_CAPI(MixerAttach, source, argsJ, responseJ) { + SoftMixerT *mixer = source->context; + json_object *playbackJ = NULL, *captureJ = NULL, *zonesJ = NULL, *streamsJ = NULL, *rampsJ = NULL, *loopsJ = NULL; + const char* uid = source->uid, *prefix = NULL; + + int error; + + error = wrap_json_unpack(argsJ, "{s?s, s?o,s?o,s?o,s?o,s?o,s?o !}" + , "prefix", &rampsJ + , "ramps", &rampsJ + , "playbacks", &playbackJ + , "captures", &captureJ + , "loops", &loopsJ + , "zones", &zonesJ + , "streams", &streamsJ + ); + if (error) { + AFB_ApiError(mixer->api, "MixerAttachVerb: invalid-syntax mixer=%s error=%s args=%s", mixer->uid, wrap_json_get_error_string(error), json_object_get_string(argsJ)); + goto OnErrorExit; + } + + if (playbackJ) { + error = ApiSinkAttach(mixer, NULL, uid, playbackJ); + if (error) goto OnErrorExit; + } + + if (captureJ) { + error = ApiSourceAttach(mixer, NULL, uid, captureJ); + if (error) goto OnErrorExit; + } + + if (loopsJ) { + error = ApiLoopAttach(mixer, NULL, uid, loopsJ); + if (error) goto OnErrorExit; + } + + if (zonesJ) { + error = ApiZoneAttach(mixer, NULL, uid, zonesJ); + if (error) goto OnErrorExit; + } + + if (rampsJ) { + error = ApiRampAttach(mixer, NULL, uid, rampsJ); + if (error) goto OnErrorExit; + } + + if (streamsJ) { + error = ApiStreamAttach(mixer, NULL, uid, prefix, streamsJ); + if (error) goto OnErrorExit; + } + + // return mixer info data after attach + return 0; + +OnErrorExit: + return -1; +} + +CTLP_CAPI(MixerCreate, source, argsJ, responseJ) { SoftMixerT *mixer = calloc(1, sizeof (SoftMixerT)); + source->context = mixer; + int error; mixer->max.loops = SMIXER_DEFLT_RAMPS; mixer->max.sinks = SMIXER_DEFLT_SINKS; @@ -339,14 +479,14 @@ CTLP_CAPI(CreateMixer, source, argsJ, responseJ) { mixer->zones = calloc(mixer->max.zones + 1, sizeof (void*)); mixer->streams = calloc(mixer->max.streams + 1, sizeof (void*)); mixer->ramps = calloc(mixer->max.ramps + 1, sizeof (void*)); - + mixer->sdLoop = AFB_GetEventLoop(source->api); - mixer->api= source->api; + mixer->api = source->api; afb_dynapi_set_userdata(source->api, mixer); error = LoadStaticVerbs(mixer, CtrlApiVerbs); if (error) goto OnErrorExit; - + return 0; OnErrorExit: |