Add documentation about Sound Manager and Audio Manager architecture
[staging/soundmanager.git] / doc / ApplicationGuide.md
1 **Sound Manager Application Guide**\r
2 ====\r
3 <div align="right">Revision: 0.1</div>\r
4 <div align="right">TOYOTA MOTOR CORPORATION</div>\r
5 <div align="right">Advanced Driver Information Technology</div>\r
6 <div align="right">22th/Aug/2017</div>\r
7 \r
8 * * *\r
9 \r
10 ## **<div id="Table\ of\ content">Table of content</div>**\r
11 - [Target reader of this document](#Target\ reader\ of\ this\ document)\r
12 - [Overview](#Overview)\r
13 - [Getting Start](#Getting\ Start)\r
14         - [Supported environment](#Supported\ environment)\r
15         - [Build](#Build)\r
16         - [Configuring](#Configuring)\r
17         - [How to call Sound Manager's APIs from your Application?](#How\ to\ call\ Sound\ Manager\ APIs\ from\ your\ Application?)\r
18 - [Supported usecase](#Supported\ usecase)\r
19 - [Software Architecture](#Software\ Architecture)\r
20 - [API reference](#API\ reference)\r
21         - [CommandReceiver API](#CommandReceiver\ API)\r
22         - [CommandSender API](#CommandSender\ API)\r
23         - [CAmRoutingReceiver API](#CAmRoutingReceiver\ API)\r
24         - [CAmRoutingSender API](#CAmRoutingSender\ API)\r
25         - [Sound Manager Specific API](#Sound\ Manager\ Specific\ API)\r
26 - [Sequence](#Sequence)\r
27         - [StartUp](#StartUp)\r
28         - [Registration](#Registration)\r
29         - [Request Sound Right](#Request\ Sound\ Right)\r
30         - [Connect Sound Route](#Connect\ Sound\ Route)\r
31         - [Start Sound Streaming](#Start\ Sound\ Streaming)\r
32         - [Stop Sound Streaming](#Stop\ Sound\ Streaming)\r
33         - [Disconnect Sound Route](#Disconnect\ Sound\ Route)\r
34         - [Change Volume](#Change\ Volume)\r
35         - [Set Mute State](#Set\ Mute\ State)\r
36         - [Release Sound Right](#Release\ Sound\ Right)\r
37         - [Audio Domain](#Audio\ Domain)\r
38 - [Sample code](#Sample\ code)\r
39 - [Limitation](#Limitation)\r
40 - [Next Plan](#Next\ Plan)\r
41 \r
42 * * *\r
43 \r
44 ## **<div id="Target\ reader\ of\ this\ document">Target reader of this document</div>**\r
45 Application developer whose software uses sound output.\r
46 \r
47 * * *\r
48 \r
49 ## **<div id="Overview">Overview</div>**\r
50 The sound manager is the service which provides **sound-right management** for multiple sound sources.  \r
51 This service based on GENIVI Audio Manager, and this package contains service binder and library for API calling.  \r
52 The reason why this service based on GENIVI Audio Manager is because the sound manager supports highly strong and flexible sound-right management function.\r
53 \r
54 In order to understand, the below figure shows the one of typical usecases.\r
55 In this example, there are four sound mode.\r
56 1. Audio Off\r
57 2. Media Player\r
58 3. Tel (Ring and talking)\r
59 4. TTS (Text To Speech; typically it's used by Navigation sound)\r
60 ![Figure: Typical usecase](parts/typical-usecase.png)\r
61 \r
62 The important points are:\r
63 - **There is a priority for each sound source.**  \r
64         In this example, "Tel" and "TTS" is stronger than "MediaPlayer". Therefore when the system got incoming call, all four outputs of MediaPlayer are muted automatically by Sound Manager. And in this timing, Sound Manager will issue the event to Media Player, then Media Player can stop the music. (Because depends on OEM's requirement, "Stop" is required, not "Mute".)  \r
65     "Tel" and "TTS" have the same priority. So if TTS event happened on talking, each sound will output from independent speaker.  \r
66     If on-hook button is touched, Sound Manager will resume previous sound mode. In this example, basically it's MediaPlayer sound. But if TTS still playing, three speaker will output MediaPlayer sound but one speaker will continue to output TTS sound.\r
67 - **Sound mode transition should be done by Sound Manager not Applications.**  \r
68         Actually application cannot recognize all sound source and its priority, so some centerized manager is required. Sound Manager provides this function. Sound Manager has a database for usecase and priority and in line with this policy Sound Manager controls proper sound mode.\r
69 \r
70 \r
71 The below links show the example of Sound/Window mode transition.\r
72 * [Single window application](Display_Audio_Transition1.md)  \r
73         This transition assumes target IVI system support only one window on screen. It's a similar transition to CES2017 demo.\r
74 * [Dual window application](Display_Audio_Transition2.md)  \r
75         This transition assumes target IVI system support two window (split screen) on screen.\r
76 \r
77         Of course user can customize shortcut menu, but since it's too many states so this example limits shortcut menu as "Home", "MediaPlayer", "HVAC" and "Navigation".\r
78 \r
79 * * *\r
80 \r
81 ## **<div id="Getting\ Start">Getting Start</div>**\r
82 \r
83 ### **<div id="Supported\ environment">Supported environment</div>**\r
84 | Item        | Description                       |\r
85 |:------------|:----------------------------------|\r
86 | AGL version | Daring Dab                        |\r
87 | Hardware    | Renesas R-Car Starter Kit Pro(M3) |\r
88 \r
89 \r
90 ### **<div id="Build">Build</div>**\r
91 \r
92 You can make Sound Manager object files by the following two stage operations.\r
93 \r
94 **Download recipe**\r
95 If repo is already done, please start with git clone\r
96 ```\r
97 $ mkdir WORK\r
98 $ cd WORK\r
99 $ repo init -b dab -m dab_4.0.0_xml -u https://gerrit.automotivelinux.org/gerrit/AGL/AGL-repo\r
100 $ repo sync\r
101 $ git clone git clone https://gerrit.automotivelinux.org/gerrit/staging/meta-hmi-framework\r
102 \r
103 ```\r
104 \r
105 Then you can get the following recipe.\r
106 * `meta-hmi-framework/soundmanager`\r
107 \r
108 \r
109 **Bitbake**\r
110 ```\r
111 $ source meta-agl/scripts/aglsetup.sh -m m3ulcb agl-demo agl-devel agl-appfw-smack\r
112 $ bitbake soundmanager\r
113 ```\r
114 \r
115 \r
116 * * *\r
117 \r
118 ### **<div id="Configuring">Configuring</div>**\r
119 To use Sound Manager API, an application shall paste the following configuration definition into "config.xml" of application.\r
120 ```\r
121 <feature name="urn:AGL:widget:required-api">\r
122         <param name="soundmanager" value="ws" />\r
123 </feature>\r
124 ```\r
125 \r
126 * * *\r
127 \r
128 ### **<div id="How\ to\ call\ Sound\ Manager\ APIs\ from\ your\ Application?">How to call Sound Manager APIs from your Application?</div>**\r
129 Sound Manager provides a library which is called "libsoundmanager".  \r
130 This library treats "json format" as API calling.  \r
131 For example, if an application wants to call "connect()" API, the you should implement as below.  \r
132 \r
133 At first the application should create the instance of libsoundmanager.\r
134 ```\r
135 LibSoundmanager* libsm;\r
136 libsm = new LibSoundmanager(port, token);\r
137 ```\r
138 The port and token is provided by Application Framework\r
139 \r
140 Then assign the argument to JSON object\r
141 ```\r
142 struct json_object* jobj = json_object_new_object();\r
143 \r
144 json_object_object_add(jobj, "sourceID", json_object_new_int(100));\r
145 json_object_object_add(jobj, "sinkID", json_object_new_int(100));\r
146 \r
147 ```\r
148 \r
149 \r
150 And finally execute the "cal()" function.\r
151 ```\r
152 libsm->call("connect", jobj);\r
153 ```\r
154 \r
155 Regarding the detail of connect() API, please refer [this](#CommandReceiver\ API) section.  \r
156 The first parameter is the name of API, so in this case "connect" is proper string.  \r
157 And the second parameter corresponds to arguments of "connect()" API.  \r
158 \r
159 \r
160 \r
161 See also our [Sample code](#Sample\ code).\r
162 \r
163 \r
164 <br />\r
165 \r
166 * * *\r
167 \r
168 ## **<div id="Supported\ usecase">Supported usecase</div>**\r
169 1. Active source change\r
170         - When user choose different audio source with current one, IVI system stop or pause current source and activate new one.\r
171         - When user connect external device e.g. iPhone, USB memory IVI system change active source automatically to connected one.\r
172 2. Active source locking\r
173         - When user is in phone call, IVI restrict to change active source.\r
174 3. Interrupt source mixing\r
175         - When car close to cross road IVI system reduce the volume of current source and mix with interrupt source e.g. Navigation Guidance.\r
176 4. Volume change\r
177         - User can change the volume of active source or sink.\r
178         - When user change volume during interruption e.g. Navigation Guidance, IVI system change its volume temporary or permanently.\r
179 5. Mute/unmute\r
180         - User can mute/unmute current active source.\r
181 6. Volume management\r
182         - When user change active source, IVI system mute/unmute to avoid distortion of sound.\r
183 7. Volume acceleration\r
184         - When road noise is increased by speed, IVI system automatically change the volume of active source.\r
185 8. Routing sound\r
186         - System needs to route sound stream to proper zones. (driver zone, passenger zone, rear seat zone)\r
187 \r
188 [See also this page](https://wiki.automotivelinux.org/eg-ui-graphics-req-audiorouting)\r
189 \r
190 * * *\r
191 \r
192 ## **<div id="Software\ Architecture">Software Architecture</div>**\r
193 The architecture of Sound Manager is shown below.  \r
194 Sound Manager is the service designed to be used by multiple applications.  \r
195 Therefore Sound Manager framework consists on two binder layers. Please refer the following figure.  \r
196 The upper binder is for application side security context for applications. The lower binder is for servide side security context.  \r
197 Usually application side binder has some business logic for each application, so the number of binders depend on the number of applications which use Sound Manager.  \r
198 On the other hand, regarding lower binder there is only one module in the system. This binder receives all messages from multiple applications (in detail, it comes from upper layer binder).\r
199 \r
200 The communication protocols between libsoundmanager and upper binder, upper binder and lower binder, lower binder (soundmanager-binding) and AudioManager are WebSocket.\r
201 \r
202 ![software-stack.png](parts/software-stack.png)\r
203 \r
204 * * *\r
205 \r
206 ## **<div id="API\ reference">API reference</div>**\r
207 "libsoundmanager" and "soundmanager_binding" provides several kinds of APIs, and these APIs basically correspond to GENIVI Audio Manager API. (Some APIs are Sound Manager original functions.)\r
208 \r
209 For understanding, GENIVI Audio Manager stands for one core module and three plug-ins.\r
210 1. AudioManagerDaemon  \r
211         This is a core module of Audio Manager.\r
212 2. AudioManagerCommandPlugin  \r
213         This is a command interface for Audio Manager.\r
214 3. AudioManagerController  \r
215         This plug-in can be used for sound-right management.\r
216 4. AudioManagerRountingPlugin  \r
217         This plug-in abstracts the hardware and software. And sometimes there may be multiple plug-ins.\r
218 \r
219 *) [See also GENIVI AudioManager Components](http://docs.projects.genivi.org/AudioManager/audiomanagercomponentspage.html)\r
220 \r
221 ![See also GENIVI AudioManager Components](parts/am-component.png)\r
222 (This figure was copied from GENIVI Web page.)\r
223 \r
224 ### **<div id="CommandReceiver\ API">CommandReceiver API</div>**\r
225 - [connect (const am_sourceID_t sourceID, const am_sinkID_t sinkID, am_mainConnectionID_t &mainConnectionID)](http://docs.projects.genivi.org/AudioManager/a00033.html#a62d8f5aee1e601d59f993c5a5561e234)\r
226 - [disconnect (const am_mainConnectionID_t mainConnectionID)](http://docs.projects.genivi.org/AudioManager/a00033.html#aa24d0146f4e3c75e02d6c0152e246da1)\r
227 - [setVolume (const am_sinkID_t sinkID, const am_mainVolume_t volume)](http://docs.projects.genivi.org/AudioManager/a00033.html#a6d47bc67473d75495260abe8c666fc7e)\r
228 - [volumeStep (const am_sinkID_t sinkID, const int16_t volumeStep)](http://docs.projects.genivi.org/AudioManager/a00033.html#ad7a4c1fe5a2ecfaae5484a14d8820e58)\r
229 - [setSinkMuteState (const am_sinkID_t sinkID, const am_MuteState_e muteState)](http://docs.projects.genivi.org/AudioManager/a00033.html#afae22041843c5349be16a6593d3ebb9c)\r
230 - [getListMainConnections (std::vector< am_MainConnectionType_s > &listConnections)](http://docs.projects.genivi.org/AudioManager/a00033.html#a59d10a7178e3227d0b8f415308c71179)\r
231 \r
232 ### **<div id="CommandSender\ API">CommandSender API</div>**\r
233 These APIs are callback function from GENIVI Audio Manager point of view, but it's treated as asynchronous "event" from Application point of view.  \r
234 To receive an event, Application should call "subscribe()" API, and register the event name.\r
235 Each CommandSender API corresponds to event name. For example, if an application wants to get the event of "cbNewMainConnection()", the event name shall be specified as "newMainConnection".\r
236 - [cbNewMainConnection (const am_MainConnectionType_s mainConnection)](http://docs.projects.genivi.org/AudioManager/a00034.html#a69ada9e19c65c1d078d8a5f473d08586)\r
237 - [cbRemovedMainConnection (const am_mainConnectionID_t mainConnection)](http://docs.projects.genivi.org/AudioManager/a00034.html#aa3b5906bcf682cff155fb24d402efd89)\r
238 - [cbMainConnectionStateChanged (const am_mainConnectionID_t connectionID, const am_ConnectionState_e connectionState)](http://docs.projects.genivi.org/AudioManager/a00034.html#a32aa8ab84632805a876e023a7aead810)\r
239 - [cbVolumeChanged (const am_sinkID_t sinkID, const am_mainVolume_t volume)](http://docs.projects.genivi.org/AudioManager/a00034.html#a4494fdd835137e572f2cf4a3aceb6ae5)\r
240 - [cbSinkMuteStateChanged (const am_sinkID_t sinkID, const am_MuteState_e muteState)](http://docs.projects.genivi.org/AudioManager/a00034.html#a6068ce59089fbdc63aec81e778aba238)\r
241 \r
242 ### **<div id="CAmRoutingReceiver\ API">CAmRoutingReceiver API</div>**\r
243 - [confirmRoutingReady (const uint16_t handle, const am_Error_e error)](http://docs.projects.genivi.org/AudioManager/a00053.html#a1dd1b89cccffeaafb1a3c11cebd7e48c)\r
244 - [registerSource (const am_Source_s &sourceData, am_sourceID_t &sourceID)](http://docs.projects.genivi.org/AudioManager/a00053.html#acadce23459d94cec496d17700cbde230)\r
245 - [registerDomain (const am_Domain_s &domainData, am_domainID_t &domainID)](http://docs.projects.genivi.org/AudioManager/a00053.html#a34841797b481e774867ce0a1efacd5f2)\r
246 - [ackConnect (const am_Handle_s handle, const am_connectionID_t connectionID, const am_Error_e error)](http://docs.projects.genivi.org/AudioManager/a00053.html#ad680eddb5bf7aa480308807903dcb592)\r
247 - [ackSetSourceState (const am_Handle_s handle, const am_Error_e error)](http://docs.projects.genivi.org/AudioManager/a00053.html#a11f6b0378a50296a72107d6a1fa7ec21)\r
248 - [ackDisconnect (const am_Handle_s handle, const am_connectionID_t connectionID, const am_Error_e error)](http://docs.projects.genivi.org/AudioManager/a00053.html#af478e5deb2e71e94c28cec497ac48ff4)\r
249 \r
250 ### **<div id="CAmRoutingSender\ API">CAmRoutingSender API</div>**\r
251 These APIs are also treaded as asynchronous event.  \r
252 \r
253 - [setRoutingReady ()](http://docs.projects.genivi.org/AudioManager/a00054.html#a7a4d410e30df0e8240d25a57e3c72c6b)\r
254 - [asyncConnect (am_Handle_s &handle, am_connectionID_t &connectionID, const am_sourceID_t sourceID, const am_sinkID_t sinkID, const am_CustomConnectionFormat_t connectionFormat)](http://docs.projects.genivi.org/AudioManager/a00054.html#a8a81297be9c64511e27d85444c59b0d6)\r
255 - [asyncSetSourceState (am_Handle_s &handle, const am_sourceID_t sourceID, const am_SourceState_e state)](http://docs.projects.genivi.org/AudioManager/a00054.html#ab02d93d54ee9cd98776a3f2d274ee24d)\r
256 - [asyncDisconnect (am_Handle_s &handle, const am_connectionID_t connectionID)](http://docs.projects.genivi.org/AudioManager/a00054.html#a93ae95515730eb615ab5dfc1316d7862)\r
257 \r
258 ### **<div id="Sound\ Manager\ Specific\ API">Sound Manager Specific API</div>**\r
259 - [LibSoundmanager ()](api-ref/html/class_lib_soundmanager.html#a8b51e9891813cb62dd12109c017ad106)\r
260 - [call (const string& verb, struct json_object* arg)](api-ref/html/class_lib_soundmanager.html#a1fe952a4dabbab6126cc23e36c79c773)\r
261 - [call (const char* verb, struct json_object* arg)](api-ref/html/class_lib_soundmanager.html#a1fe952a4dabbab6126cc23e36c79c773)\r
262 - [subscribe (const string& event_name)](api-ref/html/class_lib_soundmanager.html#a9cd7c5470cb135f9b1aa56d790c7e91e)\r
263 - [unsubscribe (const string& event_name)](api-ref/html/class_lib_soundmanager.html#a21060844aa7efad6473b6104546afb06)\r
264 - [register_callback( void (\*event_cb)(const std::string& event, struct json_object\* event_contents), void (\*reply_cb)(struct json_object\* reply_contents))](api-ref/html/class_lib_soundmanager.html#a560edf9ae3b1e367ad4cbb31c7021d74)\r
265 - [run_eventloop()](api-ref/html/class_lib_soundmanager.html#abe71d3531e7888f47185a601b284e729)\r
266 * * *\r
267 \r
268 ## **<div id="Sequence">Sequence</div>**\r
269 ### **<div id="StartUp">StartUp</div>**\r
270 ![seq_startup.png](parts/seq_startup.svg)\r
271 \r
272 ### **<div id="Registration">Registration</div>**\r
273 ![seq_registration.png](parts/seq_registration.svg)\r
274 \r
275 ### **<div id="Request\ Sound\ Right">Request Sound Right</div>**\r
276 ![seq_requestsoundmode.png](parts/seq_requestsoundmode.svg)\r
277 \r
278 ### **<div id="Connect\ Sound\ Route">Connect Sound Route</div>**\r
279 ![seq_connectsoundroute.png](parts/seq_connectsoundroute.svg)\r
280 \r
281 ### **<div id="Start\ Sound\ Streaming">Start Sound Streaming</div>**\r
282 ![seq_startsoundstreaming.png](parts/seq_startsoundstreaming.svg)\r
283 \r
284 ### **<div id="Stop\ Sound\ Streaming">Stop Sound Streaming</div>**\r
285 ![seq_stopsoundstreaming.png](parts/seq_stopsoundstreaming.svg)\r
286 \r
287 ### **<div id="Disconnect\ Sound\ Route">Disconnect Sound Route</div>**\r
288 ![seq_disconnectsoundroute.png](parts/seq_disconnectsoundroute.svg)\r
289 \r
290 ### **<div id="Change\ Volume">Change Volume</div>**\r
291 ![seq_changevolume.png](parts/seq_changevolume.svg)\r
292 \r
293 ### **<div id="Set\ Mute\ State">Set Mute State</div>**\r
294 ![seq_setmutestate.png](parts/seq_setmutestate.svg)\r
295 \r
296 ### **<div id="Release\ Sound\ Right">Release Sound Right</div>**\r
297 ![seq_releasesoundmode.png](parts/seq_releasesoundmode.svg)\r
298 \r
299 * * *\r
300 \r
301 ### **<div id="Audio\ Domain">Audio Domain</div>**\r
302 \r
303 One of the most important concept of Audio Manager is Audio Domain.\r
304 To use GENIVI Audio Manager based system, it may be better to understand this concept.\r
305 The below document should bring good understanding.\r
306 \r
307 [GENIVI Audio Manager: Generic Controller Plug-in](http://events.linuxfoundation.org/sites/events/files/slides/AGL_AMM_presentation_A01.pdf)\r
308 \r
309 Although strongly recommended to read whole pages, but you can get quick understanding by page.10 to 14.\r
310 \r
311 \r
312 # **<div id="Sample\ code">Sample code</div>**\r
313 You can find sample implementation of Sound Manager as below.\r
314 * `soundmanager/sample/radio`  \r
315 * `soundmanager/sample/mediaplayer`  \r
316 * `soundmanager/sample/phone`  \r
317 \r
318 This samples are based on QML application. But the library is written as C library so it is usable for other HMI framework.  \r
319 To use Sound Manager, at first libsoundmanager should be enabled. As this sample, please refer to "soundmanager/sample/radio/app/main.cpp".  \r
320 Then as the calling sample from QML, please refer "soundmanager/sample/radio/app/Radio.qml". The following code is found in this file.  \r
321 ```\r
322 onClicked: {\r
323         var JsonArg = JSON.stringify({sourceID:100, sinkID:100})\r
324         smw.call("connect",JsonArg)\r
325 ```\r
326 \r
327 And also we provide the other sample as below.\r
328 * `soundmanager/sample/radio_qml`  \r
329 \r
330 This is an alternative way against useing libsoundmanager.\r
331 This sample doesn't use libsoundmanager but calls API via WebSocket class which is provided by QML. How to implement this way is found in "soundmanager/sample/radio_qml/app/api/BindingSoundManager.qml".\r
332 \r
333 # **<div id="Limitation">Limitation</div>**\r
334 * The following APIs can be called, but probably it doesn't work  \r
335         * setVolume\r
336         * volumeStep\r
337 * The following APIs cannot be called so far.  \r
338         * getVolume\r
339 * The following events never happen.  \r
340         * volumeChanged\r
341 * The following sample application is under developing\r
342         * soundmanager/sample/phone\r
343 \r
344 # **<div id="Next\ Plan">Next Plan</div>**\r
345 * Add new calling style for API  \r
346 Current Sound Manger expects all APIs call be called as JSON format.\r
347 But Sound Manager provide "function call" interface in next version. So it will be possible to call all APIs of Sound Manager not only JSON format but also function style.\r
348 \r
349 * Support source name and sink name as abstract alias instead of SourceID/SinkID  \r
350 The CommandReciever APIs requires SourceID/SinkID assigned dynamically as arguments, but after supporting this feature, you can call these APIs using abstract bname such like "radio" or "speaker". It will provide more readable code.\r
351 \r
352 ```\r
353 struct json_object* jobj = json_object_new_object();\r
354 \r
355 json_object_object_add(jobj, "sourceID", json_object_new_string("radio"));\r
356 json_object_object_add(jobj, "sinkID", json_object_new_string("speaker"));\r
357 \r
358 ```\r