aboutsummaryrefslogtreecommitdiffstats
path: root/README.md
blob: c6a2c9d6ec9c639bb70d1cd35f22a44ce3950482 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
# 4a-hal-generic for 4A (AGL Advance Audio Architecture)

------------------------------------------------------------

* Object : Use a new api to centralize call to hals, automatically create hal api from configuration files
* Status : Working, improvements still expected (master)
* Author : Jonathan Aillet (jonathan.aillet@iot.bzh)
* Date   : July-2019

## Cloning needed repositories for current version

### Cloning `4a-hal-generic` repository

```bash
git clone https://gerrit.automotivelinux.org/gerrit/src/4a-hal-generic
```

### Cloning `4a-softmixer` repository

```bash
git clone https://gerrit.automotivelinux.org/gerrit/src/4a-softmixer
```

### Cloning `4a-alsacore` repository

```bash
git clone https://gerrit.automotivelinux.org/gerrit/src/4a-alsa-core
```

## Quick introduction to how hal are handled with 4a-hal-generic

* 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` 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

### 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.\
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 :
> Device Drivers > Sound card support > Advanced Linux Sound Architecture > Generic sound device

```bash
sudo modprobe snd-aloop
```

### Create a new hal json configuration corresponding to your audio hardware configuration

#### Information about audio json configuration files

* All audio hardware configuration files are a json description of your audio devices.
* 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.
* 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

* 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 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 (natively)

```bash
mkdir build
cd build
cmake -DWITHOUT_BLUEALSA=1 ..
make
```

## Compile (using a sdk)

```bash
mkdir build
cd build
cmake ..
make
```

## Using `4a-hal` binder

### Selection of the hal loaded at binding launch

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 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 (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
```

### 4A service running on target

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
systemctl | grep agl-service-audio-4a
```

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).

Note that 4A 'systemd' service file is available at `/var/local/lib/systemd/system/afm-service-agl-service-audio-4a*`.

You can also have information about 4a service status using `4a-status` command on your target.

### 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'
```

### 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, "all" : 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 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"
  }
}
```

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.

All the streams/controls listed are available as verbs of the hal api using `name` key value.

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.

For controls, you can find the targetted ALSA audio device using `cardNb` key and the
targetted ALSA control name using `cardControlName` key.

#### Play some music into a stream (natively)

Use the previously obtained card id (hw:X,X,X) to play audio in the selected stream :

```bash
gst123 --audio-output alsa=$AUDIO_HW_ENDPOINT your_audio_file.mp3
```

#### Play some music into a stream (on target)

This will request to 4a-hl api for multimedia role endpoint and play music into it :

```bash
4a-play /usr/share/4a/media/Happy_MBB_75.ogg
```

#### Set stream volume during playing

During playing, try the stream commands to change/ramp volume

Now you can use your hal api to send commands to the mixer. This way, you can change/ramp volume :

```bash
$HAL_API_NAME $SELECTED_STREAM { "volume" : "+10" }
```

```bash
$HAL_API_NAME $SELECTED_STREAM { "volume" : 70 }
```

```bash
$HAL_API_NAME $SELECTED_STREAM { "ramp" : { "uid" : $RAMP_UID, "volume" : "-10" } }
```

```bash
$HAL_API_NAME $SELECTED_STREAM { "ramp" : { "uid" : $RAMP_UID, "volume" : 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

#### 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 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",
}
```

#### 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.\
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 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 :

```bash
export CONTROL_CONFIG_PATH=/home/root/4a/smixer/etc:/home/root/4a/4a-hal/etc
```

## What is missing in this version

* Check that the external hals really exist at loading.
* Handling external hal status events.
* 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`).