aboutsummaryrefslogtreecommitdiffstats
AgeCommit message (Collapse)AuthorFilesLines
2019-05-14Merge branch 'sandbox/tbultel/spec-2387' into guppyguppy_7.0.4guppy_7.0.3guppy_7.0.2guppy/7.0.4guppy/7.0.3guppy/7.0.27.0.47.0.37.0.2guppyThierry Bultel15-172/+403
Bug AGL: SPEC-2387 This brings the following commits from master: * 43df828 loops/avirt: forget saved loops after creation * 622096c plug route: added a calculation for the number of physical c.. * c950295 streams: improved log output * 7520fbf core-pcm: fixed channels setting issues * 293fe69 core pcm: use the same model for writing and reading audio * e355716 pcm plugs: rework the alsa config cleanup * eb45566 alsa-api-pcm: added an 'optional' parameter * 93bf6e6 alsa-transaction: simplify the cleanup * bb70b48 alsa-api-pcm: added support of quirks * 93ca785 alsa-utils-dump: added missing ending null char Change-Id: I8ccc641b1f6827873e479185c0098d732d1b2b0a Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
2019-05-13loops/avirt: forget saved loops after creationsandbox/tbultel/spec-2387Thierry Bultel2-6/+11
avirt needs a backup of loops, before creating the streams. However, this breaks software dynamic streams such as those of of type bluez-alsa, because the logic was re-calling the loop creation at each call of the 'attach' verb. The fix simply consists in forgetting the saved loops once they are created Bug-AGL: SPEC-2387 Change-Id: I63f492b89233bed12de583de6e1077ac1c9c3ccf Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
2019-05-13plug route: added a calculation for the number of physical channelsThierry Bultel2-5/+17
Adds (mainly for debug purpose) a calculation on the actual number of physical channels that are used by the created ttable Change-Id: I5717046003851ebe297a494dcdd97c4d67e34d0b Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
2019-05-13streams: improved log outputThierry Bultel1-4/+4
Fixed some incomplete log messages Change-Id: Ib620905043b6ae3628d886cd8b4b3155005e6862 Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
2019-05-13core-pcm: fixed channels setting issuesThierry Bultel2-13/+24
Recent tries on the minnow board have show that the setting of channels on a PCM must be done -after- the setting of the rate. When not doing that, there can be issues (really, complicated to find) around the boundaries values (open intervals) on the period bytes. Additionally, the number of channels can now be forced in the json file. Change-Id: I2c20853daadf9ccab06be6e04d1a185440f57780 Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
2019-05-13core pcm: use the same model for writing and reading audioThierry Bultel2-67/+177
Reading sound frames relies on usage of poll before calling snd_pcm_writei Recent seeks for bugs and CPU load issues have shown that the same thing must be done on the write side. Thus this commit uses the same mechanism, including the dedicated event pipe for the thread termination. Change-Id: Ifd5407c9e27da7801623583a6f7d4a2e845b43ea Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
2019-05-13pcm plugs: rework the alsa config cleanupThierry Bultel8-30/+50
The alsa config (for softvol, routes, rate conversion ...) was cleaned up by the owner stream or zone, at their deletion time. This was a mistake, because when the stream or zone creation was not complete, the cleanup of the configuration was not done. Instead of doing that, the config is attached to the plug objects as private data (in the AlsaPcmCtlT structure). Since the AlsaPcmCtlT are always recorded in the creation transaction, it is easy to call the cleaning callback (when it exists) when the transaction is deleted. Change-Id: I952871518a20bfe0be6398887bc747338cf574fb Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
2019-05-13alsa-api-pcm: added an 'optional' parameterThierry Bultel3-5/+41
This adds a boolean 'optional' parameter for both playback and capture devices. When the device is not detected, the stream(s) that use is are not created, without leading to the exit of the softmixer. Change-Id: I3effbd61bfe1d1d4a7cde573354b9db791f759cc Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
2019-05-13alsa-transaction: simplify the cleanupThierry Bultel4-39/+36
This simplifies the invocation of cleanup, by only using AlsaMixerTransactionDelete that performs the 3 actions of cleanup, removal from list, and memory freeing. Fixes a bug at MixerExit, because the first transaction was not removed from the list and led to a double free error. Also added a boolean parameter to AlsaMixerTransactionObjectDelete (was AlsaMixerTransactionObjectForget before), that decides wether or not the found object must be destroyed with its destructor (for most of the cases) or simply freed in memory (which is needed for loop device). Change-Id: I2eacbf80a22e3d556dc432d393a1807fcd7c47fb Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
2019-05-13alsa-api-pcm: added support of quirksThierry Bultel5-5/+44
Adds an optional array of quirks in the parameters of playback and captures. For now, the only known quirk is a needed workarround for writing sound output on the minnow board. Change-Id: I6c65d110a1f9333ccb77cd8f4eeb9c088d0d2eca Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
2019-05-13alsa-utils-dump: added missing ending null charThierry Bultel1-0/+1
For some reason, snd_pcm_hw_params_dump does not add a null char at the end of the dumped string. This made weird chars appear in the console Change-Id: I6f2895e730e9bbd0f78139505f9b9e68dd164f2e Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
2019-04-16Revert libavirt for use as a submodule in guppyMark Farrugia1-0/+0
Revert latest changes to libavirt that would use it as a system lib. This breaks older compatibility with guppy. Change-Id: I253b6a744ad3b43e848703af7e1c3588da065553 Signed-off-by: Mark Farrugia <mark.farrugia@fiberdyne.com.au>
2019-04-09Updates for latest libavirt, adds avirt cleanupguppy_7.0.1guppy/7.0.17.0.1Mark Farrugia4-3/+30
Cleanup for avirt is introduced. There are still some issues with this when invoked whilst a PCM is active, This now allows 4A to be restarted without a reboot. Loops must be deleted last to avoid any cleanup issues, so to enforce this a new transaction API is added: AlsaMixerTransactionObjectAddTail. Change-Id: Ide4bbb319e8c6a2f4209ab957d80a54690f76de4 Signed-off-by: Mark Farrugia <mark.farrugia@fiberdyne.com.au>
2019-04-08submodule: libavirt: Correct gerrit src linkPierre MARZIN1-1/+1
Change-Id: If57bcb184d29d38fd38093a2cf7a7c1e40c38254 Signed-off-by: Pierre MARZIN <pierre.marzin@iot.bzh>
2019-04-05Fix a SIGSEGV during initializationJosé Bollo1-10/+8
During the initialisation of 4a-softmixer, when the function 'ProcessOneAvirtSubdev' fails, the function 'AttachOneLoop' was crashing because it tried to call 'snd_ctl_close' with a NULL pointer. This change fixes it. A test is introduced because depending on the kind of loop, the order of initialization of control versus subdevs differs. At the same time, some gotos are improved to avoid a dummy test -this are also virtual fixes-. Also a tiny refactor of the 3 times declared variable 'subdev' is expected to improve the readability. Bug-AGL: SPEC-2287 Change-Id: Ie5231a1064090d772ea0ea7d86ad8c8d79b38d72 Signed-off-by: José Bollo <jose.bollo@iot.bzh>
2019-02-10Add support for AVIRTMark Farrugia8-98/+328
Leverage the new AVIRT driver for a more secure, more dynamically configurable loopback sound driver. To use, replace the file smixer-4a-default.json with smixer-4a-avirt.json, at /usr/libexec/agl/smixer/etc The existing snd-aloop configuration is not broken by this change. The submodule libavirt is temporary, and will be transformed into a library. Change-Id: I827636656c109a7393ad77997e05069a2462ea46 Signed-off-by: Mark Farrugia <mark.farrugia@fiberdyne.com.au>
2019-02-04Add gitreview file for guppy branchguppy_7.0.0guppy_6.99.5guppy/7.0.0guppy/6.99.57.0.06.99.5Jan-Simon Möller1-0/+1
Signed-off-by: Jan-Simon Möller <jsmoeller@linuxfoundation.org>
2019-01-18Merge "bluetooth sco: fixed the softvol open error"halibut_7.90.0halibut/7.90.0guppy_6.99.4guppy/6.99.47.90.06.99.4Jan-Simon Moeller3-3/+5
2019-01-17Prevents setting of ALSA controls out-of-rangeJonathan Aillet1-0/+14
Prevents setting of ALSA control values out-of-range for INTEGER type controls. Change-Id: I7f1ef24b50022df844f6916489e0f45680de6126 Signed-off-by: Jonathan Aillet <jonathan.aillet@iot.bzh>
2019-01-16Correct sent back stream volumeJonathan Aillet1-15/+20
Send back the real applied value when a stream volume changed. Change-Id: If11e11271080c1f1710775b120f26e1cf34f0a67 Signed-off-by: Jonathan Aillet <jonathan.aillet@iot.bzh>
2019-01-16bluetooth sco: fixed the softvol open errorThierry Bultel3-3/+5
This fixes #SPEC-2125. The fix consists in specifying the number of channels in the softvol pcm configuration. When it is not set, the libasound detects a configuration mismatch (the default number of channels being 2), and attempts to remove the sotfvol control, which for unknown reason, (broken support on kernel side ?) randomly fails. Change-Id: I816b623715e413452e6793ee519e97fac6fdde43 Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
2019-01-03bluetooth: fixes the cleanup at SCO hangupThierry Bultel1-6/+0
A bug in bluez-alsa was preventing to perform the PCM close, it was leading to a crash. There is a fix for this already, in bluez-alsa (as a patch in meta-agl-devel: https://gerrit.automotivelinux.org/gerrit/#/c/19365), that allows to get rid of the current limitation (4a had to be restarted between 2 phone calls). Now that the fix is available, (even if it is still no mainlined), it is now safe to perform the PCM close, without having a a crash. Change-Id: I6654e8e5b308985c4b0842001bc11eef22724deb Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
2018-12-22Implemented the bug cleanup at application exitStephane Desneux15-132/+312
Fixes most memory leaks in softmixer. The concept of 'transaction' for dynamic streams has been generalized to the objects created at startup. The cleanup is done via a handle set through a atexit() call. Also added a missing strdup in alsa-api-loop, that fixes a double free. Warning, the bluez-alsa PCM are not closed in this version. This is intentional due to a BUG in the bluealsa ioplug PCM, that crashes upon close (pthread_cancel is used to terminate the io_thread and things get very bad. I have a pending fix for that, relying on a cancellation pipe, but deeper testing must be done). As an effect, only one phone call can be made, else 4a needs to be restarted Change-Id: Idb84cafe15f17c0ef02fcc70296d541dc55a2dcf Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh> Signed-off-by: Stephane Desneux <stephane.desneux@iot.bzh>
2018-12-19Add support for bluetooth telephonyguppy_6.99.3guppy/6.99.36.99.3Thierry Bultel24-1056/+2166
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>
2018-12-04Move autobuild to top treeFrederic Marec2-26/+42
Bug-AGL: SPEC-495 Change-Id: I1c051997697c3c04c4b8e7ca4669b7052c5713ad Signed-off-by: Frederic Marec <frederic.marec@iot.bzh>
2018-12-04Add tests for 4a-softmixerFrederic Marec9-0/+281
Add test tree Add new config for test Add tests for softmixer Add script to load snd-aloop before test Bug-AGL: SPEC-1796 Change-Id: I6336dbb5689e7baf8f2e8754b23f6aa83b0797d7 Signed-off-by: Frederic Marec <frederic.marec@iot.bzh>
2018-11-30Update version of app-controller-submoduleFrederic Marec1-0/+0
Changes of app-controller-submodule: (70e1d98 - Frederic Marec) Fix Parse plugin (309003b - Clément Bénier) AFB:servsync: add string for query argument (33abde5 - Romain Forlot) Reworked pluginConfig function (8094951 - Romain Forlot) Retrieve plugin list from api rather than a global (871bd64 - Romain Forlot) Add setter/getter for user free defined pointer (f543f05 - Romain Forlot) Pass the plugin to action. (ce07538 - Romain Forlot) Abort if one required API is missing (625ce77 - Jonathan Aillet) Correct an error when no plugins are defined (0f708ba - Jonathan Aillet) Decrease print level when no onload action (8d53984 - Jonathan Aillet) Add a 'params' fields for controller plugins (35398f2 - Jonathan Aillet) Call wasn't done correctly in 'CtlConfigExec' (bc13eef - Romain Forlot) Add ctlPlugins array to the ctlConfig structure (0176d18 - Romain Forlot) Add an Init step to the plugins load (d6eb01e - Romain Forlot) Change loading configuration object behavior Change-Id: I945689c50308fb671305c2ea0e10785868a47d8b Signed-off-by: Frederic Marec <frederic.marec@iot.bzh>
2018-11-30Change .gitmodules following submodule migrationFrederic Marec1-3/+0
Remove app-template in .gitmodules Change-Id: I00477c074fdeed5e32af6e8b0122f9c5db53025f Signed-off-by: Frederic Marec <frederic.marec@iot.bzh>
2018-11-29Add gitreview file to 4a-softmixer repoguppy_6.99.2guppy/6.99.26.99.2Jan-Simon Möller1-0/+4
Allow git review to work. Bug-AGL: SPEC-1731 Change-Id: I80f723b268419911ec6e2cf9dc4942e33ca9ee45 Signed-off-by: Jan-Simon Möller <jsmoeller@linuxfoundation.org>
2018-11-13remove dead code and renamed unobvious variables6.9.0Thierry Bultel6-51/+41
Changed the ringbuffer "xxx_free" function to something more explicit, because it does not free anything. Changed "single letter" variables to nicer names Change-Id: I000c57aa5cc684d387105441889e011a45a6ccf3 Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
2018-11-08Fix the error string of attach actionsThierry Bultel6-17/+21
Fixes the "syntax-error" to something more explicit (SPEC-1906) Change-Id: I9d4c81ee1d62dcfb99799480c6dc910e2019a791 Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
2018-11-07Handle too small card PCM buffer when writingJonathan Aillet1-1/+15
In the writing thread, handle the case when 'writing threshold' was smaller than ALSA sound card's PCM buffer (defined in the driver). This avoids waiting indefinitely for a buffer to contain a wanted number of frames that it cannot contain. Change-Id: Ie1aa69ea1a93471ed46d571c669ec08a1b827476 Signed-off-by: Jonathan Aillet <jonathan.aillet@iot.bzh>
2018-11-07Tweaking debug printsJonathan Aillet3-13/+13
Replace some 'printf' by application framework debug functions. Improve 'ALSA_PCM_UID' macro. Correct minor errors in debug prints. Change-Id: I49899fd904d42b5b3bec46017eb319ed7d321dc5 Signed-off-by: Jonathan Aillet <jonathan.aillet@iot.bzh>
2018-11-07alsa-core-pcm: fixed the mute logicThierry Bultel1-4/+6
This fixes the mute/unmute logic. This was broken due to a forgotten push for a commit Change-Id: I6cbdedefc11ebd508d30ece71df364d9b69c74f0 Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
2018-11-07config.cmake: fixed a typoThierry Bultel1-1/+1
remoce extra parenthesis Change-Id: Ieeb5ca1a9064d97c9674dc855dc79aab36cadf3e Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
2018-11-07Merge pull request #2 from iotbzh/app-templates-migrationtbultel3-10/+12
Migrate app-templates to CMake module
2018-10-31Migrate app-templates to CMake moduleapp-templates-migrationRomain Forlot3-10/+12
Bug-AGL SPEC-1682 Change-Id: Ia8d8bc6b614065d9cc9ab73a33d4643267686bcf Signed-off-by: Romain Forlot <romain.forlot@iot.bzh>
2018-10-16Lower the verbosity when not in debug levelThierry Bultel2-17/+17
There were too many things printed in notice mode. Change-Id: Ia7841e219cb2e9ca71e0c4436a2048a812ef6b07 Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
2018-09-20removed the dependency to alsalib-1.1.6 for hostThierry Bultel6-2/+8
This fixes the compilation for hosts (Ubuntu, fedora, opensuse), that do not have alsalib-1.1.6 Notice that this fix needed another one in app-template, since the OS detection was broken. These are the changes brought by the bump of app-templates: (3dc85ec - Thierry Bultel) common.cmake: fixed erroneous search path for os-release (7fa5e5a - Romain Forlot) Fix: missing gcov symbol in compiled binaries (76e12e7 - CorentinLGS) app-templates doc: Changed doc to fit new format. (02f45f1 - Romain Forlot) Update Docs (52ae181 - Romain Forlot) Fix: typo (f0b24b0 - Romain Forlot) Rollback about TEST build type (e841a77 - Romain Forlot) Adding a TEST build type (994ebc1 - Romain Forlot) Change default compilation options. (85d5ffd - Romain Forlot) Test widget only if there are test materials (d14bdce - Romain Forlot) Handles more test LABELS. (70cf8fd - Romain Forlot) Missing flag for COVERAGE build type (3c99b8a - Romain Forlot) Create a test widget Change-Id: I788d8d0bf110dd9cdc11aac256bd535db0d90e4d Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
2018-09-20Remove an unfilled response json objectJonathan Aillet1-3/+1
Remove an unfilled response json object when a call is received to change bluetooth streamed devbie. Change-Id: I72ad4cd71c29e3cdf1427813228f6c7df63b3144 Signed-off-by: Jonathan Aillet <jonathan.aillet@iot.bzh>
2018-09-12config.cmake: bump the needed version of alsalib to 1.1.6Thierry Bultel1-1/+1
It was kwown that the softmixer needs alsalib >= 1.1.6, for runtime reasons. Since the integration of bluetooth support, there is now also a compile error with older alsalib. Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
2018-09-10bluez-alsa: fixed the null device logicThierry Bultel1-2/+1
Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
2018-09-07fixed crash upon misconfiguration of capture/playback devicesThierry Bultel6-16/+24
The null pcmplug case was not correctly handled in various places. Also fixed some typos in the log Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
2018-09-07dmix: used device when in name of slaveThierry Bultel1-5/+27
When a sound card has multiple devices, it is invalid to set the slave name of the dmix as "hw:cardname" because alsa does not know which device to use. The fix consists in using the device number, when it is given. Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
2018-08-31Added bluez sound playback supportThierry Bultel13-57/+271
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>
2018-08-01Bump revisions for all submodulesStephane Desneux3-0/+0
Changes for app-afb-helpers-submodule: * f0ce5b6 wrap-json: Fix duplicated lines in header file * 764c355 Add '@' as binder middle name separator. * 74be4cc Enhance 'wrap_json_clone_depth' description * a37225f Fix: use of GetBindingDirPath without dynapi * 4f99d16 Retrieve directory list from environment variables * f46a0dc Remove the file .gitmodules Changes for app-controller-submodule: * 4e30eb1 New defaults useful functions on lua table * 61cbc9a More precise log message when loading a Lua file * 535df7f Fix: wrong legacy function signature * b79a761 Split loading JSON controller file. * c3d7de2 Release arguments once C function returned. * a58d83b Fix : typo introduced in a previous commit. * 86f65bd Fixed character counting that was shortening paths * e32d98c Keep json unmodified during action execution * 88892db Use prefix variable to find controller's plugins Changes for app-templates: * 9c1a0fb Fix: interpreted '&' character * 9202fac More accurate comment about widget template file. * f94e45e Align sample on actual default compile options * d0acc2a Add support to binding version 3. * 6fb3846 Warning if not using wgtpkg-pack to make a widget * 35f3af1 Rework CMAKE_INSTALL_PREFIX and INSTALL_PREFIX var * 332f377 Be able to overwrite BUILD_TYPE using CLI * 1ec7531 Use CACHE variable for other common CMAKE variable * 0880356 Fix:: wrong wgt using RELEASE BUILD TYPE Change-Id: If6597632b9f719fcfd476697d1fd2332742d9801 Signed-off-by: Stephane Desneux <stephane.desneux@iot.bzh>
2018-07-26Reduce verbosity of message "readThreadEntry..."Stephane Desneux1-6/+6
Moves the log level of the message from info to debug. Change-Id: I348421a17875b9061255c3b353e27070b0068c3b Signed-off-by: Stephane Desneux <stephane.desneux@iot.bzh>
2018-07-20Updated the readme.mdThierry Bultel1-18/+30
Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
2018-07-20rework the sound capture & playback modelThierry Bultel4-254/+324
Now uses two threads for in the playing loop The first one reads from the capture device (ie, a phys. capture, or snd_aloop) and writes data to a circular buffer. The second one gets data from the circular buffer and outputs it to the playback. This model solves a lot of correlated timing bugs between read & write tasks. The read tasks only wakes up the write task when the buffer is 80% full. The buffer size big enough to hold 2 seconds of sound. The mute implementation has also been simplified, since it has been found out that it was possible to recover from an interrupted read, by calling snd_pcm_start additionnally to snd_pcm_prepare. Thus, the mute code consists in listening to an extra file descriptor in the read loop. Reading from that descriptor gives the mute or unmute command sent at higher level (in the PCM control event callback). When a 'mute' order is get, the capture sound fd is simply backup and replaced by '-1' in the set of the poll of the read task. When a 'unmute' order is get, the fd is simply restored. The start threshold is only computed for capture, and hardcoded to 1 for playback. This removes most of the remaining EPIPE on playback. The stop threshold has been removed. It had bad side effects on the amount of writeable data returned by snd_pcm_avail_update (was returning too small chunks) Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>
2018-07-20added ringbuffer and time utilsThierry Bultel7-1/+694
Signed-off-by: Thierry Bultel <thierry.bultel@iot.bzh>