diff options
author | Jonathan Aillet <jonathan.aillet@iot.bzh> | 2019-05-16 15:42:30 +0200 |
---|---|---|
committer | Jonathan Aillet <jonathan.aillet@iot.bzh> | 2019-07-31 11:04:54 +0200 |
commit | 40150cceba81a967d46d378dd3854a339bf40475 (patch) | |
tree | d29c2fac9a4f09a3b144001b271cd9de4d917d7d | |
parent | 5d9e6198cfef52e1d10fb02e25e9965e001b9b02 (diff) |
README.md updates
Update README.md to describe last version of hal functionalities and
how to compile/use 4a-hal.
BUG-AGL: SPEC-2683
Change-Id: I8ddf97872fc34c6e3fb3a9f7cc59a096849854fa
Signed-off-by: Jonathan Aillet <jonathan.aillet@iot.bzh>
-rw-r--r-- | README.md | 853 |
1 files changed, 704 insertions, 149 deletions
@@ -2,49 +2,94 @@ ------------------------------------------------------------ -* Object: Use a new api to centralize call to hals, automatically create hal api from configuration files -* Status: In Progress (master) -* Author: Jonathan Aillet jonathan.aillet@iot.bzh -* Date : June-2018 +* Object : Use a new api to centralize call to hals, automatically createhal api from configuration files +* Status : Working, improvements still expected (master) +* Author : Jonathan Aillet (jonathan.aillet@iot.bzh) +* Date : July-2019 -## Cloning repositories for current version +## Cloning needed repositories for current version -### Cloning 4a-hal-generic with its submodules +### Cloning `4a-hal-generic` repository -git clone --recurse-submodules https://github.com/iotbzh/4a-hal-generic.git +```bash +git clone https://gerrit.automotivelinux.org/gerrit/src/4a-hal-generic +``` -### Cloning 4a-softmixer hal-rc1 version (needed to make work '4a-hal-generic') with its submodules +### Cloning `4a-softmixer` repository -git clone --recurse-submodules https://github.com/iotbzh/4a-softmixer.git +```bash +git clone https://gerrit.automotivelinux.org/gerrit/src/4a-softmixer +``` -### Cloning 4a-alsacore with its submodules +### Cloning `4a-alsacore` repository -git clone --recurse-submodules https://gerrit.automotivelinux.org/gerrit/src/4a-alsa-core +```bash +git clone https://gerrit.automotivelinux.org/gerrit/src/4a-alsa-core +``` ## Quick introduction to how hal are handled with 4a-hal-generic -* At startup of the 4a-hal binding, a new api called '4a-hal-manger' will be created. +* At the startup of the `4a-hal` binding, a new api called `4a-hal-manager` will be created. This api is meant to provide verbs to list the loaded hals in your system and to know their current status. -* The '4a-hal-manager' will also create a new hal for each audio configuration file found. - These configuration files are used by the controller and are meant to be used with a mixer. -* External hal (e.g. loaded in another binding) can be loaded/unloaded into '4a-hal-manager' by reaching it - with this hal. It must provide information such as 'api' and 'uid' at loading. It must also provide - a subscription to an event that the '4a-hal-manager' will use to know this hal status. - WARNING: not fully implemented yet. +* The `4a-hal-manager` api will also create a new hal for each audio configuration file found.\ + These configuration files are handled by the controller for standard sections (`metadata`, `ressources`, ...), + and by internals-hal code for hal specific sections (`haldependencies`, `halmap`, ...). + If hal audio device(s) is/are found, the `halmixer` section is sent to the selected mixer + (with `haldependencies` resolution added to the call). +* External hal (e.g. another binding) can be registered/unregistered into `4a-hal-manager` by calling it + within the external hal. It must provide information such as `api` and `uid` at loading. It must also provide + a subscription to an event that the `4a-hal-manager` will use to know this hal status.\ + To be used by the `4a-hl-api`, external hals must provide same verbs and same response formats as internal hals + (see verb descriptions above).\ + WARNING : external hal handling is working but not fully implemented yet. ## Preparation -### Install Alsa Loopback (DEPRECATED) +### Mandatory packages + +* Regular packages to execute application framework binder, and to load bindings with it +(see [Download Packages for Binder](https://docs.automotivelinux.org/docs/en/master/devguides/reference/2-download-packages.html) +and [Installing the Binder Daemon](https://docs.automotivelinux.org/docs/en/master/devguides/reference/3-installing-binder-daemon.html)). + +* Requested packages to compile the binding : + * agl-cmake-apps-module + * json-c + * libsystemd + * afb-daemon + * libmicrohttpd + * uuid + * alsa + * afb-helpers + * ctl-utilities + * lua + +If you use an SDK to cross-compile this binding for your target, all packages should already be found after sourcing the SDK.\ +Alsa Loopback should also already be installed on your target.\ +So, you're not concerned by the three next steps.\ + +#### Example command for installation on ubuntu (18.04) + +```bash +sudo apt install agl-app-framework-binder-dev cmake agl-cmake-apps-module-bin libjson-c-dev agl-libmicrohttpd-devlibsdl2-dev liblua5.3-dev agl-libafb-helpers-dev agl-libappcontroller-dev +``` + +#### Example command for installation on fedora (29) + +```bash +sudo dnf install agl-app-framework-binder-devel cmake agl-cmake-apps-module libjson-c-dev libmicrohttpd-devel uuid-devel alsa-lib-devel agl-libafb-helpers-devel agl-libappcontroller-devel lua-devel +``` + +#### Install Alsa Loopback (for native execution) -You must have snd-aloop enabled as a module in the running kernel. -Check that this way on the target: +You must have snd-aloop enabled as a module in the running kernel.\ +Run this command to be sure you have `snd-aloop` running on your target : ```bash zcat /proc/config.gz | grep CONFIG_SND_ALOOP CONFIG_SND_ALOOP=m ``` -If it is not the case, run menuconfig and enable it under: +If it is not the case, run `menuconfig` and enable it under : > Device Drivers > Sound card support > Advanced Linux Sound Architecture > Generic sound device ```bash @@ -56,89 +101,136 @@ sudo modprobe snd-aloop #### Information about audio json configuration files * All audio hardware configuration files are a json description of your audio devices. -* They all must be in the 4a-hal-configs repository and must begin with 'hal-4a'. -* You can find some examples of these configurations in the 4a-hal-cfg-example folder.. +* Official hals are available in +[4a-hal-configs](https://gerrit.automotivelinux.org/gerrit/admin/repos/src/4a-hal-configs) repository. +* You can find examples of these configurations in this repository `4a-hal-cfg-example` folder. * Each configuration file found at startup will create a new hal with its own api. -* At 'init-mixer' hal command, your mixer configuration will be sent. +* If all mandatory `haldependencies` devices are found at hal api startup, `halmixer` section +will automatically be sent to the selected mixer.\ +However, `haldependencies` resolution will be added at mixer call. +This is done for the mixer to be able to get the required audio device card number(s) without having to search for them. #### What you need to set in this configuration file to make your audio work -* In `metadata` section: - * The `uid` field must be the path to your alsa audio device. - * The `api` field should be changed to the desired application framework api of your hal. -* For `onload`, `controls`, and `events` sections, please look at the controller documentation - (In ./app-controller/README.md) -* In `halcontrol` section: - * In this section you put controls corresponding to alsa control calls. - * If a control is not available, it will be registered in alsa using '4a-alsa-core'. - * These controls will be available as verbs for your hal. - * The value passed to these verbs should be a percentage, the hal will do the conversion to the correct alsa value. - To be recognized by the hal, the value should be associated to the key `val` and should be an integer. -* In `halmixer` section (that it is passed to the mixer): - * The `uid` field will be the name of the mixer corresponding to your hal. - * The `mixerapi` field should contain the name of the api to call for reaching the mixer - (not need to be changed if you use '4a-softmixer'). - * The `prefix` field is not mandatory, it is where you precise the prefix that will be applied - when the mixer attach call happens. All the streams the mixer creates will be prefixed with this field. - * In `ramps` section: - * Define the ramp that you can use in your mixer (ramps in example files can be used). - * The `uid` field is where you specify the name of the ramp. - * The ramp will set the current volume to the targeted volume step by step: - * The `delay` field is the delay between two volume modification. - * The `up` field is the volume increase in one step (when increasing volume is requested). - * The `down` field is the volume decrease in one step (when decreasing volume is requested). - * The `playbacks` section will contain your output audio information (such as the path to you alsa audio device - and the configuration of your device): - * A `uid` field that will be used by the mixer to identify the playback. - * The `params` field is an optional field where you can specify some parameters - for your playback (such as rate). - * The `sink` field is where you describe your playback: - * The `controls` field must contain the alsa control labels - that the mixer will use to set/mute volume on your audio device. - * The `channels` field must contain an object that will link an `uid` to - a physical output audio `port` that will be used in zone. - * The `captures` section will contain your input audio information (such as the path to you alsa audio device - and the configuration of your device): - * A `uid` field that will be used by the mixer to identify the capture. - * The `params` field is an optional field where you can specify some parameters - for your capture (such as rate). - * The `sink` field is where you describe your capture: - * The `controls` field must contain the alsa control labels - that the mixer will use to set/mute volume on your audio device. - * The `channels` field must contain an object that will link an `uid` to - a physical input audio `port` that will be used in zone. - * In `zones` section: (zones in example files can be used): - * You can define the zones that you want for your mixer. - * You must define which sink will be used in these zones. - * These zones will be used to define streams. - * The `sink` field must contain objects that will link a physical ouput audio port - (defined in `playbacks` section) using `target` field to a logical output audio `channel` - that will be used in zone. - * The `source` field must contain objects that will link a physical input audio port - (defined in `captures` section) using `target` field to a logical input audio `channel` - that will be used in zone. - * In `streams` section: (streams in example files can be used): - * You can define the streams that you want for your mixer. - * Mandatory fields: - * A `uid` field, it is the name used by the mixer to identify streams (e.g. when using `info` verb) - * The `verb` field is the name used by the mixer to declare the stream verb - (but prefixing it with `prefix` if defined). - It is also used by the hal to declare a verb to make it accessible from a hal point of view. - * The `zone` field must correspond to the wanted zone of the stream. - * Optional fields: - * The `source` is where you can precise which loop to use for this stream (not the default one). - The loop are defined in the mixer configuration file. - * The `params` is where you can specify some parameters for your stream (such as rate). - * `volume` and `mute` fields are initiate values of the stream. +* For information about `metadata`, `ressources`, `onload`, `controls`, and `events` sections, +please look at [controller documentation](https://docs.automotivelinux.org/docs/en/master/devguides/reference/ctrler/controllerConfig.html) +* `haldependencies` section :\ +This section is used to look for a/some specific audio devices(s). +Each found device will be saved with its corresponding (ALSA) card number.\ +`halmap` and `halmixer` sections (described above) use these dependencies to get the (ALSA) audio card number(s).\ +`haldependencies` section can contain one dependency object, or an array of dependency objects. +A dependency (one object) is resolved if only one audio card is found using specified search keys (it can be : +`cardNb`, `cardPath`, `cardId`, `cardShortName`, `cardLongName`, `cardDriver`, `cardMixerName`, `cardComponents`, +`playbackDeviceId`, `playbackDeviceName`, `AnyOf`).\ +Most of these keys can have an array as a value. If so, it will behave as an XOR condition, and multiple searches +will be performed to find an audio card. However, remember that a dependency is validated if only one audio card is found.\ +Available keys : + * `uid` key is the name of the dependency (it's a mandatory key). If the dependecy is resolved, + `halmap` and `halmixer` sections will be able to use this key value to get corresponding (ALSA) card number. + * `class` key is an optional key that defines the class of the dependency + (If no `class` key is specified, dependency will be considered as a `static` class).\ + Three classes are available : + * `mandatory` class means that if the dependency is not resolved at hal startup, hal will stop and send back an error. + * `static` class means that no error will be thrown if the dependency is not resolved at startup + and the dependency will be considered as not available.\ + If `halmap` or `halmixer` sections refer to a not available dependency, + associated `halmap`/`halmixer` parts will be ignored without returning any errors. + * `dynamic` class means that the dependency can be resolved dynamically (at startup or later). + If the device is found while the binding is runing, a new resolution for `halmap` and `halmixer` sections + will be triggered to use newly resolved dependency.\ + `dynamic` class is **NOT YET IMPLEMENTED**, it is working like a `static` class for now. + * `cardNb` key is an optional key used to search for an audio card using an (ALSA) card number + (e.g. '1' in 'hw:1', '2' in 'hw:2'), value should be an integer or an array of integers. + * `cardPath` key is an optional key used to search for an audio card using the audio card linux path + (e.g. '/dev/snd/by-path/...'), value should be a string or an array of strings. + * `cardId` key is an optional key used to search for an audio card using (ALSA) card id + (e.g. 'Loopback' in 'hw:Loopback', 'PCH' in 'hw:PCH'), value should be a string or an array of strings. + * `cardShortName` key is an optional key used to search for an audio card using (ALSA) card shortname + (e.g. 'HDA Intel PCH', 'USB Audio Device'), value should be a string or an array of strings. + * `cardLongName` key is an optional key used to search for an audio card using (ALSA) card longname + (e.g. 'HDA Intel PCH at 0xdc248000 irq 159', 'C-Media Electronics Inc. USB Audio Device at usb-0000:00:14.0-2.1, full speed'), + value should be a string or an array of strings. + * `cardDriver` key is an optional key used to search for an audio card using (ALSA) card driver + (e.g. 'HDA-Intel', 'USB-Audio'), value should be a string or an array of strings. + * `cardMixerName` key is an optional key used to search for an audio card using (ALSA) card mixer name + (e.g. 'Realtek ALC257', 'USB Mixer'), value should be a string or an array of strings. + * `cardComponents` key is an optional key used to search for an audio card using (ALSA) card components + (e.g. 'HDA:10ec0257,17aa225d,00100001 HDA:8086280b,80860101,00100000', 'USB0d8c:0014'), + value should be a string or an array of strings. + * `playbackDeviceNb` key is an optional key used to search for an audio card playback device + using (ALSA) playback device number (e.g. '2' in 'hw:0,2', '4' in 'hw:1,4'), + value should be an integer or an array of integers. + * `playbackDeviceId` key is an optional key used to search for an audio card playback device + using (ALSA) playback device id (e.g 'HDMI 1', 'HDMI 2'), value should be a string or an array of strings. + * `playbackDeviceName` key is an optional key used to search for an audio card playback device + using (ALSA) playback device name (e.g 'HDMI 1', 'HDMI 2'), value should be a string or an array of strings. + * `AnyOf` key is an optional key that can contain an object of properties. + An object allows the combination of several of the keys previously described, however, + these keys cannot contain arrays as a value. + Each property in the object will be considered as an input of an XOR condition. +* `halmap` section :\ +This section is meant to map ALSA device controls to application framework verbs.\ +When you use ALSA, the control names are not standardized +(i.e. control to get/set master volume are not named the same way for different audio cards).\ +Using halmap, it is possbile to provide a standardized verb to get/set control values in each hal.\ +Verbs created by halmap will also standardize control value ranges, i.e., a verb mapped to an integer ALSA control +will only take a percentage as a value (conversion is done by 4a-hal binding).\ +That means that you can abstract which audio device you are using by calling hal halmap verbs. +Also, these verbs are meant to be used by higher level applications.\ +It is possible to call another binding or a specific code (c or lua) using +[controller action fonctionnality](https://docs.automotivelinux.org/docs/en/master/devguides/reference/ctrler/controllerConfig.html#actions-categories) +when a control is get/set.\ +In combination with `create` key in halmap, it is possible to create an ALSA audio control (not handled by ALSA driver) that will use controller action fonctionnality to perform an action when this ALSA audio control is set/get.\ +`halmap` section can contain only one halmap object, or an array of halmap objects.\ +Available keys : + * `uid` key is a mandatory key to identify halmap controls related to a specific audio device. + * `info` key is an optional key to provide information about halmap controls related to a specific audio device. + * `target` key is a mandatory key that is used to get ALSA audio card number, + this key must correspond to a `hal-dependency` `uid` key to be resolved. + * `controls` section is one or several hal verbs that can be used to call ALSA controls + (mandatory, can be an object or an array of objects). + * `uid` key is a mandatory key to identify a halmap control. + * `info` key is an optional key to provide information about a halmap control. + * `alsa` section is a mandatory object that describes the ALSA control to map. + If `create` key is provided in this section, it will create an ALSA control instead of searching for it. + * `name` key is the name of the ALSA control to map. + If it is an ALSA control creation, this name will be used for ALSA control registration + (`name` key is optional for search, but mandatory for control creation). + * `numid` key is an optional key that can only be used to search for the id of the control to map. + * `value` key is an optional key to set a default value to the mapped control. + * `create` section is an optional object that is used to describe ALSA control to create. + * `type` key is a mandatory key to specify ALSA control type for ALSA control creation. + * `count` key is a mandatory key to specify ALSA control number of value(s) for ALSA control creation. + * `minval` key is a mandatory key to specify ALSA control minimum value for ALSA control creation. + * `maxval` key is a mandatory key to specify ALSA control maximum value for ALSA control creation. + * `step` key is a mandatory key to specify ALSA control value step for ALSA control creation. + * `action` key is using + [controller action fonctionnality](https://docs.automotivelinux.org/docs/en/master/devguides/reference/ctrler/controllerConfig.html#actions-categories) + to specificy an action to call each time the ALSA control is set/get. +* `halmixer` section is a section that is transfered to the mixer, for full description of this section, please look at +[mixer documentation](https://gerrit.automotivelinux.org/gerrit/gitweb?p=src/4a-softmixer.git;a=blob;f=README.md;h=34eb934164657a7af993d1c50563c54bcf21ef46;hb=refs/heads/master). + +N.B. : Examples of configuration files are provided in +this repository `4a-hal-cfg-example` directory to illustrate these functionalities. ### Note about using a USB device -Dynamic handling of USB devices is not yet implemented, so you need to modify the 'hal-4a-2ch-generic-usb.json' -to change the `uid` value in `metadata` section and `path` values in `playbacks` and `captures` sections. -All these values should be replaced by the alsa entry path of your usb device, these entry are listed -under directory '/dev/snd/by-id/...'. +Dynamic handling of devices is not yet implemented.\ +To have a working USB hal, you will need to modify the 'hal-4a-2ch-generic-usb.json' (in `4a-hal-cfg-example` directory) +to change key values in `haldependencies` section and `path` values in `playbacks` and `captures` sections.\ +All these values should be replaced by the alsa information of your usb device.\ +The usb device should also be plugged in at binder startup. -## Compile (for each repositories) +## Compile (natively) + +```bash +mkdir build +cd build +cmake -DWITHOUT_BLUEALSA=1 .. +make +``` + +## Compile (using a sdk) ```bash mkdir build @@ -147,127 +239,590 @@ cmake .. make ``` -## Using '4a-hal' binder +## Using `4a-hal` binder ### Selection of the hal loaded at binding launch -Currently, the 4a-hal binding will try to launch a hal for each json audio configuration -files found in path specified with CONTROL_CONFIG_PATH (an audio configuration file should begin with 4a-hal-*). -If you don't want a hal to be launch with the binding, you can just rename/remove the corresponding +Currently, the `4a-hal` binding will try to create a hal api for each json audio configuration +file found in the path specified with `CONTROL_CONFIG_PATH` environment variable +(an audio configuration file should begin with `4a-hal-`).\ +If you don't want a hal to be launched with the binding, you can just rename/remove the corresponding audio json configuration file. -Be aware that every hal which will find its associated audio device will attach to the mixer. -So, if you work on M3 and want to use an external usb audio device, be sure to rename the m3 configuration file. +Be aware that every hal which finds its associated audio device will attach to the mixer. +So, if you work on Renesas R-Car M3 and want to use an external usb audio device, be sure to rename the m3 configuration file to prevent it from being selected (on target, loaded hal configuration files are stored in `/usr/libexec/agl/4a-hal/etc`) -### Run your binder from shell +### Run your binder from shell (native execution) ```bash -afb-daemon --name=afb-4a --workdir=$PATH_TO_4a-softmixer/build --binding=$PATH_TO_4a-alsa-core/build/alsa-binding/afb-alsa-4a.so --binding=$$PATH_TO_4a-softmixer/build/package/lib/softmixer-binding.so --binding=$PATH_TO_4a-hal-generic/build/4a-hal/4a-hal.so --roothttp=$PATH_TO_4a-softmixer/build/package/htdocs --no-ldpaths --port=1234 --token= -vvv +afb-daemon --name=afb-4a --workdir=$PATH_TO_4a_softmixer/build --binding=$PATH_TO_4a_alsa_core/build/alsa-binding/afb-alsa-4a.so --binding=$PATH_TO_4a_softmixer/build/package/lib/softmixer-binding.so --binding=$PATH_TO_4a_hal_generic/build/4a-hal/4a-hal.so --roothttp=$PATH_TO_4a_softmixer/build/package/htdocs --no-ldpaths --port=1234 --token= -vvv ``` -### Connect your binder +### 4A service running on target -Connect to your 4a binder using afb-client-demo +If 4A is available on your AGL version, 4A service should run at target startup, you can get its service name by using command ```bash -afb-client-demo ws://localhost:1234/api?token= +systemctl | grep agl-service-audio-4a ``` -### List the ready hal +Using this service name, it is possible to get service logs (using `journalctl -u $4A_SERVICE_NAME` command), +and start/stop/restart this service (using `systemctl start $4A_SERVICE_NAME` / `systemctl stop $4A_SERVICE_NAME` / +`systemctl restart $4A_SERVICE_NAME` commands). + +To update the cross-compiled binding, you can replace target remote '/usr/libexec/agl/4a-hal/lib/4a-hal.so' binding +by your local './package/lib/4a-hal.so' binding using `scp`. +This also should be done if you want to update `4a-hal` plugin(s) (by transferring the corresponding plugin(s) on target). -In the connected client, try to list the ready hal: +Note that 4A 'systemd' service file is available at `/var/local/lib/systemd/system/afm-service-agl-service-audio-4a*`. -```4a-hal-manager loaded``` +You can also have information about 4a service status using `4a-status` command on your target. -And now with more information: +### Connect to 4A binder + +Connect to 4A binder using afb-client-demo + +```bash +afb-client-demo -H ws://localhost:1234/api?token= +``` + +N.B. : You can change the ip/port/token to connect to a remote binding + +```bash +afb-client-demo -H ws://minnow03:31002/api?token='HELLO' +``` -```4a-hal-manager loaded { "verbose" : true }``` +### List ready hals + +In the connected client command line, try to list the ready hal : + +```bash +4a-hal-manager loaded +``` + +Output example : + +```json +ON-REPLY 1:4a-hal-manager/loaded: OK +{ + "response":[ + "4a-hal-csl-cm106-8ch-usb" + ], + "jtype":"afb-reply", + "request":{ + "status":"success", + "info":"Requested data" + } +} +``` + +And now with more information : + +```bash +4a-hal-manager loaded { "verbose" : true } +``` + +Output example : + +```json +ON-REPLY 1:4a-hal-manager/loaded: OK +{ + "response":[ + { + "api":"4a-hal-csl-cm106-8ch-usb", + "status":2, + "internal":1, + "uid":"CSL-CM106-USB-4A-HAL", + "info":"4a hal for CSL CM106 8ch USB device", + "author":"Jonathan Aillet", + "version":"1.0", + "date":"2018-06-09", + "dependencies":[ + { + "uid":"dependency-csl-cm106-8ch-usb", + "cardNb":"hw:3" + } + ] + } + ], + "jtype":"afb-reply", + "request":{ + "status":"success", + "info":"Requested data" + } +} +``` ### Play with an 'internal' hal (described in a json configuration file) -#### Get streams information +#### Get hal information + +Now, you can obtain information about your initialized internal hal : + +```bash +$HAL_API_NAME info +``` + +Output example : + +```json +ON-REPLY 1:4a-hal-csl-cm106-8ch-usb/info: OK +{ + "response":{ + "streams":[ + { + "name":"multimedia", + "cardId":"hw:0,0,2" + }, + { + "name":"navigation", + "cardId":"hw:0,0,3" + }, + { + "name":"emergency", + "cardId":"hw:0,0,4" + }, + { + "name":"legacy", + "cardId":"hw:0,0,0" + }, + { + "name":"radio_stream", + "cardId":"hw:0,0,5" + } + ], + "controls":[ + { + "name":"agl-master-capture-volume", + "info":"none", + "target":"dependency-csl-cm106-8ch-usb", + "available":true, + "cardNb":3, + "cardControlName":"Mic Capture Volume", + "halmap-uid":"halmap-csl-cm106-8ch-usb", + "halmap-info":"none" + }, + { + "name":"agl-master-playback-volume", + "info":"none", + "target":"dependency-csl-cm106-8ch-usb", + "available":true, + "cardNb":3, + "cardControlName":"Speaker Playback Volume", + "halmap-uid":"halmap-csl-cm106-8ch-usb", + "halmap-info":"none" + }, + { + "name":"hal-ping", + "info":"ping this hal through alsa", + "target":"dependency-csl-cm106-8ch-usb", + "available":true, + "cardNb":3, + "cardControlName":"Hal-Ping", + "halmap-uid":"halmap-csl-cm106-8ch-usb", + "halmap-info":"none" + } + ], + "dependencies":[ + { + "uid":"dependency-csl-cm106-8ch-usb", + "class":"mandatory", + "available":true, + "cardNb":3, + "cardId":"Device", + "cardShortName":"USB Sound Device", + "cardLongName":"USB Sound Device at usb-0000:00:14.0-1.1, full speed", + "cardDriver":"USB-Audio", + "cardMixerName":"USB Mixer", + "cardComponents":"USB0d8c:0102", + "extendedCardNb":"hw:3" + } + ] + }, + "jtype":"afb-reply", + "request":{ + "status":"success", + "info":"Requested data" + } +} +``` -Now, you can obtain streams information of your initialized internal hal: +Firstly, you can get the audio device(s) used by your hal in `dependencies` section. +That way you can have correspondance between `uid` and ALSA `extendedCardNb`.\ +FYI, `halmap` and `halmixer` sections are able to dynamically get `extendedCardNb` by using dependency `uid` key value as `target` key value. -```*halapiname* info``` +All the streams/controls listed are available as verbs of the hal api using `name` key value. -All the streams listed are available as a verb of the hal api using `name` field. -You can also get the corresponding card id of the stream in `cardId` field. +For streams, you can get the corresponding ALSA card id of the stream in `cardId` key value. The card id stream format is `hw:X,X,X` and can be used to play music. -#### Play some music into a stream +For controls, you can find the targetted ALSA audio device using `cardNb` key and the +targetted ALSA control name using `cardControlName` key. -WARNING: Current version does not handle audio rate conversion, using gstreamer -or equivalent with audio hardware params is mandatory. +#### Play some music into a stream (natively) -Use the previously obtain card id to play audio in the selected stream: +Use the previously obtained card id (hw:X,X,X) to play audio in the selected stream : -`gst123 --audio-output alsa=hw:X,X,X your_audio_file.mp3` +```bash +gst123 --audio-output alsa=$AUDIO_HW_ENDPOINT your_audio_file.mp3 +``` -#### During playing, try the stream commands to change/ramp volume +#### Play some music into a stream (on target) -Now you can use your hal api to send commands to mixer. This way, you can change/ramp volume: +This will request to 4a-hl api for multimedia role endpoint and play music into it : -`*halapiname* *selected_stream* { "volume" : "+10" }` +```bash +4a-play /usr/share/4a/media/Happy_MBB_75.ogg +``` -`*halapiname* *selected_stream* { "volume" : 70 }` +#### Set stream volume during playing -`*halapiname* *selected_stream* { "ramp" : "-10" }` +During playing, try the stream commands to change/ramp volume -`*halapiname* *selected_stream* { "ramp" : 100 }` +Now you can use your hal api to send commands to the mixer. This way, you can change/ramp volume : -#### Warning +```bash +$HAL_API_NAME $SELECTED_STREAM { "volume" : "+10" } +``` -Alsa try to automatically store current state into `/var/lib/alsa/asound.state` -that may result to odd situation during development/testing. In order to clean -up your Alsa snd-aloop config, a simple `rmmod` might not be enough in some case -you may have to delete `/var/lib/alsa/asound.state` before applying `modprobe`. +```bash +$HAL_API_NAME $SELECTED_STREAM { "volume" : 70 } +``` -In case of doubt, check with following command that you start from a clear green field +```bash +$HAL_API_NAME $SELECTED_STREAM { "ramp" : "-10" } +``` ```bash -rmmod snd-aloop && modprobe --first-time snd-aloop && amixer -D hw:Loopback controls | grep vol +$HAL_API_NAME $SELECTED_STREAM { "ramp" : 100 } +``` + +Example : + +```json +4a-hal-csl-cm106-8ch-usb multimedia { "volume" : "+10" } + +ON-REPLY 1:4a-hal-csl-cm106-8ch-usb/multimedia: OK +{ + "response":{ + "volnew":70, + "volold":60 + }, + "jtype":"afb-reply", + "request":{ + "status":"success", + "info":"Action cm106-usb#multimedia correctly transferred to smixer without any error raised" + } +} ``` +N.B. : Values are normalized to a 0-100 range + +##### `all_streams` verb + +`all_streams` verb should also be available to send a command to all available streams : + +```json +4a-hal-csl-cm106-8ch-usb all-streams { "volume" : "+10" } + +ON-REPLY 1:4a-hal-csl-cm106-8ch-usb/all-streams: OK +{ + "response":{ + "multimedia":{ + "volnew":80, + "volold":70 + }, + "navigation":{ + "volnew":80, + "volold":70 + }, + "emergency":{ + "volnew":70, + "volold":60 + }, + "legacy":{ + "volnew":60, + "volold":50 + }, + "radio_stream":{ + "volnew":80, + "volold":70 + } + }, + "jtype":"afb-reply", + "request":{ + "status":"success", + "info":"Actions correctly transferred to all streams without any error raised" + } +} +``` + +#### Set control value during playing + +If a hal control to set/get master volume on your audio device is defined, you can set value using : + +```bash +$HAL_API_NAME $SELECTED_CONTROL { "value" : "60" } +``` + +```bash +$HAL_API_NAME $SELECTED_CONTROL { "value" : "-10" } +``` + +Example : + +```json +4a-hal-csl-cm106-8ch-usb agl-master-playback-volume { "value" : "-10" } + +ON-REPLY 1:4a-hal-csl-cm106-8ch-usb/agl-master-playback-volume: OK +{ + "response":{ + "previous":[ + 70, + 70, + 70, + 70, + 70, + 70, + 70, + 70 + ], + "current":[ + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60 + ] + }, + "jtype":"afb-reply", + "request":{ + "status":"success", + "info":"Values correctly applied on alsa control" + } +} +``` + +N.B. : + +* Values are normalized to a 0-100 range. +* The number of values in the reponse depends on the number of values of the ALSA control. + ### Load an 'external' hal -To load an external to '4a-hal-manger', you need to you use an 'api_call' from you hal binding. -With this 'api_call' you must sent a json description of your api: +#### Register your external hal + +To load an external hal to `4a-hal-manager`, you need to use an api call +to `load` verb of `4a-hal-manager` api from your external hal.\ +Within this call you must provide a json description of your api, corresponding to the following description : ```json "metadata" : { "api" : "mandatory, string that is your hal binding api", - "uid" : "mandatory, string that specify your hal uid (usually the device used by your hal)", + "uid" : "mandatory, string that specifies your hal uid (usually the device used by your hal)", "info" : "optional, string that describes your hal", "author" : "optional, string that says who is the author of your hal", "version" : "optional, string that says what is the version of your hal", "date" : "optional, string that says the date of your hal", - "snd-dev-id": "optional, integer that specify you alsa device id (hw:X), -1 if not available" } ``` -Your hal must also have a 'subscribe' verb available and event name 'hal_status'. +#### Provide an event to share you hal status + +Your hal must also have a `subscribe` verb available and event named `status`. -At external hal loading, the '4a-hal-manager' will subscribe to this event. +At external hal loading, the `4a-hal-manager` will subscribe to this event.\ Within your hal, you must generate an event each time the status of your hal changes. +Here are the possible status (integer value) : + +* Unavailable = 0 +* Available = 1 +* Ready = 2 + +#### Verbs to provide and json response formats recognized by `4a-hl-api` + +Be aware that only `info`/`streams` verbs are mandatory, `controls` can also be implemented but they are optional. + +##### `info` verb (mandatory) + +Response format : + +```json +"response":{ + "streams":[ + { + "name":"multimedia", + "cardId":"hw:0,0,2" + }, + { + "name":"navigation", + "cardId":"hw:0,0,3" + }, + { + "name":"emergency", + "cardId":"hw:0,0,4" + }, + { + "name":"legacy", + "cardId":"hw:0,0,0" + }, + { + "name":"radio_stream", + "cardId":"hw:0,0,5" + } + ], + "controls":[ + { + "name":"agl-master-capture-volume", + "info":"none", + "target":"dependency-csl-cm106-8ch-usb", + "available":true, + "cardNb":3, + "cardControlName":"Mic Capture Volume", + "halmap-uid":"halmap-csl-cm106-8ch-usb", + "halmap-info":"none" + }, + { + "name":"agl-master-playback-volume", + "info":"none", + "target":"dependency-csl-cm106-8ch-usb", + "available":true, + "cardNb":3, + "cardControlName":"Speaker Playback Volume", + "halmap-uid":"halmap-csl-cm106-8ch-usb", + "halmap-info":"none" + }, + { + "name":"hal-ping", + "info":"ping this hal through alsa", + "target":"dependency-csl-cm106-8ch-usb", + "available":true, + "cardNb":3, + "cardControlName":"Hal-Ping", + "halmap-uid":"halmap-csl-cm106-8ch-usb", + "halmap-info":"none" + } + ], + "dependencies":[ + { + "uid":"dependency-csl-cm106-8ch-usb", + "class":"mandatory", + "available":true, + "cardNb":3, + "cardId":"Device", + "cardShortName":"USB Sound Device", + "cardLongName":"USB Sound Device at usb-0000:00:14.0-1.1, full speed", + "cardDriver":"USB-Audio", + "cardMixerName":"USB Mixer", + "cardComponents":"USB0d8c:0102", + "extendedCardNb":"hw:3" + } + ] +} +``` + +Note that, for `4a-hl-api`, only streams section is mandatory. + +##### stream verbs (mandatory) + +E.g. in some standard hals, available streams can be `multimedia`, `navigation`, or `emergency`. + +Response format : + +```json +"response":{ + "volnew":70, + "volold":60 +} +``` + +##### `all-streams` verb (mandatory) + +`all-streams` verb transfers an action to perform to all hal streams, so, +its response is a concatenation of all stream reponses. + +Response format : + +```json +"response":{ + "multimedia":{ + "volnew":80, + "volold":70 + }, + "navigation":{ + "volnew":80, + "volold":70 + }, + "emergency":{ + "volnew":70, + "volold":60 + }, + "legacy":{ + "volnew":60, + "volold":50 + }, + "radio_stream":{ + "volnew":80, + "volold":70 + } +}, +``` + +##### control verbs (optional) + +Response format : + +```json +"response":{ + "previous":[ + 70, + 70, + 70, + 70, + 70, + 70, + 70, + 70 + ], + "current":[ + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60 + ] +}, +``` + ### Known issues #### Fail to find json configuration files -When compiling and executing 4a-hal-generic and 4a-softmixer for a specific target using an sdk, -some bindings won't find there json configuration files. -This issue does not appears when compiling and deploying the 4a-hal-generic/4a-softmixer -with yocto because a recipe its taking charge of these issues. +When compiling and executing `4a-hal-generic` and `4a-softmixer` for a specific target using an sdk, +some bindings won't find their json configuration files. +This issue does not appear when compiling and deploying the 4a-hal-generic/4a-softmixer +with yocto because a recipe is taking charge of these issues. Nevertheless, to make the bindings find their configuration files, you can export the `CONTROL_CONFIG_PATH` environment variable to the directories where the configuration files are stored. + Example on a target where the 4a-hal and 4a-softmixer are deployed into `/home/root/4a` directory : -`export CONTROL_CONFIG_PATH=/home/root/4a/smixer/etc:/home/root/4a/4a-hal/etc`. + +```bash +export CONTROL_CONFIG_PATH=/home/root/4a/smixer/etc:/home/root/4a/4a-hal/etc +``` ## What is missing in this version -* Check that external hal really exist at loading +* Check that the external hals really exist at loading. * Handling external hal status events. -* Generation of an '4a-hal-manager' event when a hal status change. +* Generation of a '4a-hal-manager' events when a hal status changes. * Dynamic handling of USB devices. +* Documentation about hal events (subscribe/unsubscribe to events, available events, response formats ofr `4a-hl-api`). |