diff options
author | Thierry Bultel <thierry.bultel@iot.bzh> | 2018-08-31 13:53:47 +0200 |
---|---|---|
committer | Thierry Bultel <thierry.bultel@iot.bzh> | 2018-08-31 13:53:47 +0200 |
commit | 80deafbe1bfb87c3a5e9f547c9491afd210e736a (patch) | |
tree | 67f83684cf67268dcb65d8062280f848057a74c2 /plugins/alsa/alsa-api-mixer.c | |
parent | ded8e37b50982677480869763f3573ff43858505 (diff) |
Added bluez sound playback support
This adds sound playback for incoming sound from
connected bluetooth devices.
In this version, the softmixer relies on a modified
bluez-alsa version (https://github.com/iotbzh/bluez-alsa),
that provides an ioplug PCM bluezalsa connection proxy.
The softmixer api has a new verb to dynamically set the
device to listen to:
afb-client-demo ws://localhost:1234/api?token=\uuid=123 smixer bluezalsa_dev '{"interface":"hci0", "device":"F6:32:15:2A:80:70", "profile":"a2dp"}'
In this way it is possible to switch from a bluezalsa audio source to
another without any further configuration.
For now, only interface hci0 is supported.
This commit also migrates the softmixer binding to API v3
Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
Diffstat (limited to 'plugins/alsa/alsa-api-mixer.c')
-rw-r--r-- | plugins/alsa/alsa-api-mixer.c | 64 |
1 files changed, 56 insertions, 8 deletions
diff --git a/plugins/alsa/alsa-api-mixer.c b/plugins/alsa/alsa-api-mixer.c index 558a522..c4b016c 100644 --- a/plugins/alsa/alsa-api-mixer.c +++ b/plugins/alsa/alsa-api-mixer.c @@ -19,6 +19,8 @@ #define _GNU_SOURCE // needed for vasprintf #include "alsa-softmixer.h" +#include "alsa-bluez.h" + #include <string.h> #include <pthread.h> @@ -26,7 +28,7 @@ extern Lua2cWrapperT Lua2cWrap; static void MixerRemoveVerb(AFB_ReqT request) { - SoftMixerT *mixer = (SoftMixerT*) afb_request_get_vcbdata(request); + SoftMixerT *mixer = (SoftMixerT*) afb_req_get_vcbdata(request); int error; for (int idx = 0; mixer->streams[idx]->uid; idx++) { @@ -41,7 +43,7 @@ static void MixerRemoveVerb(AFB_ReqT request) { goto OnErrorExit; } - error = afb_dynapi_sub_verb(mixer->api, stream->uid); + error = afb_api_del_verb(mixer->api, stream->uid, (void**)&mixer); if (error) { AFB_ReqFailF(request, "internal-error", "Mixer=%s fail to remove verb=%s error=%s", mixer->uid, stream->uid, strerror(error)); goto OnErrorExit; @@ -481,7 +483,7 @@ OnErrorExit: STATIC void MixerInfoAction(AFB_ReqT request, json_object * argsJ) { - SoftMixerT *mixer = (SoftMixerT*) afb_request_get_vcbdata(request); + SoftMixerT *mixer = (SoftMixerT*) afb_req_get_vcbdata(request); int error, verbose = 0; json_object *streamsJ = NULL, *rampsJ = NULL, *zonesJ = NULL, *capturesJ = NULL, *playbacksJ = NULL; @@ -534,15 +536,15 @@ STATIC void MixerInfoAction(AFB_ReqT request, json_object * argsJ) { } STATIC void MixerInfoVerb(AFB_ReqT request) { - json_object *argsJ = afb_request_json(request); + json_object *argsJ = afb_req_json(request); MixerInfoAction(request, argsJ); } STATIC void MixerAttachVerb(AFB_ReqT request) { - SoftMixerT *mixer = (SoftMixerT*) afb_request_get_vcbdata(request); + SoftMixerT *mixer = (SoftMixerT*) afb_req_get_vcbdata(request); const char *uid = NULL, *prefix = NULL; json_object *playbacksJ = NULL, *capturesJ = NULL, *zonesJ = NULL, *streamsJ = NULL, *rampsJ = NULL, *loopsJ = NULL; - json_object *argsJ = afb_request_json(request); + json_object *argsJ = afb_req_json(request); json_object *responseJ = json_object_new_object(); int error; @@ -632,6 +634,49 @@ STATIC void MixerAttachVerb(AFB_ReqT request) { return; OnErrorExit: + AFB_ApiError(mixer->api,"%s FAILED", __func__); + return; +} + + +static void MixerBluezAlsaDevVerb(AFB_ReqT request) { + SoftMixerT *mixer = (SoftMixerT*) afb_req_get_vcbdata(request); + + json_object *argsJ = afb_req_json(request); + json_object *responseJ = json_object_new_object(); + + char * interface = NULL, *device = NULL, *profile = NULL; + + int error; + + error = wrap_json_unpack(argsJ, "{ss,ss,ss !}" + , "interface", &interface + , "device", &device + , "profile", &profile + ); + + if (error) { + AFB_ReqFailF(request, + "invalid-syntax", + "mixer=%s missing 'interface|device|profile' error=%s args=%s", + mixer->uid, wrap_json_get_error_string(error), json_object_get_string(argsJ)); + goto OnErrorExit; + } + + printf("%s: interface %s, device %s, profile %s\n", __func__, interface, device, profile); + + error = alsa_bluez_set_device(interface, device, profile); + if (error) { + AFB_ReqFailF(request, + "runtime error", + "Unable to set device , err %d", error); + goto OnErrorExit; + } + + + AFB_ReqSuccess(request, responseJ, NULL); + +OnErrorExit: return; } @@ -641,6 +686,7 @@ STATIC AFB_ApiVerbs CtrlApiVerbs[] = { { .verb = "attach", .callback = MixerAttachVerb, .info = "attach resources to mixer"}, { .verb = "remove", .callback = MixerRemoveVerb, .info = "remove existing mixer streams, zones, ..."}, { .verb = "info", .callback = MixerInfoVerb, .info = "list existing mixer streams, zones, ..."}, + { .verb = "bluezalsa_dev", .callback = MixerBluezAlsaDevVerb, .info = "set bluez alsa device"}, { .verb = NULL} /* marker for end of the array */ }; @@ -648,7 +694,7 @@ STATIC int LoadStaticVerbs(SoftMixerT *mixer, AFB_ApiVerbs * verbs) { int errcount = 0; for (int idx = 0; verbs[idx].verb; idx++) { - errcount += afb_dynapi_add_verb(mixer->api, CtrlApiVerbs[idx].verb, CtrlApiVerbs[idx].info, CtrlApiVerbs[idx].callback, (void*) mixer, CtrlApiVerbs[idx].auth, 0); + errcount += afb_api_add_verb(mixer->api, CtrlApiVerbs[idx].verb, CtrlApiVerbs[idx].info, CtrlApiVerbs[idx].callback, (void*) mixer, CtrlApiVerbs[idx].auth, 0, 0); } return errcount; @@ -757,7 +803,7 @@ CTLP_CAPI(MixerCreate, source, argsJ, responseJ) { mixer->sdLoop = AFB_GetEventLoop(source->api); mixer->api = source->api; - afb_dynapi_set_userdata(source->api, mixer); + afb_api_set_userdata(source->api, mixer); error = LoadStaticVerbs(mixer, CtrlApiVerbs); if (error) goto OnErrorExit; @@ -767,3 +813,5 @@ CTLP_CAPI(MixerCreate, source, argsJ, responseJ) { OnErrorExit: return -1; } + + |