diff options
author | Thierry Bultel <thierry.bultel@iot.bzh> | 2018-12-04 23:11:20 +0100 |
---|---|---|
committer | Thierry Bultel <thierry.bultel@iot.bzh> | 2018-12-19 23:09:21 +0100 |
commit | e0f57e523112e1bc73a04e8615d7a21355f0ce0e (patch) | |
tree | 19198c38d7433862cee733fde3efca8170228279 /plugins/alsa/alsa-softmixer.h | |
parent | 7df040a3742af8d800852dd39f8e921cd82a4cf2 (diff) |
Add support for bluetooth telephonyguppy_6.99.3guppy/6.99.36.99.3
This adds support for bluetooth telephony.
A big rework in the softmixer internals has been
mandatory, in order to support dynamic streams creation
and deletions.
Bluetooth telephony relies on the recent evolutions
of bluez-alsa, the most important one being the
support of HFP over Ofono. The softmixer opens
PCM ioplugs provided by bluez-alsa.
Bluetooth SCO needs 2 streams, one for listening
and the other for talking. These streams are created
upon requests sent by the hal-manager.
The hal manager subscribes for bluez-alsa events
and request the list of availalble transports.
For each "attach" transaction verb, the softmixer
maintains a list of the all created objects
(sources, sinks, zones, ramps, streams, and more)
Additionnally, it creates a new verb when the attach
succeeds, that verb is typically something like
"sco_XX:XX:XX:XX:XX:XX", and the only supported action
at the present time is {"action":"remove"}, that performs
all the cleanup of the registered objects.
Change-Id: I1b119e6c079e60daf771e63c083a1ef33a39f379
Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
Diffstat (limited to 'plugins/alsa/alsa-softmixer.h')
-rw-r--r-- | plugins/alsa/alsa-softmixer.h | 148 |
1 files changed, 109 insertions, 39 deletions
diff --git a/plugins/alsa/alsa-softmixer.h b/plugins/alsa/alsa-softmixer.h index e7218bd..a8cc6de 100644 --- a/plugins/alsa/alsa-softmixer.h +++ b/plugins/alsa/alsa-softmixer.h @@ -21,7 +21,6 @@ #ifndef _ALSA_SOFTMIXER_ #define _ALSA_SOFTMIXER_ -//#include <afb/afb-binding.h> #include <json-c/json_object.h> #include <stdlib.h> #include <stdio.h> @@ -31,11 +30,15 @@ #include <systemd/sd-event.h> #include <semaphore.h> +#include <urcu/list.h> + #include "ctl-plugin.h" #include "wrap-json.h" #include "alsa-ringbuf.h" +#include "alsa-transaction.h" + #ifndef PUBLIC #define PUBLIC #endif @@ -51,7 +54,7 @@ #define ALSA_CARDID_MAX_LEN 64 -#define SMIXER_SUBDS_CTLS 3 +#define SMIXER_SUBDS_CTLS 16 #define SMIXER_DEFLT_LOOPS 4 #define SMIXER_DEFLT_SINKS 8 #define SMIXER_DEFLT_SOURCES 32 @@ -59,9 +62,16 @@ #define SMIXER_DEFLT_STREAMS 32 #define SMIXER_DEFLT_RAMPS 8 +#define SMIXER_DEFLT_DELAYMS 1000 + +#define SOFTMIXER_VERB_NONE "none" + #define ALSA_PLUG_PROTO(plugin) \ int _snd_pcm_ ## plugin ## _open(snd_pcm_t **pcmp, const char *name, snd_config_t *root, snd_config_t *conf, snd_pcm_stream_t stream, int mode) +#define SOFTMIXER_NOMEM(api) \ + AFB_ApiError((api), "%s: Insufficient memory", __func__) + // auto switch from Log to API request depending on request presence. #define AFB_IfReqFailF(mixer, request, status, format, ...) \ if (request) AFB_ReqFailF(request, status, format, __VA_ARGS__); \ @@ -101,16 +111,20 @@ typedef struct { } AlsaPcmHwInfoT; typedef struct { + const char * name; int ccount; bool mute; - int muteFd; + int eventFd; AlsaDevInfoT cid; snd_pcm_t *handle; AlsaPcmHwInfoT *params; - void * mixer; + struct SoftMixerT_ * mixer; snd_pcm_uframes_t avail_min; + + bool closeAtDeletion; // intermediate pcms in the pcm chain must not be closed, else it make libasound abort() + bool isPcmPlug; } AlsaPcmCtlT; typedef struct { @@ -138,12 +152,15 @@ typedef struct { char* info; int nbPcmFds; - struct pollfd pollFds[2]; + struct pollfd * pollFds; sem_t sem; pthread_mutex_t mutex; int saveFd; + bool ending; + + struct AlsaStreamAudioT_ * stream; } AlsaPcmCopyHandleT; @@ -156,87 +173,112 @@ typedef struct { long step; } AlsaSndControlT; + typedef struct { const char*uid; int port; + double volume; + struct cds_list_head list; } AlsaPcmChannelT; - typedef struct { const char *uid; int delay; // delay between volset in us int stepDown; // linear % int stepUp; // linear % + struct cds_list_head list; } AlsaVolRampT; - - - typedef struct { int numid; RegistryNumidT type; AlsaPcmCtlT *pcm; + struct cds_list_head cardListEntry; /* node to list in AlsaSndCtlT */ + struct AlsaSndCtlT_ *sndcard; /* ref to owner */ } RegistryEntryPcmT; -typedef struct { - long rcount; + +typedef struct AlsaSndCtlT_ { AlsaDevInfoT cid; snd_ctl_t *ctl; AlsaPcmHwInfoT *params; - RegistryEntryPcmT **registry; + long nbRegistry; + struct cds_list_head registryList; + struct SubscribeHandleT_ * eventSubscribeHandle; } AlsaSndCtlT; typedef struct { const char *uid; - AlsaPcmChannelT **sources; - AlsaPcmChannelT **sinks; + unsigned int nbSources; + AlsaPcmChannelT sources; + unsigned int nbSinks; + AlsaPcmChannelT sinks; int ccount; AlsaPcmHwInfoT *params; + struct cds_list_head list; + snd_config_t * routeConfig; + bool isPcmPlug; } AlsaSndZoneT; typedef struct { const char *uid; const char *verb; - unsigned int ccount; AlsaSndCtlT *sndcard; AlsaSndControlT volume; AlsaSndControlT mute; - AlsaPcmChannelT **channels; + unsigned int nbChannels; + AlsaPcmChannelT channels; snd_pcm_stream_t direction; + struct cds_list_head list; + bool isPcmPlug; + void * apiVerbHandle; } AlsaSndPcmT; typedef struct { const char*uid; int index; int numid; + struct cds_list_head list; } AlsaLoopSubdevT; -typedef struct { + +struct SoftMixerT_; + +typedef struct AlsaSndLoopT { const char *uid; + struct SoftMixerT_ * mixer; /* owner */ int playback; int capture; - long scount; AlsaSndCtlT *sndcard; - AlsaLoopSubdevT **subdevs; + int nbSubdevs; + AlsaLoopSubdevT subdevs; + struct cds_list_head list; } AlsaSndLoopT; -typedef struct { +typedef struct AlsaStreamAudioT_ { const char *uid; const char *verb; const char *info; const char *sink; + const char *playback; const char *source; const char *ramp; int volume; int mute; + unsigned int delayms; AlsaPcmHwInfoT *params; AlsaPcmCopyHandleT *copy; + struct cds_list_head list; /* link to the global list*/ + AlsaPcmCtlT * softvol; + snd_config_t * softvolConfig; + snd_config_t * rateConfig; + void * verbApiHandle; } AlsaStreamAudioT; -typedef struct { +typedef struct SoftMixerT_{ const char *uid; const char *info; AFB_ApiT api; @@ -250,17 +292,27 @@ typedef struct { unsigned int streams; unsigned int ramps; } max; - AlsaSndLoopT **loops; - AlsaSndPcmT **sinks; - AlsaSndPcmT **sources; - AlsaSndZoneT **zones; - AlsaStreamAudioT **streams; - AlsaVolRampT **ramps; + unsigned int nbLoops; + AlsaSndLoopT loops; + unsigned int nbSinks; + AlsaSndPcmT sinks; + unsigned int nbSources; + AlsaSndPcmT sources; + unsigned int nbZones; + AlsaSndZoneT zones; + unsigned int nbStreams; + AlsaStreamAudioT streams; + unsigned int nbRamps; + AlsaVolRampT ramps; + + AlsaMixerTransaction * transaction; } SoftMixerT; // alsa-utils-bypath.c PUBLIC snd_ctl_card_info_t *AlsaByPathInfo(SoftMixerT *mixer, const char *devpath); -PUBLIC AlsaPcmCtlT *AlsaByPathOpenPcm(SoftMixerT *mixer, AlsaDevInfoT *pcmId, snd_pcm_stream_t direction); +PUBLIC AlsaPcmCtlT * AlsaPcmCtlNew(SoftMixerT*, const char*); +PUBLIC void AlsaPcmCtlDelete(SoftMixerT *mixer, void *); +PUBLIC AlsaPcmCtlT *AlsaByPathOpenPcmCtl(SoftMixerT *mixer, AlsaDevInfoT *pcmId, snd_pcm_stream_t direction); PUBLIC snd_ctl_t *AlsaByPathOpenCtl(SoftMixerT *mixer, const char *uid, AlsaSndCtlT *dev); // alsa-utils-dump.c @@ -279,7 +331,7 @@ PUBLIC void AlsaDumpCtlConfig(SoftMixerT *mixer, const char* info, snd_config_t // alsa-core-ctl.c PUBLIC snd_ctl_elem_id_t *AlsaCtlGetNumidElemId(SoftMixerT *mixer, AlsaSndCtlT *sndcard, int numid) ; PUBLIC snd_ctl_elem_id_t *AlsaCtlGetNameElemId(SoftMixerT *mixer, AlsaSndCtlT *sndcard, const char *ctlName) ; -PUBLIC snd_ctl_t *AlsaCtlOpenCtl(SoftMixerT *mixer, const char *cardid) ; + PUBLIC int CtlElemIdGetLong(SoftMixerT *mixer, AlsaSndCtlT *sndcard, snd_ctl_elem_id_t *elemId, long *value) ; PUBLIC int CtlElemIdSetLong(SoftMixerT *mixer, AlsaSndCtlT *sndcard, snd_ctl_elem_id_t *elemId, long value) ; PUBLIC snd_ctl_card_info_t *AlsaCtlGetCardInfo(SoftMixerT *mixer, const char *cardid) ; @@ -288,37 +340,55 @@ PUBLIC int AlsaCtlNumidGetLong(SoftMixerT *mixer, AlsaSndCtlT *sndcard, int numi PUBLIC int AlsaCtlNameSetLong(SoftMixerT *mixer, AlsaSndCtlT *sndcard, const char *ctlName, long value) ; PUBLIC int AlsaCtlNameGetLong(SoftMixerT *mixer, AlsaSndCtlT *sndcard, const char *ctlName, long* value) ; PUBLIC int AlsaCtlCreateControl(SoftMixerT *mixer, AlsaSndCtlT *sndcard, char* ctlName, int ctlCount, int ctlMin, int ctlMax, int ctlStep, long value) ; -PUBLIC snd_ctl_t* AlsaCrlFromPcm(SoftMixerT *mixer, snd_pcm_t *pcm) ; + PUBLIC int AlsaCtlSubscribe(SoftMixerT *mixer, const char *uid, AlsaSndCtlT *sndcard) ; + +PUBLIC void AlsaCtlUnregister(SoftMixerT* mixer, void *); PUBLIC int AlsaCtlRegister(SoftMixerT *mixer, AlsaSndCtlT *sndcard, AlsaPcmCtlT *pcmdev, RegistryNumidT type, int numid); // alsa-core-pcm.c PUBLIC int AlsaPcmConf(SoftMixerT *mixer, AlsaPcmCtlT *pcm, int mode); -PUBLIC int AlsaPcmCopy(SoftMixerT *mixer, AlsaStreamAudioT *stream, AlsaPcmCtlT *pcmIn, AlsaPcmCtlT *pcmOut, AlsaPcmHwInfoT * opts); +PUBLIC int AlsaPcmCopyStart(SoftMixerT *mixer, AlsaStreamAudioT *stream, AlsaPcmCtlT *pcmIn, AlsaPcmCtlT *pcmOut, AlsaPcmHwInfoT * opts); +PUBLIC int AlsaPcmCopyStop(SoftMixerT *mixer, AlsaPcmCopyHandleT * handle); // alsa-plug-*.c _snd_pcm_PLUGIN_open_ see macro ALSA_PLUG_PROTO(plugin) -PUBLIC int AlsaPcmCopy(SoftMixerT *mixer, AlsaStreamAudioT *streamAudio, AlsaPcmCtlT *pcmIn, AlsaPcmCtlT *pcmOut, AlsaPcmHwInfoT * opts); PUBLIC int AlsaPcmCopyMuteSignal(SoftMixerT *mixer, AlsaPcmCtlT *pcmIn, bool mute); + PUBLIC AlsaPcmCtlT* AlsaCreateSoftvol(SoftMixerT *mixer, AlsaStreamAudioT *stream, char *slaveid, AlsaSndCtlT *sndcard, char* ctlName, int max, int open); PUBLIC AlsaPcmCtlT* AlsaCreateRoute(SoftMixerT *mixer, AlsaSndZoneT *zone, int open); -PUBLIC AlsaPcmCtlT* AlsaCreateRate(SoftMixerT *mixer, const char* pcmName, AlsaPcmCtlT *pcmSlave, AlsaPcmHwInfoT *params, int open); +PUBLIC AlsaPcmCtlT* AlsaCreateRate(SoftMixerT *mixer, AlsaStreamAudioT *stream, const char* pcmName, AlsaPcmCtlT *pcmSlave, AlsaPcmHwInfoT *params, int open); PUBLIC AlsaPcmCtlT* AlsaCreateDmix(SoftMixerT *mixer, const char* pcmName, AlsaSndPcmT *pcmSlave, int open); // alsa-api-* + +PUBLIC int ApiLoopAttach(SoftMixerT *mixer, AFB_ReqT request, const char *, json_object * argsJ); +PUBLIC int ApiSourceAttach(SoftMixerT *mixer, AFB_ReqT request, const char *, json_object * argsJ); +PUBLIC int ApiSinkAttach(SoftMixerT *mixer, AFB_ReqT request, const char *, json_object * argsJ); +PUBLIC int ApiStreamAttach(SoftMixerT *mixer, AFB_ReqT request, const char * uid, const char *prefix, json_object * argsJ); +PUBLIC int ApiZoneAttach(SoftMixerT *mixer, AFB_ReqT request, const char *, json_object * argsJ); +PUBLIC int ApiRampAttach(SoftMixerT *mixer, AFB_ReqT request, const char *, json_object *argsJ); + +// helper used for attach verb,and also by the streams API for fake zones +PUBLIC AlsaSndZoneT * zoneCreate(SoftMixerT* mixer, const char * uid, json_object * argsJ); + PUBLIC AlsaLoopSubdevT *ApiLoopFindSubdev(SoftMixerT *mixer, const char *streamUid, const char *targetUid, AlsaSndLoopT **loop); -PUBLIC int ApiLoopAttach(SoftMixerT *mixer, AFB_ReqT request, const char *uid, json_object * argsJ); + PUBLIC AlsaPcmHwInfoT *ApiPcmSetParams(SoftMixerT *mixer, const char *uid, json_object *paramsJ); +PUBLIC void ApiPcmDelParams(SoftMixerT*, AlsaPcmHwInfoT*); + PUBLIC AlsaSndPcmT *ApiPcmAttachOne(SoftMixerT *mixer, const char *uid, snd_pcm_stream_t direction, json_object *argsJ); +PUBLIC AlsaSndPcmT * ApiPcmNew(SoftMixerT* mixer); +PUBLIC void ApiPcmDelete(SoftMixerT * mixer, AlsaSndPcmT * pcm); + PUBLIC AlsaVolRampT *ApiRampGetByUid(SoftMixerT *mixer, const char *uid); -PUBLIC int ApiRampAttach(SoftMixerT *mixer, AFB_ReqT request, const char *uid, json_object *argsJ); + PUBLIC AlsaPcmHwInfoT *ApiSinkGetParamsByZone(SoftMixerT *mixer, const char *target); -PUBLIC int ApiSinkAttach(SoftMixerT *mixer, AFB_ReqT request, const char *uid, json_object * argsJ); + PUBLIC AlsaSndPcmT *ApiSinkGetByUid(SoftMixerT *mixer, const char *target); PUBLIC AlsaSndCtlT *ApiSourceFindSubdev(SoftMixerT *mixer, const char *target); -PUBLIC int ApiSourceAttach(SoftMixerT *mixer, AFB_ReqT request, const char *uid, json_object * argsJ); -PUBLIC int ApiStreamAttach(SoftMixerT *mixer, AFB_ReqT request, const char *uid, const char *prefix, json_object * argsJ); + + PUBLIC AlsaSndZoneT *ApiZoneGetByUid(SoftMixerT *mixer, const char *target); -PUBLIC int ApiZoneAttach(SoftMixerT *mixer, AFB_ReqT request, const char *uid, json_object * argsJ); // alsa-effect-ramp.c PUBLIC AlsaVolRampT *ApiRampGetByUid(SoftMixerT *mixer, const char *uid); |