Fix Coverity Issues-2
[platform/core/api/sound-pool.git] / test / proxy / src / proxy.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "proxy.h"
18 #include "logger.h"
19
20 #include <string.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24
25 #define DEFAULT_MAX_STREAMS_PER_POOL_CNT 25U
26 #define DEFAULT_STREAM_PRIORITY_RANK 255U
27 #define MICROSECS_PER_MILLISEC 1000
28
29 #define MAX_POOL_CNT 100
30 static sound_pool_h pools[MAX_POOL_CNT] = { NULL };
31
32 /* Messages to be used for callbacks output (for pool state changing) */
33 static char *messages[MAX_POOL_CNT] = { NULL };
34 /* Scripts will be launched from callbacks (for stream state changing) */
35 static char *scripts[MAX_POOL_CNT] = { NULL };
36
37 #define MAX_STREAM_CNT 1000
38
39 static const char *__stringify_sound_pool_error(sound_pool_error_e error);
40 static int __proxy_sound_pool_execute_script(const char *pars);
41
42 static const char *__stringify_sound_pool_error(sound_pool_error_e error)
43 {
44         switch (error) {
45         case SOUND_POOL_ERROR_NONE:
46                 return "SOUND_POOL_ERROR_NONE";
47                 break;
48         case SOUND_POOL_ERROR_KEY_NOT_AVAILABLE:
49                 return "SOUND_POOL_ERROR_KEY_NOT_AVAILABLE";
50                 break;
51         case SOUND_POOL_ERROR_OUT_OF_MEMORY:
52                 return "SOUND_POOL_ERROR_OUT_OF_MEMORY";
53                 break;
54         case SOUND_POOL_ERROR_INVALID_PARAMETER:
55                 return "SOUND_POOL_ERROR_INVALID_PARAMETER";
56                 break;
57         case SOUND_POOL_ERROR_INVALID_OPERATION:
58                 return "SOUND_POOL_ERROR_INVALID_OPERATION";
59                 break;
60         case SOUND_POOL_ERROR_NOT_PERMITTED:
61                 return "SOUND_POOL_ERROR_NOT_PERMITTED";
62                 break;
63         case SOUND_POOL_ERROR_NO_SUCH_FILE:
64                 return "SOUND_POOL_ERROR_NO_SUCH_FILE";
65                 break;
66         default:
67                 return "";
68                 break;
69         }
70
71         return NULL;
72 }
73
74 const char *__stringify_stream_state(sound_pool_stream_state_e state)
75 {
76         switch (state) {
77         case SOUND_POOL_STREAM_STATE_NONE:
78                 return "SOUND_POOL_STREAM_STATE_NONE";
79                 break;
80         case SOUND_POOL_STREAM_STATE_PLAYING:
81                 return "SOUND_POOL_STREAM_STATE_PLAYING";
82                 break;
83         case SOUND_POOL_STREAM_STATE_PAUSED:
84                 return "SOUND_POOL_STREAM_STATE_PAUSED";
85                 break;
86         case SOUND_POOL_STREAM_STATE_SUSPENDED:
87                 return "SOUND_POOL_STREAM_STATE_SUSPENDED";
88                 break;
89         case SOUND_POOL_STREAM_STATE_STOPPED:
90                 return "SOUND_POOL_STREAM_STATE_STOPPED";
91                 break;
92         case SOUND_POOL_STREAM_STATE_FINISHED:
93                 return "SOUND_POOL_STREAM_STATE_FINISHED";
94                 break;
95         default:
96                 return "";
97                 break;
98         }
99
100         return NULL;
101 }
102
103 static void __sp_cb_msg(sound_pool_h pool, sound_pool_state_e prev_state,
104                 sound_pool_state_e cur_state, void *data)
105 {
106         const char *msg = (const char *)data;
107         _logger_log_info("Sound pool state was changing from %s to %s: %s",
108                         prev_state == SOUND_POOL_STATE_ACTIVE ?
109                                         "SOUND_POOL_STATE_ACTIVE" : "SOUND_POOL_STATE_INACTIVE",
110                         cur_state == SOUND_POOL_STATE_ACTIVE ?
111                                         "SOUND_POOL_STATE_ACTIVE" : "SOUND_POOL_STATE_INACTIVE",
112                         msg ? msg : "No message");
113 }
114
115 static void __sp_cb_scr(sound_pool_h pool, sound_pool_state_e prev_state,
116                 sound_pool_state_e cur_state, void *data)
117 {
118         const char *scr = (const char *)data;
119         _logger_log_info("Sound pool state was changing from %s to %s; "
120                         "Executing: %s...",
121                         prev_state == SOUND_POOL_STATE_ACTIVE ? "SOUND_POOL_STATE_ACTIVE" :
122                                         "SOUND_POOL_STATE_INACTIVE",
123                         cur_state == SOUND_POOL_STATE_ACTIVE ? "SOUND_POOL_STATE_ACTIVE" :
124                                         "SOUND_POOL_STATE_INACTIVE",
125                         scr ? scr : "No script");
126         __proxy_sound_pool_execute_script(scr);
127 }
128
129 static void __s_cb_msg(sound_pool_h pool, unsigned id,
130                 sound_pool_stream_state_e prev_state,
131                 sound_pool_stream_state_e cur_state, void *data)
132 {
133         const char *msg = (const char *)data;
134         _logger_log_info("Stream state was changing from %s to %s: %s",
135                         __stringify_stream_state(prev_state),
136                         __stringify_stream_state(cur_state),
137                         msg ? msg : "No message");
138 }
139
140 /* CMD_EXIT */
141 static int __exit()
142 {
143         return EXIT;
144 }
145
146 /* CMD_HELP */
147 static int __print_cmd_help_msg()
148 {
149         printf("\nTest suite usage help:\n");
150
151         printf(CMD_HELP "\n");
152         printf("\t- Shows this help.\n");
153
154         printf(CMD_CREATE_POOL "\n");
155         printf("\t- creates pool with specific identifier.\n");
156
157         printf(CMD_DESTROY_POOL "\n");
158         printf("\t- destroys pool with specific identifier.\n");
159
160         printf(CMD_ACTIVATE_POOL "\n");
161         printf("\t- activates pool with specific identifier.\n");
162
163         printf(CMD_DEACTIVATE_POOL "\n");
164         printf("\t- deactivates pool with specific identifier.\n");
165
166         printf(CMD_GET_POOL_STATE "\n");
167         printf("\t- shows state of the pool with specific identifier.\n");
168
169         printf(CMD_SET_POOL_VOLUME "\n");
170         printf("\t- use this command to set volume for the specific sound pool.\n");
171
172         printf(CMD_GET_POOL_VOLUME "\n");
173         printf("\t- shows volume of the sound pool with specific identifier.\n");
174
175         printf(CMD_SET_POOL_CB_MSG "\n");
176         printf("\t- sets callback which will show the message when sound pool "
177                         "state is changed.\n");
178
179         printf(CMD_UNSET_POOL_CB "\n");
180         printf("\t- unsets the callback for the sound pool.\n");
181
182         printf(CMD_LIST_POOL "\n");
183         printf("\t- shows ids of all pools had been created and their states.\n");
184
185         printf(CMD_LOAD_SOURCE "\n");
186         printf("\t- loads the source with specific source tag.\n");
187
188         printf(CMD_UNLOAD_SOURCE "\n");
189         printf("\t- unloads the source with specific source tag.\n");
190
191         printf(CMD_PLAY_STREAM "\n");
192         printf("\t- creates the stream with unique identifier and starts playback.\n"
193                         "\t  Source tag to be used for stream creation should be specified.\n");
194
195         printf(CMD_STOP_STREAM "\n");
196         printf("\t- stops the stream playback. Stream unique identifier should be\n"
197                         "\t  specified after command. After stopping the stream became invalid.\n");
198
199         printf(CMD_PAUSE_STREAM "\n");
200         printf("\t- pauses the stream playback. Stream unique identifier should be\n"
201                         "\t  specified after command.\n");
202
203         printf(CMD_RESUME_STREAM "\n");
204         printf("\t- resumes the stream was paused before. Stream unique identifier\n"
205                         "\t  should be specified after command.\n");
206
207         printf(CMD_SET_STREAM_VOLUME "\n");
208         printf("\t- use this command to set volume parameter of the stream.\n");
209
210         printf(CMD_GET_STREAM_VOLUME "\n");
211         printf("\t- shows volume of the stream in the pool with specified "
212                         "identifiers.\n");
213
214         printf(CMD_SET_STREAM_PRIORITY "\n");
215         printf("\t- use this command to set priority parameter of the stream. "
216                         "0 is the lowest priority.\n");
217
218         printf(CMD_GET_STREAM_PRIORITY "\n");
219         printf("\t- shows priority rank of the stream in the pool with specified "
220                         "identifiers. 0 is the lowest priority.\n");
221
222         printf(CMD_GET_STREAM_STATE "\n");
223         printf("\t- shows state of the stream in the pool with specified "
224                         "identifiers.\n");
225
226         printf(CMD_EXECUTE_SCRIPT "\n");
227         printf("\t- executes the script from the file in filesystem. Script has to\n"
228                         "\t  be compiled with commands supported by testsuite, one command\n"
229                         "\t  per single line.\n");
230
231         printf(CMD_SLEEP "\n");
232         printf("\t- suspends execution of the main thread for the specific amount "
233                         "of milleseconds.\n");
234
235         printf(CMD_EXIT "\n");
236         printf("\t- exits from the test suite.\n");
237
238         printf("\n");
239
240         return OK;
241 }
242
243 /* CMD_CREATE_POOL */
244 static int __proxy_sound_pool_create()
245 {
246         _logger_log_info(CMD_CREATE_POOL " command was called");
247         _logger_log_info("Creating the pool...");
248
249         sound_pool_h pool = NULL;
250         int ret = sound_pool_create(&pool);
251
252         if (ret == SOUND_POOL_ERROR_NONE) {
253                 _logger_log_info("sound_pool_create(pool) returned %s value",
254                                 __stringify_sound_pool_error(ret));
255
256                 size_t idx = 0;
257                 while (idx < MAX_POOL_CNT) {
258                         if (pools[idx++] == NULL) {
259                                 pools[--idx] = pool;
260                                 break;
261                         }
262                 }
263
264                 if (idx == MAX_POOL_CNT) {
265                         _printf(CMD_COLOR_RED, "Limit of possible pools is exceeded. Destroy "
266                                         "some pools before creating of new ones.\n");
267
268                         _logger_log_warn("Pool can't be created due to test suite "
269                                         "restrictions. Destroying the pool...");
270
271                         ret = sound_pool_destroy(pool);
272
273                         PRINT_INFO_OR_ERROR_INFO(ret == SOUND_POOL_ERROR_NONE,
274                                         "sound_pool_destroy(pool) returned %s value",
275                                         __stringify_sound_pool_error(ret));
276
277                         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
278                 }
279
280                 if (!pool)
281                         _logger_log_warn("Created pool is NULL");
282                 else
283                         _logger_log_info("Identifier of the pool has been created is %zu", idx);
284         } else {
285                 _logger_log_err("sound_pool_create(pool) returned %s value",
286                                 __stringify_sound_pool_error(ret));
287         }
288
289         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
290 }
291
292 /* CMD_DESTROY_POOL */
293 static int __proxy_sound_pool_destroy(const char *pars)
294 {
295         int ret = SOUND_POOL_ERROR_NONE;
296         size_t idx = 0;
297         if ((pars == NULL) || (sscanf(pars, " %zu", &idx) < 1)) {
298                 _printf(CMD_COLOR_RED, "You have to specify identifier of the pool to be "
299                                 "destroyed after command! Format: " CMD_DESTROY_POOL " <id>\n");
300                 return FAIL;
301         }
302
303         if (idx > (MAX_POOL_CNT - 1)) {
304                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
305                                 MAX_POOL_CNT - 1);
306                 return FAIL;
307         }
308
309         _logger_log_info(CMD_DESTROY_POOL " command was called");
310         _logger_log_info("Destroying the pool by %zu identifier...", idx);
311
312         if (pools[idx] == NULL)
313                 _logger_log_warn("Pool to be destroyed is NULL");
314
315         ret = sound_pool_destroy(pools[idx]);
316
317         PRINT_INFO_OR_ERROR_INFO(ret == SOUND_POOL_ERROR_NONE,
318                         "sound_pool_destroy(pool) returned %s value",
319                         __stringify_sound_pool_error(ret));
320
321         pools[idx] = NULL;
322
323         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
324 }
325
326 /* CMD_ACTIVATE_POOL */
327 static int __proxy_sound_pool_activate(const char *pars)
328 {
329         int ret = SOUND_POOL_ERROR_NONE;
330         size_t idx = 0;
331         if ((pars == NULL) || (sscanf(pars, " %zu", &idx) < 1)) {
332                 _printf(CMD_COLOR_RED, "You have to specify identifier of the pool "
333                                 "to be activated after command name! Format: "
334                                 CMD_ACTIVATE_POOL " <id>\n");
335                 return FAIL;
336         }
337
338         if (idx > (MAX_POOL_CNT - 1)) {
339                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
340                                 MAX_POOL_CNT - 1);
341                 return FAIL;
342         }
343
344         _logger_log_info(CMD_ACTIVATE_POOL " command was called");
345         _logger_log_info("Activating the pool by %zu identifier...", idx);
346
347         if (pools[idx] == NULL)
348                 _logger_log_warn("Pool to be activated is NULL");
349
350         ret = sound_pool_activate(pools[idx]);
351
352         PRINT_INFO_OR_ERROR_INFO(ret == SOUND_POOL_ERROR_NONE,
353                         "sound_pool_set_state(pool, SOUND_POOL_STATE_ACTIVE) returned "
354                         "%s value", __stringify_sound_pool_error(ret));
355
356         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
357 }
358
359 /* CMD_DEACTIVATE_POOL */
360 static int __proxy_sound_pool_deactivate(const char *pars)
361 {
362         size_t idx = 0;
363         if ((pars == NULL) || (sscanf(pars, " %zu", &idx) < 1)) {
364                 _printf(CMD_COLOR_RED, "You have to specify identifier of the pool "
365                                 "to be deactivated after command name! Format: "
366                                 CMD_DEACTIVATE_POOL " <id>\n");
367                 return FAIL;
368         }
369
370         if (idx > (MAX_POOL_CNT - 1)) {
371                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
372                                 MAX_POOL_CNT - 1);
373                 return FAIL;
374         }
375
376         _logger_log_info(CMD_DEACTIVATE_POOL " command was called");
377         _logger_log_info("Deactivating the pool by %zu identifier...", idx);
378
379         if (pools[idx] == NULL)
380                 _logger_log_warn("Pool to be deactivated is NULL");
381
382         int ret = sound_pool_deactivate(pools[idx]);
383
384         PRINT_INFO_OR_ERROR_INFO(ret == SOUND_POOL_ERROR_NONE,
385                         "sound_pool_set_state(pool, SOUND_POOL_STATE_INACTIVE) returned "
386                         "%s value", __stringify_sound_pool_error(ret));
387
388         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
389 }
390
391 /* CMD_GET_POOL_STATE */
392 static int __proxy_sound_pool_get_state(const char *pars)
393 {
394         size_t idx = 0;
395         if ((pars == NULL) || (sscanf(pars, " %zu", &idx) < 1)) {
396                 _printf(CMD_COLOR_RED, "You have to specify identifier of the pool "
397                                 "to get state for, after command name! Format: "
398                                 CMD_GET_POOL_STATE " <id>\n");
399                 return FAIL;
400         }
401
402         if (idx > (MAX_POOL_CNT - 1)) {
403                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
404                                 MAX_POOL_CNT - 1);
405                 return FAIL;
406         }
407
408         _logger_log_info(CMD_GET_POOL_STATE " command was called");
409         _logger_log_info("Getting the pool state by %zu identifier...", idx);
410
411         if (pools[idx] == NULL)
412                 _logger_log_warn("Pool to get state for is NULL");
413
414         sound_pool_state_e state = SOUND_POOL_STATE_INACTIVE;
415         int ret = sound_pool_get_state(pools[idx], &state);
416
417         const char *str_state = (state == SOUND_POOL_STATE_ACTIVE ?
418                         "SOUND_POOL_STATE_ACTIVE" : "SOUND_POOL_STATE_INACTIVE");
419
420         PRINT_INFO_OR_ERROR_INFO(ret == SOUND_POOL_ERROR_NONE,
421                         "sound_pool_get_state(pool, state) returned %s value,"
422                         " state is %s", __stringify_sound_pool_error(ret), str_state);
423
424         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
425 }
426
427 /* CMD_SET_POOL_VOLUME */
428 static int __proxy_sound_pool_set_volume(const char *pars)
429 {
430         size_t idx = 0;
431         float volume = .0f;
432         if ((pars == NULL) || (sscanf(pars, " %zu %f", &idx, &volume) < 2)) {
433                 _printf(CMD_COLOR_RED, "You have to specify both identifier of the "
434                                 "pool and new volume float value to set volume for whole pool! "
435                                 "Format: " CMD_SET_POOL_VOLUME " <id> <volume>\n");
436                 return FAIL;
437         }
438
439         if (idx > (MAX_POOL_CNT - 1)) {
440                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
441                                 MAX_POOL_CNT - 1);
442                 return FAIL;
443         }
444
445         _logger_log_info(CMD_SET_POOL_VOLUME " command was called");
446         _logger_log_info("Set %f volume value for pool with %zu identifier...",
447                         volume, idx);
448
449         if (pools[idx] == NULL)
450                 _logger_log_warn("Pool to get state for is NULL");
451
452         if (volume < .0f || volume > 1.0f)
453                 _logger_log_warn("Volume is set as %f, not in [0, 1.0] range", volume);
454
455         int ret = sound_pool_set_volume(pools[idx], volume);
456
457         PRINT_INFO_OR_ERROR_INFO(ret == SOUND_POOL_ERROR_NONE,
458                         "sound_pool_set_global_volume(pool, %f) returned %s value",
459                         volume, __stringify_sound_pool_error(ret));
460
461         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
462 }
463
464 /* CMD_GET_POOL_VOLUME */
465 static int __proxy_sound_pool_get_volume(const char *pars)
466 {
467         size_t idx = 0;
468         if ((pars == NULL) || (sscanf(pars, " %zu", &idx) < 1)) {
469                 _printf(CMD_COLOR_RED, "You have to specify identifier of the pool "
470                                 "to get volume for, after command name! Format: "
471                                 CMD_GET_POOL_VOLUME " <id>\n");
472                 return FAIL;
473         }
474
475         if (idx > (MAX_POOL_CNT - 1)) {
476                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
477                                 MAX_POOL_CNT - 1);
478                 return FAIL;
479         }
480
481         _logger_log_info(CMD_GET_POOL_VOLUME " command was called");
482         _logger_log_info("Getting the pool global volume for pool with %zu "
483                         "identifier...", idx);
484
485         if (pools[idx] == NULL)
486                 _logger_log_warn("Pool to get state for is NULL");
487
488         float volume = .0f;
489         int ret = sound_pool_get_volume(pools[idx], &volume);
490
491         PRINT_INFO_OR_ERROR_INFO(ret == SOUND_POOL_ERROR_NONE,
492                         "sound_pool_get_global_volume(pool, volume) returned %s value, "
493                         "volume is %f", __stringify_sound_pool_error(ret), volume);
494
495         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
496 }
497
498 /* CMD_SET_POOL_CB_MSG */
499 static int __proxy_sound_pool_set_state_changed_cb_message(const char *pars)
500 {
501         size_t idx = 0;
502
503         char msg[MAX_MSG_LEN] = { '\0' };
504
505         if ((pars == NULL) || (sscanf(pars, " %zu %"MAX_MSG_LEN_STR"[^ ]", &idx, msg) < 2)) {
506                 _printf(CMD_COLOR_RED, "You have to specify both identifier of the "
507                                 "pool and message to be shown each time when state of the pool "
508                                 " is changed! Message should be a single word. Format: "
509                                 CMD_SET_POOL_CB_MSG " <id> <message>\n");
510                 return FAIL;
511         }
512
513         if (idx > (MAX_POOL_CNT - 1)) {
514                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
515                                 MAX_POOL_CNT - 1);
516                 return FAIL;
517         }
518
519         _logger_log_info(CMD_SET_POOL_CB_MSG " command was called");
520         _logger_log_info("Set state changing callback (%s message) for pool with "
521                         "%zu identifier...", msg, idx);
522
523         if (pools[idx] == NULL)
524                 _logger_log_warn("Pool to set callback for is NULL");
525
526         if (messages[idx])
527                 free(messages[idx]);
528         messages[idx] = strndup(msg, MAX_MSG_LEN);
529
530         int ret = sound_pool_set_state_changed_cb(pools[idx], __sp_cb_msg,
531                         messages[idx]);
532
533         PRINT_INFO_OR_ERROR_INFO(ret == SOUND_POOL_ERROR_NONE,
534                         "sound_pool_set_state_change_callback(pool, cb, \"%s\") "
535                         "returned %s value", msg, __stringify_sound_pool_error(ret));
536
537         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
538 }
539
540 /* CMD_SET_POOL_CB_SCRIPT */
541 static int __proxy_sound_pool_set_state_changed_cb_script(const char *pars)
542 {
543         size_t idx = 0;
544
545         char scr[MAX_MSG_LEN] = { '\0' };
546
547         if ((pars == NULL) || (sscanf(pars, " %zu %"MAX_MSG_LEN_STR"[^ ]", &idx, scr) < 2)) {
548                 _printf(CMD_COLOR_RED, "You have to specify both identifier of the "
549                                 "pool and script file name to be executed each time when state "
550                                 "of the pool will be changed! Format: "
551                                 CMD_SET_POOL_CB_SCRIPT " <id> <script file>\n");
552                 return FAIL;
553         }
554
555         if (idx > (MAX_POOL_CNT - 1)) {
556                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
557                                 MAX_POOL_CNT - 1);
558                 return FAIL;
559         }
560
561         _logger_log_info(CMD_SET_POOL_CB_SCRIPT " command was called");
562         _logger_log_info("Set state changing callback (%s script) for pool with "
563                         "%zu identifier...", scr, idx);
564
565         if (pools[idx] == NULL)
566                 _logger_log_warn("Pool to set callback for is NULL");
567
568         if (scripts[idx])
569                 free(scripts[idx]);
570         scripts[idx] = strndup(scr, MAX_MSG_LEN);
571
572         int ret = sound_pool_set_state_changed_cb(pools[idx], __sp_cb_scr,
573                         scripts[idx]);
574
575         PRINT_INFO_OR_ERROR_INFO(ret == SOUND_POOL_ERROR_NONE,
576                         "sound_pool_set_state_change_callback(pool, cb, \"%s\") "
577                         "returned %s value", scr, __stringify_sound_pool_error(ret));
578
579         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
580 }
581
582 /* CMD_UNSET_POOL_CB */
583 static int __proxy_sound_pool_unset_state_changed_cb(const char *pars)
584 {
585         size_t idx = 0;
586         if ((pars == NULL) || (sscanf(pars, " %zu", &idx) < 1)) {
587                 _printf(CMD_COLOR_RED, "You have to specify identifier of the pool! "
588                                 "Format: " CMD_UNSET_POOL_CB " <id>\n");
589                 return FAIL;
590         }
591
592         if (idx > (MAX_POOL_CNT - 1)) {
593                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
594                                 MAX_POOL_CNT - 1);
595                 return FAIL;
596         }
597
598         _logger_log_info(CMD_UNSET_POOL_CB " command was called");
599         _logger_log_info("Unset state changing callback for pool with "
600                         "%zu identifier...", idx);
601
602         if (pools[idx] == NULL)
603                 _logger_log_warn("Pool to unset callback for is NULL");
604
605         int ret = sound_pool_unset_state_changed_cb(pools[idx]);
606
607         if (messages[idx] != NULL)
608                 free(messages[idx]);
609         messages[idx] = NULL;
610
611         if (scripts[idx] != NULL)
612                 free(scripts[idx]);
613         scripts[idx] = NULL;
614
615         PRINT_INFO_OR_ERROR_INFO(ret == SOUND_POOL_ERROR_NONE,
616                         "sound_pool_unset_state_change_callback(pool) "
617                         "returned %s value", __stringify_sound_pool_error(ret));
618
619         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
620 }
621
622 /* CMD_LIST_POOL */
623 static int __proxy_sound_pool_list()
624 {
625         _logger_log_info("Getting the pool identifiers...");
626
627         const size_t buffer_size = 1024;
628         char buffer[buffer_size];
629         buffer[0] = '\0';
630
631         size_t idx = 0;
632         size_t len = 0;
633         while (idx < MAX_POOL_CNT) {
634                 len = strnlen(buffer, buffer_size);
635                 if (pools[idx++] != NULL) {
636                         size_t add_len = 1;
637                         size_t id = idx - 1;
638                         do
639                                 add_len++;
640                         while ((id = id / 10) > 0);
641                         id = idx - 1;
642                         if (len + add_len + 1 > buffer_size)
643                                 break;
644                         snprintf(buffer + len, buffer_size, "%zu ", id);
645                 }
646         }
647
648         _printf(CMD_COLOR_GREEN, "Pools identifiers: %s\n", buffer);
649         _logger_log_info("Pools identifiers: %s", buffer);
650
651         _logger_log_info("Pool identifiers were retrieved...");
652
653         return OK;
654 }
655
656 /* CMD_LOAD_SOURCE */
657 static int __proxy_sound_pool_load_source_from_file(const char *pars)
658 {
659         size_t idx = 0;
660
661         char fname[MAX_PATH_LEN] = {'\0'};
662         char tag[MAX_PATH_LEN] = {'\0'};
663
664         if ((pars == NULL) || sscanf(pars, " %zu %"MAX_PATH_LEN_STR"[^ ] "
665                         "%"MAX_PATH_LEN_STR"[^ ]", &idx, fname, tag) < 2) {
666                 _printf(CMD_COLOR_RED, "You have to specify at least pool identifier and "
667                                 "file name to be loaded! Format: " CMD_LOAD_SOURCE " <pool id> "
668                                 "<file name> <source tag>\n");
669                 return FAIL;
670         }
671
672         if (idx > (MAX_POOL_CNT - 1)) {
673                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
674                                 MAX_POOL_CNT - 1);
675                 return FAIL;
676         }
677
678         if (pools[idx] == NULL)
679                 _logger_log_warn("Pool with specified identifier is NULL");
680
681         /* If tag wasn't specified by the user, we will use file path as a tag */
682         if (tag[0] == '\0')
683                 strncpy(tag, fname, MAX_PATH_LEN - 1);
684
685         _logger_log_info(CMD_LOAD_SOURCE " command was called");
686         _logger_log_info("Loading source to the pool with %zu identifier from %s file. "
687                         "Tag '%s' will be assigned for the loaded source...", idx, fname, tag);
688
689         int ret = sound_pool_load_source_from_file(pools[idx], fname, tag);
690
691         PRINT_INFO_OR_ERROR_INFO(ret == SOUND_POOL_ERROR_NONE,
692                         "sound_pool_load_source_from_file(pool, \"%s\", \"%s\") returned "
693                         "%s value", fname, tag, __stringify_sound_pool_error(ret));
694
695         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
696 }
697
698 /* CMD_UNLOAD_SOURCE */
699 static int __proxy_sound_pool_unload_source(const char *pars)
700 {
701         size_t idx = 0;
702
703         char tag[MAX_PATH_LEN] = {'\0'};
704
705         if ((pars == NULL) || sscanf(pars, " %zu %"MAX_PATH_LEN_STR"[^ ]", &idx, tag) < 2) {
706                 _printf(CMD_COLOR_RED, "You have to specify both pool identifier and "
707                                 "source tag to be unloaded! Format: " CMD_UNLOAD_SOURCE
708                                 " <pool id> <source tag>\n");
709                 return FAIL;
710         }
711
712         if (idx > (MAX_POOL_CNT - 1)) {
713                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
714                                 MAX_POOL_CNT - 1);
715                 return FAIL;
716         }
717
718         if (pools[idx] == NULL)
719                 _logger_log_warn("Pool with specified identifier is NULL");
720
721         _logger_log_info(CMD_UNLOAD_SOURCE " command was called");
722         _logger_log_info("Unloading source by '%s' tag from the pool with %zu "
723                         "identifier...", tag, idx);
724
725         int ret = sound_pool_unload_source(pools[idx], tag);
726
727         PRINT_INFO_OR_ERROR_INFO(ret == SOUND_POOL_ERROR_NONE,
728                         "sound_pool_unload_source(pool, \"%s\") returned "
729                         "%s value", tag, __stringify_sound_pool_error(ret));
730
731         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
732 }
733
734 /* CMD_PLAY_STREAM */
735 static int __proxy_sound_pool_play_stream(const char *pars)
736 {
737         size_t idx = 0;
738         int loop = 0;
739         float volume = 1.0f;
740         unsigned rank = DEFAULT_STREAM_PRIORITY_RANK;
741         sound_pool_stream_priority_policy_e priority_policy = SOUND_POOL_STREAM_PRIORITY_POLICY_MUTE;
742
743         char tag[MAX_PATH_LEN] = {'\0'};
744
745         if ((pars == NULL) || sscanf(pars, " %zu %"MAX_PATH_LEN_STR"[^ ] %i %f %u %u",
746                                                                 &idx, tag, &loop, &volume, &rank, &priority_policy) < 2) {
747                 _printf(CMD_COLOR_RED, "You have to specify at least pool identifier and "
748                                 "source tag to be played in stream! Format: " CMD_PLAY_STREAM
749                                 " <pool id> <source tag> <loop> <volume> <priority rank> <priority_policy>... "
750                                 "0 'priority rank' value corresponds to the lowest priority.\n");
751                 return FAIL;
752         }
753
754         if (idx > (MAX_POOL_CNT - 1)) {
755                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
756                                 MAX_POOL_CNT - 1);
757                 return FAIL;
758         }
759
760         if (pools[idx] == NULL)
761                 _logger_log_warn("Pool with specified identifier is NULL");
762
763         _logger_log_info(CMD_PLAY_STREAM " command was called");
764         _logger_log_info("Playing stream based on source with '%s' tag from the pool "
765                         "with %zu identifier...", tag, idx);
766
767         unsigned stream_idx = 0;
768         int ret = sound_pool_stream_play(pools[idx], tag, loop, volume, rank, priority_policy, __s_cb_msg,
769                         NULL, &stream_idx);
770
771         if (ret == SOUND_POOL_ERROR_NONE) {
772                 _logger_log_info("sound_pool_play_stream(pool, \"%s\", %i, %f, %u,"
773                                 " %u, %p, NULL, &stream_idx) returned %s value. "
774                                 "Generated identifier is %i", tag, loop, volume, rank, priority_policy, __s_cb_msg,
775                                 __stringify_sound_pool_error(ret), stream_idx);
776                 _printf(CMD_COLOR_GREEN, "Generated stream identifier is %i\n", stream_idx);
777         } else {
778                 _logger_log_err("sound_pool_play_stream(pool, \"%s\", %i, %f, %u,"
779                                 " %u, %p, NULL, &stream_idx) returned %s value",
780                                 tag, loop, volume, rank, priority_policy, __s_cb_msg, __stringify_sound_pool_error(ret));
781         }
782
783         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
784 }
785
786 /* CMD_PAUSE_STREAM */
787 static int __proxy_sound_pool_pause_stream(const char *pars)
788 {
789         size_t idx = 0;
790         size_t stream_idx = 0;
791
792         if ((pars == NULL) || (sscanf(pars, " %zu %i", &idx, &stream_idx) < 2)) {
793                 _printf(CMD_COLOR_RED, "You have to specify both pool identifier and "
794                                 "stream to be paused identifier! Format: " CMD_PAUSE_STREAM
795                                 " <pool id> <stream id>\n");
796                 return FAIL;
797         }
798
799         if (idx > (MAX_POOL_CNT - 1)) {
800                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
801                                 MAX_POOL_CNT - 1);
802                 return FAIL;
803         }
804
805         if (pools[idx] == NULL)
806                 _logger_log_warn("Pool with specified identifier is NULL");
807
808         _logger_log_info(CMD_PAUSE_STREAM " command was called");
809
810         int ret = sound_pool_stream_pause(pools[idx], stream_idx);
811
812         PRINT_INFO_OR_ERROR_INFO(ret == SOUND_POOL_ERROR_NONE,
813                         "sound_pool_pause_stream(pool, %i) returned %s value",
814                         stream_idx, __stringify_sound_pool_error(ret));
815
816         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
817 }
818
819 /* CMD_RESUME_STREAM */
820 static int __proxy_sound_pool_resume_stream(const char *pars)
821 {
822         size_t idx = 0;
823         size_t stream_idx = 0;
824
825         if ((pars == NULL) || (sscanf(pars, " %zu %i", &idx, &stream_idx) < 2)) {
826                 _printf(CMD_COLOR_RED, "You have to specify both pool identifier and "
827                                 "stream to be resumed identifier! Format: " CMD_RESUME_STREAM
828                                 " <pool id> <stream id>\n");
829                 return FAIL;
830         }
831
832         if (idx > (MAX_POOL_CNT - 1)) {
833                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
834                                 MAX_POOL_CNT - 1);
835                 return FAIL;
836         }
837
838         if (pools[idx] == NULL)
839                 _logger_log_warn("Pool with specified identifier is NULL");
840
841         _logger_log_info(CMD_RESUME_STREAM " command was called");
842
843         int ret = sound_pool_stream_resume(pools[idx], stream_idx);
844
845         PRINT_INFO_OR_ERROR_INFO(ret == SOUND_POOL_ERROR_NONE,
846                         "sound_pool_resume_stream(pool, %i) returned %s value",
847                         stream_idx, __stringify_sound_pool_error(ret));
848
849         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
850 }
851
852 /* CMD_STOP_STREAM */
853 static int __proxy_sound_pool_stop_stream(const char *pars)
854 {
855         size_t idx = 0;
856         size_t stream_idx = 0;
857
858         if ((pars == NULL) || (sscanf(pars, " %zu %zu", &idx, &stream_idx) < 2)) {
859                 _printf(CMD_COLOR_RED, "You have to specify both pool identifier and "
860                                 "stream to be stopped identifier! Format: " CMD_STOP_STREAM
861                                 " <pool id> <stream id>\n");
862                 return FAIL;
863         }
864
865         if (idx > (MAX_POOL_CNT - 1)) {
866                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
867                                 MAX_POOL_CNT - 1);
868                 return FAIL;
869         }
870
871         if (pools[idx] == NULL)
872                 _logger_log_warn("Pool with specified identifier is NULL");
873
874         _logger_log_info(CMD_STOP_STREAM " command was called");
875
876         int ret = sound_pool_stream_stop(pools[idx], stream_idx);
877
878         PRINT_INFO_OR_ERROR_INFO(ret == SOUND_POOL_ERROR_NONE,
879                         "sound_pool_stop_stream(pool, %i) returned %s value",
880                         stream_idx, __stringify_sound_pool_error(ret));
881
882         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
883 }
884
885 /* CMD_SET_STREAM_VOLUME */
886 static int __proxy_sound_pool_stream_set_volume(const char *pars)
887 {
888         size_t idx = 0;
889         size_t stream_idx = 0;
890         float volume_val = 1.0f;
891
892         if ((pars == NULL)
893                         || (sscanf(pars, " %zu %zu %f", &idx, &stream_idx, &volume_val) < 3)) {
894                 _printf(CMD_COLOR_RED, "You have to specify all following parameters: "
895                                 "pool identifier, stream identifier! Format: "
896                                 CMD_SET_STREAM_VOLUME " <pool id> <stream id> <volume>\n");
897                 return FAIL;
898         }
899
900         if (idx > (MAX_POOL_CNT - 1)) {
901                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
902                                 MAX_POOL_CNT - 1);
903                 return FAIL;
904         }
905
906         if (pools[idx] == NULL)
907                 _logger_log_warn("Pool with specified identifier is NULL");
908
909         if (volume_val < .0f || volume_val > 1.0f)
910                 _logger_log_warn("Volume has to be specified in 0.0~1.0 range");
911
912         _logger_log_info(CMD_SET_STREAM_VOLUME " command was called");
913
914         int ret = sound_pool_stream_set_volume(pools[idx], stream_idx, volume_val);
915
916         PRINT_INFO_OR_ERROR_INFO(ret == SOUND_POOL_ERROR_NONE,
917                         "sound_pool_stream_set_volume(pool, %i, %f) returned %s value",
918                         stream_idx, volume_val, __stringify_sound_pool_error(ret));
919
920         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
921 }
922
923 /* CMD_GET_STREAM_VOLUME */
924 static int __proxy_sound_pool_stream_get_volume(const char *pars)
925 {
926         size_t idx = 0;
927         size_t stream_idx = 0;
928         if ((pars == NULL) || (sscanf(pars, " %zu %zu", &idx, &stream_idx) < 2)) {
929                 _printf(CMD_COLOR_RED, "You have to specify both pool and stream "
930                                 "identifiers after command name! Format: "
931                                 CMD_GET_STREAM_VOLUME " <pool id> <stream id>\n");
932                 return FAIL;
933         }
934
935         if (idx > (MAX_POOL_CNT - 1)) {
936                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
937                                 MAX_POOL_CNT - 1);
938                 return FAIL;
939         }
940
941         _logger_log_info(CMD_GET_STREAM_VOLUME " command was called");
942         _logger_log_info("Getting the %zu stream from %zu pool volume value...",
943                         stream_idx, idx);
944
945         if (pools[idx] == NULL)
946                 _logger_log_warn("Pool to get state for is NULL");
947
948         float volume = .0f;
949         int ret = sound_pool_stream_get_volume(pools[idx], stream_idx, &volume);
950
951         PRINT_INFO_OR_ERROR_INFO(ret == SOUND_POOL_ERROR_NONE,
952                         "sound_pool_stream_get_volume(pool, %zu, volume) returned %s value, "
953                         "volume is %f", stream_idx, __stringify_sound_pool_error(ret), volume);
954
955         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
956 }
957
958 /* CMD_SET_STREAM_PRIORITY */
959 static int __proxy_sound_pool_stream_set_priority(const char *pars)
960 {
961         size_t idx = 0;
962         size_t stream_idx = 0;
963         unsigned rank = 0;
964
965         if ((pars == NULL)
966                         || (sscanf(pars, " %zu %zu %u", &idx, &stream_idx, &rank) < 3)) {
967                 _printf(CMD_COLOR_RED, "You have to specify all following parameters: "
968                                 "pool identifier, stream identifier, and priority rank! Format: "
969                                 CMD_SET_STREAM_PRIORITY " <pool id> <stream id> <rank>\n");
970                 return FAIL;
971         }
972
973         if (idx > (MAX_POOL_CNT - 1)) {
974                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
975                                 MAX_POOL_CNT - 1);
976                 return FAIL;
977         }
978
979         if (pools[idx] == NULL)
980                 _logger_log_warn("Pool with specified identifier is NULL");
981
982         _logger_log_info(CMD_SET_STREAM_PRIORITY " command was called");
983
984         int ret = sound_pool_stream_set_priority(pools[idx], stream_idx, rank);
985
986         PRINT_INFO_OR_ERROR_INFO(ret == SOUND_POOL_ERROR_NONE,
987                         "sound_pool_stream_set_priority(pool, %zu, %u) returned %s value",
988                         stream_idx, rank, __stringify_sound_pool_error(ret));
989
990         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
991 }
992
993 /* CMD_GET_STREAM_PRIORITY */
994 static int __proxy_sound_pool_stream_get_priority(const char *pars)
995 {
996         size_t idx = 0;
997         size_t stream_idx = 0;
998         if ((pars == NULL) || (sscanf(pars, " %zu %zu", &idx, &stream_idx) < 2)) {
999                 _printf(CMD_COLOR_RED, "You have to specify both pool and stream "
1000                                 "identifiers after command name! Format: "
1001                                 CMD_GET_STREAM_PRIORITY " <pool id> <stream id>\n");
1002                 return FAIL;
1003         }
1004
1005         if (idx > (MAX_POOL_CNT - 1)) {
1006                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
1007                                 MAX_POOL_CNT - 1);
1008                 return FAIL;
1009         }
1010
1011         _logger_log_info(CMD_GET_STREAM_PRIORITY " command was called");
1012         _logger_log_info("Getting the stream priority rank by %zu identifier in "
1013                         "%zu pool...", stream_idx, idx);
1014
1015         if (pools[idx] == NULL)
1016                 _logger_log_warn("Pool where stream should be located is NULL");
1017
1018         unsigned rank = 0;
1019         int ret = sound_pool_stream_get_priority(pools[idx], stream_idx, &rank);
1020
1021         PRINT_INFO_OR_ERROR_INFO(ret == SOUND_POOL_ERROR_NONE,
1022                         "sound_pool_stream_get_priority(pool, %u, rank) returned %s value, "
1023                         "rank value is %u", stream_idx, __stringify_sound_pool_error(ret), rank);
1024
1025         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
1026 }
1027
1028 /* CMD_GET_STREAM_STATE */
1029 static int __proxy_sound_pool_get_stream_state(const char *pars)
1030 {
1031         size_t idx = 0;
1032         size_t stream_idx = 0;
1033         if ((pars == NULL) || (sscanf(pars, " %zu %zu", &idx, &stream_idx) < 2)) {
1034                 _printf(CMD_COLOR_RED, "You have to specify both pool and stream "
1035                                 "identifiers after command name! Format: "
1036                                 CMD_GET_STREAM_STATE " <pool id> <stream id>\n");
1037                 return FAIL;
1038         }
1039
1040         if (idx > (MAX_POOL_CNT - 1)) {
1041                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
1042                                 MAX_POOL_CNT - 1);
1043                 return FAIL;
1044         }
1045
1046         _logger_log_info(CMD_GET_STREAM_STATE " command was called");
1047         _logger_log_info("Getting the stream state by %zu identifier in %zu "
1048                         "pool...", stream_idx, idx);
1049
1050         if (pools[idx] == NULL)
1051                 _logger_log_warn("Pool where stream should be located is NULL");
1052
1053         sound_pool_stream_state_e state = SOUND_POOL_STREAM_STATE_NONE;
1054         int ret = sound_pool_stream_get_state(pools[idx], stream_idx,  &state);
1055
1056         PRINT_INFO_OR_ERROR_INFO(ret == SOUND_POOL_ERROR_NONE,
1057                         "sound_pool_get_stream_state(pool, %zu, state) returned %s value, "
1058                         "state is %s", stream_idx, __stringify_sound_pool_error(ret),
1059                         __stringify_stream_state(state));
1060
1061         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
1062 }
1063
1064 /* CMD_SLEEP */
1065 static int __proxy_sleep(const char *pars)
1066 {
1067         useconds_t stime = 0;
1068
1069         if ((pars == NULL) || (sscanf(pars, " %u", &stime) < 1)) {
1070                 _printf(CMD_COLOR_RED, "You have to specify number of milliseconds "
1071                                 "for the pause duration! Format: " CMD_SLEEP " <millisecs>\n");
1072                 return FAIL;
1073         }
1074
1075         _logger_log_info(CMD_SLEEP " command was called");
1076         _logger_log_info("Start main thread sleep for %u milliseconds...", stime);
1077         stime *= MICROSECS_PER_MILLISEC;
1078         usleep(stime);
1079         _logger_log_info("Main thread sleep has been finished...", stime);
1080
1081         return OK;
1082 }
1083
1084 /* CMD_EXECUTE_SCRIPT */
1085 static int __proxy_sound_pool_execute_script(const char *pars)
1086 {
1087         char script_file[MAX_PATH_LEN] = {'\0'};
1088
1089         if ((pars == NULL) || (sscanf(pars, " %"MAX_PATH_LEN_STR"[^ ]", script_file) < 1)) {
1090                 _printf(CMD_COLOR_RED, "You have to specify script file name to be "
1091                                 "executed after command name! Format: " CMD_EXECUTE_SCRIPT " "
1092                                 "<script file>\n");
1093                 return FAIL;
1094         }
1095
1096         _logger_log_info(CMD_EXECUTE_SCRIPT " command was called");
1097         _logger_log_info("Loading script from file...");
1098         FILE *fd = fopen(script_file, "r");
1099
1100         if (fd) {
1101                 _logger_log_info("File has been loaded...");
1102                 _logger_log_info("Reading lines...");
1103                 size_t line_len = 0;
1104                 char *line = NULL;
1105                 while ((line_len = getline(&line, &line_len, fd)) != -1) {
1106                         line[strnlen(line, MAX_COMMAND_LINE_LEN) - 1] = '\0';
1107                         _logger_log_info("Executing line: %s", line);
1108                         if (_exec_cmd(line) != OK)
1109                                 _logger_log_warn("Unknown or unsupported command! "
1110                                                 "Line was skipped.");
1111                 }
1112                 _logger_log_info("Lines were read...");
1113         } else {
1114                 _logger_log_err("File wasn't loaded...");
1115                 return FAIL;
1116         }
1117
1118         _logger_log_info("Close file...");
1119
1120         if (fd)
1121                 fclose(fd);
1122
1123         return OK;
1124 }
1125
1126 /* Number of parameters supported by each command */
1127 static int cmd_pars[MAX_COMMAND_LINE_LEN] = { /* CMD_EXIT */ 0,
1128                 /* CMD_HELP */ 0, /* CMD_CREATE_POOL */ 0, /* CMD_DESTROY_POOL */ 1,
1129                 /* CMD_ACTIVATE_POOL */ 1, /* CMD_DEACTIVATE_POOL */ 1,
1130                 /* CMD_GET_POOL_STATE */ 1, /* CMD_SET_POOL_VOLUME */ 2,
1131                 /* CMD_GET_POOL_VOLUME */ 2, /* CMD_SET_POOL_CB_MSG */ 2,
1132                 /* CMD_SET_POOL_CB_SCRIPT */ 2, /* CMD_UNSET_POOL_CB */ 1,
1133                 /* CMD_LIST_POOL */ 0, /* CMD_LOAD_SOURCE */ 3,
1134                 /* CMD_LOAD_MEDIA_PACKAGE */ 3, /* CMD_UNLOAD_SOURCE */ 2,
1135                 /* CMD_PLAY_STREAM */ 5, /* CMD_STOP_STREAM */ 2,
1136                 /* CMD_PAUSE_STREAM */ 2, /* CMD_RESUME_STREAM */ 2,
1137                 /* CMD_SET_STREAM_VOLUME */ 3, /* CMD_GET_STREAM_VOLUME */ 2,
1138                 /* CMD_SET_STREAM_PRIORITY */ 3, /* CMD_GET_STREAM_PRIORITY */ 2,
1139                 /* CMD_GET_STREAM_STATE */ 2, /* CMD_SET_STREAM_CB_MSG */ 3,
1140                 /* CMD_SET_STREAM_CB_SCRIPT */ 3, /* CMD_UNSET_STREAM_CB */ 2,
1141                 /* CMD_EXECUTE_SCRIPT */ 1, /* CMD_SLEEP */ 1 };
1142
1143 /* Command -> Function mapping */
1144 static int (*cmd_fcns[MAX_COMMAND_LINE_LEN])() = {
1145                 /* CMD_EXIT */ __exit,
1146                 /* CMD_HELP */ __print_cmd_help_msg,
1147                 /* CMD_CREATE_POOL */ __proxy_sound_pool_create,
1148                 /* CMD_DESTROY_POOL */ __proxy_sound_pool_destroy,
1149                 /* CMD_ACTIVATE_POOL */ __proxy_sound_pool_activate,
1150                 /* CMD_DEACTIVATE_POOL */ __proxy_sound_pool_deactivate,
1151                 /* CMD_GET_POOL_STATE */ __proxy_sound_pool_get_state,
1152                 /* CMD_SET_POOL_VOLUME */ __proxy_sound_pool_set_volume,
1153                 /* CMD_GET_POOL_VOLUME */ __proxy_sound_pool_get_volume,
1154                 /* CMD_SET_POOL_CB_MSG */ __proxy_sound_pool_set_state_changed_cb_message,
1155                 /* CMD_SET_POOL_CB_SCRIPT */ __proxy_sound_pool_set_state_changed_cb_script,
1156                 /* CMD_UNSET_POOL_CB */ __proxy_sound_pool_unset_state_changed_cb,
1157                 /* CMD_LIST_POOL */ __proxy_sound_pool_list,
1158                 /* CMD_LOAD_SOURCE */ __proxy_sound_pool_load_source_from_file,
1159                 /* CMD_LOAD_MEDIA_PACKAGE */ NULL,
1160                 /* CMD_UNLOAD_SOURCE */ __proxy_sound_pool_unload_source,
1161                 /* CMD_PLAY_STREAM */ __proxy_sound_pool_play_stream,
1162                 /* CMD_STOP_STREAM */ __proxy_sound_pool_stop_stream,
1163                 /* CMD_PAUSE_STREAM */ __proxy_sound_pool_pause_stream,
1164                 /* CMD_RESUME_STREAM */ __proxy_sound_pool_resume_stream,
1165                 /* CMD_SET_STREAM_VOLUME */ __proxy_sound_pool_stream_set_volume,
1166                 /* CMD_GET_STREAM_VOLUME */ __proxy_sound_pool_stream_get_volume,
1167                 /* CMD_SET_STREAM_PRIORITY */ __proxy_sound_pool_stream_set_priority,
1168                 /* CMD_GET_STREAM_PRIORITY */ __proxy_sound_pool_stream_get_priority,
1169                 /* CMD_GET_STREAM_STATE */ __proxy_sound_pool_get_stream_state,
1170                 /* CMD_EXECUTE_SCRIPT */ __proxy_sound_pool_execute_script,
1171                 /* CMD_SLEEP */ __proxy_sleep };
1172
1173 int _exec_cmd(const char *cmd_line)
1174 {
1175         /* User just pressed enter: */
1176         if (strlen(cmd_line) == 0) return OK;
1177
1178         size_t trim_len = 0;
1179         while ((cmd_line + trim_len)[0] == ' ')
1180                 trim_len++;
1181
1182         const char *cmd = cmd_line + trim_len;
1183
1184         /* Macro for checking command correctness */
1185 #   define CHECK_CMD(ccmd, line) \
1186                         (strncmp(ccmd, line, strnlen(ccmd, MAX_COMMAND_LINE_LEN)) == 0)
1187
1188         int idx = 0;
1189         for (; idx < CMD_COUNT; ++idx) {
1190                 if (CHECK_CMD(cmd_list[idx], cmd)) {
1191                         if (cmd_pars[idx] > 0) {
1192                                 if (cmd_fcns[idx])
1193                                         return cmd_fcns[idx](cmd + strlen(cmd_list[idx]));
1194                         } else {
1195                                 return cmd_fcns[idx]();
1196                         }
1197                 }
1198         }
1199
1200         return UCMD;
1201 }