Add policy(Mute option instead of suspend) on revised logic
[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 /* Messages to be used for callbacks output (for pool state changing) */
39 static char *stream_messages[MAX_POOL_CNT][MAX_STREAM_CNT] = { { NULL } };
40 /* Messages to be used for callbacks output (for stream state changing) */
41 static char *stream_scripts[MAX_POOL_CNT][MAX_STREAM_CNT] = { { NULL } };
42
43 static const char *__stringify_sound_pool_error(sound_pool_error_e error);
44 static int __proxy_sound_pool_execute_script(const char *pars);
45
46 static const char *__stringify_sound_pool_error(sound_pool_error_e error)
47 {
48         switch (error) {
49         case SOUND_POOL_ERROR_NONE:
50                 return "SOUND_POOL_ERROR_NONE";
51                 break;
52         case SOUND_POOL_ERROR_NOT_SUPPORTED:
53                 return "SOUND_POOL_ERROR_NOT_SUPPORTED";
54                 break;
55         case SOUND_POOL_ERROR_MSG_TOO_LONG:
56                 return "SOUND_POOL_ERROR_MSG_TOO_LONG";
57                 break;
58         case SOUND_POOL_ERROR_NO_DATA:
59                 return "SOUND_POOL_ERROR_NO_DATA";
60                 break;
61         case SOUND_POOL_ERROR_KEY_NOT_AVAILABLE:
62                 return "SOUND_POOL_ERROR_KEY_NOT_AVAILABLE";
63                 break;
64         case SOUND_POOL_ERROR_OUT_OF_MEMORY:
65                 return "SOUND_POOL_ERROR_OUT_OF_MEMORY";
66                 break;
67         case SOUND_POOL_ERROR_INVALID_PARAMETER:
68                 return "SOUND_POOL_ERROR_INVALID_PARAMETER";
69                 break;
70         case SOUND_POOL_ERROR_INVALID_OPERATION:
71                 return "SOUND_POOL_ERROR_INVALID_OPERATION";
72                 break;
73         case SOUND_POOL_ERROR_PERMISSION_DENIED:
74                 return "SOUND_POOL_ERROR_PERMISSION_DENIED";
75                 break;
76         case SOUND_POOL_ERROR_NO_SUCH_FILE:
77                 return "SOUND_POOL_ERROR_NO_SUCH_FILE";
78                 break;
79         default:
80                 return "";
81                 break;
82         }
83
84         return NULL;
85 }
86
87 const char *__stringify_stream_state(sound_pool_stream_state_e state)
88 {
89         switch (state) {
90         case SOUND_POOL_STREAM_STATE_NONE:
91                 return "SOUND_POOL_STREAM_STATE_NONE";
92                 break;
93         case SOUND_POOL_STREAM_STATE_PLAYING:
94                 return "SOUND_POOL_STREAM_STATE_PLAYING";
95                 break;
96         case SOUND_POOL_STREAM_STATE_PAUSED:
97                 return "SOUND_POOL_STREAM_STATE_PAUSED";
98                 break;
99         case SOUND_POOL_STREAM_STATE_SUSPENDED:
100                 return "SOUND_POOL_STREAM_STATE_SUSPENDED";
101                 break;
102         case SOUND_POOL_STREAM_STATE_STOPPED:
103                 return "SOUND_POOL_STREAM_STATE_STOPPED";
104                 break;
105         case SOUND_POOL_STREAM_STATE_FINISHED:
106                 return "SOUND_POOL_STREAM_STATE_FINISHED";
107                 break;
108         default:
109                 return "";
110                 break;
111         }
112
113         return NULL;
114 }
115
116 static void __sp_cb_msg(sound_pool_h pool, sound_pool_state_e prev_state,
117                 sound_pool_state_e cur_state, void *data)
118 {
119         const char *msg = (const char *)data;
120         _logger_log_info("Sound pool state was changing from %s to %s: %s",
121                         prev_state == SOUND_POOL_STATE_ACTIVE ?
122                                         "SOUND_POOL_STATE_ACTIVE" : "SOUND_POOL_STATE_INACTIVE",
123                         cur_state == SOUND_POOL_STATE_ACTIVE ?
124                                         "SOUND_POOL_STATE_ACTIVE" : "SOUND_POOL_STATE_INACTIVE",
125                         msg ? msg : "No message");
126 }
127
128 static void __sp_cb_scr(sound_pool_h pool, sound_pool_state_e prev_state,
129                 sound_pool_state_e cur_state, void *data)
130 {
131         const char *scr = (const char *)data;
132         _logger_log_info("Sound pool state was changing from %s to %s; "
133                         "Executing: %s...",
134                         prev_state == SOUND_POOL_STATE_ACTIVE ? "SOUND_POOL_STATE_ACTIVE" :
135                                         "SOUND_POOL_STATE_INACTIVE",
136                         cur_state == SOUND_POOL_STATE_ACTIVE ? "SOUND_POOL_STATE_ACTIVE" :
137                                         "SOUND_POOL_STATE_INACTIVE",
138                         scr ? scr : "No script");
139         __proxy_sound_pool_execute_script(scr);
140 }
141
142 static void __s_cb_msg(sound_pool_h pool, const char *tag, unsigned id,
143                 sound_pool_stream_state_e prev_state,
144                 sound_pool_stream_state_e cur_state, void *data)
145 {
146         const char *msg = (const char *)data;
147         _logger_log_info("Stream state was changing from %s to %s: %s",
148                         __stringify_stream_state(prev_state),
149                         __stringify_stream_state(cur_state),
150                         msg ? msg : "No message");
151 }
152
153 static void __s_cb_scr(sound_pool_h pool, const char *tag, unsigned id,
154                 sound_pool_stream_state_e prev_state,
155                 sound_pool_stream_state_e cur_state, void *data)
156 {
157         const char *scr = (const char *)data;
158         _logger_log_info("Sound pool state was changing from %s to %s; "
159                         "Executing: %s...", __stringify_stream_state(prev_state),
160                         __stringify_stream_state(cur_state),
161                         scr ? scr : "No script");
162         __proxy_sound_pool_execute_script(scr);
163 }
164
165 /* CMD_EXIT */
166 static int __exit()
167 {
168         return EXIT;
169 }
170
171 /* CMD_HELP */
172 static int __print_cmd_help_msg()
173 {
174         printf("\nTest suite usage help:\n");
175
176         printf(CMD_HELP "\n");
177         printf("\t- Shows this help.\n");
178
179         printf(CMD_CREATE_POOL "\n");
180         printf("\t- creates pool with specific identifier.\n");
181
182         printf(CMD_DESTROY_POOL "\n");
183         printf("\t- destroys pool with specific identifier.\n");
184
185         printf(CMD_ACTIVATE_POOL "\n");
186         printf("\t- activates pool with specific identifier.\n");
187
188         printf(CMD_DEACTIVATE_POOL "\n");
189         printf("\t- deactivates pool with specific identifier.\n");
190
191         printf(CMD_GET_POOL_STATE "\n");
192         printf("\t- shows state of the pool with specific identifier.\n");
193
194         printf(CMD_SET_POOL_VOLUME "\n");
195         printf("\t- use this command to set volume for the specific sound pool.\n");
196
197         printf(CMD_GET_POOL_VOLUME "\n");
198         printf("\t- shows volume of the sound pool with specific identifier.\n");
199
200         printf(CMD_SET_POOL_CB_MSG "\n");
201         printf("\t- sets callback which will show the message when sound pool "
202                         "state is changed.\n");
203
204         printf(CMD_SET_POOL_CB_SCRIPT "\n");
205         printf("\t- sets callback which will execute the script when sound pool "
206                         "state is changed.\n");
207
208         printf(CMD_UNSET_POOL_CB "\n");
209         printf("\t- unsets the callback for the sound pool.\n");
210
211         printf(CMD_LIST_POOL "\n");
212         printf("\t- shows ids of all pools had been created and their states.\n");
213
214         printf(CMD_LOAD_SOURCE "\n");
215         printf("\t- loads the source with specific source tag.\n");
216
217         printf(CMD_UNLOAD_SOURCE "\n");
218         printf("\t- unloads the source with specific source tag.\n");
219
220         printf(CMD_PLAY_STREAM "\n");
221         printf("\t- creates the stream with unique identifier and starts playback.\n"
222                         "\t  Source tag to be used for stream creation should be specified.\n");
223
224         printf(CMD_STOP_STREAM "\n");
225         printf("\t- stops the stream playback. Stream unique identifier should be\n"
226                         "\t  specified after command. After stopping the stream became invalid.\n");
227
228         printf(CMD_PAUSE_STREAM "\n");
229         printf("\t- pauses the stream playback. Stream unique identifier should be\n"
230                         "\t  specified after command.\n");
231
232         printf(CMD_RESUME_STREAM "\n");
233         printf("\t- resumes the stream was paused before. Stream unique identifier\n"
234                         "\t  should be specified after command.\n");
235
236         printf(CMD_SET_STREAM_VOLUME "\n");
237         printf("\t- use this command to set volume parameter of the stream.\n");
238
239         printf(CMD_GET_STREAM_VOLUME "\n");
240         printf("\t- shows volume of the stream in the pool with specified "
241                         "identifiers.\n");
242
243         printf(CMD_SET_STREAM_LOOP "\n");
244         printf("\t- use this command to set loop parameter of the stream.\n");
245
246         printf(CMD_GET_STREAM_LOOP "\n");
247         printf("\t- shows loop count of the stream in the pool with specified "
248                         "identifiers.\n");
249
250         printf(CMD_SET_STREAM_PRIORITY "\n");
251         printf("\t- use this command to set priority parameter of the stream. "
252                         "0 is the lowest priority.\n");
253
254         printf(CMD_GET_STREAM_PRIORITY "\n");
255         printf("\t- shows priority rank of the stream in the pool with specified "
256                         "identifiers. 0 is the lowest priority.\n");
257
258         printf(CMD_GET_STREAM_STATE "\n");
259         printf("\t- shows state of the stream in the pool with specified "
260                         "identifiers.\n");
261
262         printf(CMD_SET_STREAM_CB_MSG "\n");
263         printf("\t- sets callback which will show the message when sound stream "
264                         "state is changed.\n");
265
266         printf(CMD_SET_STREAM_CB_SCRIPT "\n");
267         printf("\t- sets callback which will execute the script (from file) when "
268                         "sound stream state is changed.\n");
269
270         printf(CMD_UNSET_STREAM_CB "\n");
271         printf("\t- unsets the callback for the sound stream.\n");
272
273         printf(CMD_EXECUTE_SCRIPT "\n");
274         printf("\t- executes the script from the file in filesystem. Script has to\n"
275                         "\t  be compiled with commands supported by testsuite, one command\n"
276                         "\t  per single line.\n");
277
278         printf(CMD_SLEEP "\n");
279         printf("\t- suspends execution of the main thread for the specific amount "
280                         "of milleseconds.\n");
281
282         printf(CMD_EXIT "\n");
283         printf("\t- exits from the test suite.\n");
284
285         printf("\n");
286
287         return OK;
288 }
289
290 /* CMD_CREATE_POOL */
291 static int __proxy_sound_pool_create()
292 {
293         _logger_log_info(CMD_CREATE_POOL " command was called");
294         _logger_log_info("Creating the pool...");
295
296         sound_pool_h pool = NULL;
297         int ret = sound_pool_create(&pool);
298
299         if (ret == SOUND_POOL_ERROR_NONE) {
300                 _logger_log_info("sound_pool_create(pool) returned %s value",
301                                 __stringify_sound_pool_error(ret));
302
303                 size_t idx = 0;
304                 while (idx < MAX_POOL_CNT) {
305                         if (pools[idx++] == NULL) {
306                                 pools[--idx] = pool;
307                                 break;
308                         }
309                 }
310
311                 if (idx == MAX_POOL_CNT) {
312                         _printf(CMD_COLOR_RED, "Limit of possible pools is exceeded. Destroy "
313                                         "some pools before creating of new ones.\n");
314
315                         _logger_log_warn("Pool can't be created due to test suite "
316                                         "restrictions. Destroying the pool...");
317
318                         ret = sound_pool_destroy(pool);
319                         if (ret == SOUND_POOL_ERROR_NONE)
320                                 _logger_log_info("sound_pool_destroy(pool) returned %s value",
321                                                 __stringify_sound_pool_error(ret));
322                         else
323                                 _logger_log_err("sound_pool_destroy(pool) returned %s value",
324                                                 __stringify_sound_pool_error(ret));
325
326                         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
327                 }
328
329                 if (!pool)
330                         _logger_log_warn("Created pool is NULL");
331                 else
332                         _logger_log_info("Identifier of the pool has been created is %zu", idx);
333         } else {
334                 _logger_log_err("sound_pool_create(pool) returned %s value",
335                                 __stringify_sound_pool_error(ret));
336         }
337
338         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
339 }
340
341 /* CMD_DESTROY_POOL */
342 static int __proxy_sound_pool_destroy(const char *pars)
343 {
344         int ret = SOUND_POOL_ERROR_NONE;
345         size_t idx = 0;
346         if ((pars == NULL) || (sscanf(pars, " %zu", &idx) < 1)) {
347                 _printf(CMD_COLOR_RED, "You have to specify identifier of the pool to be "
348                                 "destroyed after command! Format: " CMD_DESTROY_POOL " <id>\n");
349                 return FAIL;
350         }
351
352         if (idx > (MAX_POOL_CNT - 1)) {
353                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
354                                 MAX_POOL_CNT - 1);
355                 return FAIL;
356         }
357
358         _logger_log_info(CMD_DESTROY_POOL " command was called");
359         _logger_log_info("Destroying the pool by %zu identifier...", idx);
360
361         if (pools[idx] == NULL)
362                 _logger_log_warn("Pool to be destroyed is NULL");
363
364         ret = sound_pool_destroy(pools[idx]);
365
366         if (ret == SOUND_POOL_ERROR_NONE)
367                 _logger_log_info("sound_pool_destroy(pool) returned %s value",
368                                 __stringify_sound_pool_error(ret));
369         else
370                 _logger_log_err("sound_pool_destroy(pool) returned %s value",
371                                 __stringify_sound_pool_error(ret));
372
373         pools[idx] = NULL;
374
375         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
376 }
377
378 /* CMD_ACTIVATE_POOL */
379 static int __proxy_sound_pool_activate(const char *pars)
380 {
381         int ret = SOUND_POOL_ERROR_NONE;
382         size_t idx = 0;
383         if ((pars == NULL) || (sscanf(pars, " %zu", &idx) < 1)) {
384                 _printf(CMD_COLOR_RED, "You have to specify identifier of the pool "
385                                 "to be activated after command name! Format: "
386                                 CMD_ACTIVATE_POOL " <id>\n");
387                 return FAIL;
388         }
389
390         if (idx > (MAX_POOL_CNT - 1)) {
391                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
392                                 MAX_POOL_CNT - 1);
393                 return FAIL;
394         }
395
396         _logger_log_info(CMD_ACTIVATE_POOL " command was called");
397         _logger_log_info("Activating the pool by %zu identifier...", idx);
398
399         if (pools[idx] == NULL)
400                 _logger_log_warn("Pool to be activated is NULL");
401
402         ret = sound_pool_activate(pools[idx]);
403
404         if (ret == SOUND_POOL_ERROR_NONE)
405                 _logger_log_info("sound_pool_set_state(pool, "
406                                 "SOUND_POOL_STATE_ACTIVE) returned %s value",
407                                 __stringify_sound_pool_error(ret));
408         else
409                 _logger_log_err("sound_pool_set_state(pool, "
410                                 "SOUND_POOL_STATE_ACTIVE) returned %s value",
411                                 __stringify_sound_pool_error(ret));
412
413         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
414 }
415
416 /* CMD_DEACTIVATE_POOL */
417 static int __proxy_sound_pool_deactivate(const char *pars)
418 {
419         size_t idx = 0;
420         if ((pars == NULL) || (sscanf(pars, " %zu", &idx) < 1)) {
421                 _printf(CMD_COLOR_RED, "You have to specify identifier of the pool "
422                                 "to be deactivated after command name! Format: "
423                                 CMD_DEACTIVATE_POOL " <id>\n");
424                 return FAIL;
425         }
426
427         if (idx > (MAX_POOL_CNT - 1)) {
428                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
429                                 MAX_POOL_CNT - 1);
430                 return FAIL;
431         }
432
433         _logger_log_info(CMD_DEACTIVATE_POOL " command was called");
434         _logger_log_info("Deactivating the pool by %zu identifier...", idx);
435
436         if (pools[idx] == NULL)
437                 _logger_log_warn("Pool to be deactivated is NULL");
438
439         int ret = sound_pool_deactivate(pools[idx]);
440
441         if (ret == SOUND_POOL_ERROR_NONE)
442                 _logger_log_info("sound_pool_set_state(pool, "
443                                 "SOUND_POOL_STATE_INACTIVE) returned %s value",
444                                 __stringify_sound_pool_error(ret));
445         else
446                 _logger_log_err("sound_pool_set_state(pool, "
447                                 "SOUND_POOL_STATE_INACTIVE) returned %s value",
448                                 __stringify_sound_pool_error(ret));
449
450         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
451 }
452
453 /* CMD_GET_POOL_STATE */
454 static int __proxy_sound_pool_get_state(const char *pars)
455 {
456         size_t idx = 0;
457         if ((pars == NULL) || (sscanf(pars, " %zu", &idx) < 1)) {
458                 _printf(CMD_COLOR_RED, "You have to specify identifier of the pool "
459                                 "to get state for, after command name! Format: "
460                                 CMD_GET_POOL_STATE " <id>\n");
461                 return FAIL;
462         }
463
464         if (idx > (MAX_POOL_CNT - 1)) {
465                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
466                                 MAX_POOL_CNT - 1);
467                 return FAIL;
468         }
469
470         _logger_log_info(CMD_GET_POOL_STATE " command was called");
471         _logger_log_info("Getting the pool state by %zu identifier...", idx);
472
473         if (pools[idx] == NULL)
474                 _logger_log_warn("Pool to get state for is NULL");
475
476         sound_pool_state_e state = SOUND_POOL_STATE_INACTIVE;
477         int ret = sound_pool_get_state(pools[idx], &state);
478
479         const char *str_state = (state == SOUND_POOL_STATE_ACTIVE ?
480                         "SOUND_POOL_STATE_ACTIVE" : "SOUND_POOL_STATE_INACTIVE");
481
482         if (ret == SOUND_POOL_ERROR_NONE)
483                 _logger_log_info("sound_pool_get_state(pool, state) returned %s value,"
484                                 " state is %s", __stringify_sound_pool_error(ret), str_state);
485         else
486                 _logger_log_err("sound_pool_get_state(pool, state) returned %s value,"
487                                 " state is %s", __stringify_sound_pool_error(ret), str_state);
488
489         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
490 }
491
492 /* CMD_SET_POOL_VOLUME */
493 static int __proxy_sound_pool_set_volume(const char *pars)
494 {
495         size_t idx = 0;
496         float volume = .0f;
497         if ((pars == NULL) || (sscanf(pars, " %zu %f", &idx, &volume) < 2)) {
498                 _printf(CMD_COLOR_RED, "You have to specify both identifier of the "
499                                 "pool and new volume float value to set volume for whole pool! "
500                                 "Format: " CMD_SET_POOL_VOLUME " <id> <volume>\n");
501                 return FAIL;
502         }
503
504         if (idx > (MAX_POOL_CNT - 1)) {
505                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
506                                 MAX_POOL_CNT - 1);
507                 return FAIL;
508         }
509
510         _logger_log_info(CMD_SET_POOL_VOLUME " command was called");
511         _logger_log_info("Set %f volume value for pool with %zu identifier...",
512                         volume, idx);
513
514         if (pools[idx] == NULL)
515                 _logger_log_warn("Pool to get state for is NULL");
516
517         if (volume < .0f || volume > 1.0f)
518                 _logger_log_warn("Volume is set as %f, not in [0, 1.0] range", volume);
519
520         int ret = sound_pool_set_volume(pools[idx], volume);
521
522         if (ret == SOUND_POOL_ERROR_NONE)
523                 _logger_log_info("sound_pool_set_global_volume(pool, %f) "
524                                 "returned %s value", volume, __stringify_sound_pool_error(ret));
525         else
526                 _logger_log_err("sound_pool_set_global_volume(pool, %f) "
527                                 "returned %s value", volume, __stringify_sound_pool_error(ret));
528
529         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
530 }
531
532 /* CMD_GET_POOL_VOLUME */
533 static int __proxy_sound_pool_get_volume(const char *pars)
534 {
535         size_t idx = 0;
536         if ((pars == NULL) || (sscanf(pars, " %zu", &idx) < 1)) {
537                 _printf(CMD_COLOR_RED, "You have to specify identifier of the pool "
538                                 "to get volume for, after command name! Format: "
539                                 CMD_GET_POOL_VOLUME " <id>\n");
540                 return FAIL;
541         }
542
543         if (idx > (MAX_POOL_CNT - 1)) {
544                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
545                                 MAX_POOL_CNT - 1);
546                 return FAIL;
547         }
548
549         _logger_log_info(CMD_GET_POOL_VOLUME " command was called");
550         _logger_log_info("Getting the pool global volume for pool with %zu "
551                         "identifier...", idx);
552
553         if (pools[idx] == NULL)
554                 _logger_log_warn("Pool to get state for is NULL");
555
556         float volume = .0f;
557         int ret = sound_pool_get_volume(pools[idx], &volume);
558
559         if (ret == SOUND_POOL_ERROR_NONE)
560                 _logger_log_info("sound_pool_get_global_volume(pool, volume) returned "
561                                 "%s value, volume is %f", __stringify_sound_pool_error(ret),
562                                 volume);
563         else
564                 _logger_log_err("sound_pool_get_global_volume(pool, volume) returned "
565                                 "%s value, volume is %f", __stringify_sound_pool_error(ret),
566                                 volume);
567
568         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
569 }
570
571 /* CMD_SET_POOL_CB_MSG */
572 static int __proxy_sound_pool_set_state_change_callback_message(const char *pars)
573 {
574         size_t idx = 0;
575
576         char msg[MAX_MSG_LEN] = { '\0' };
577
578         if ((pars == NULL) || (sscanf(pars, " %zu %"MAX_MSG_LEN_STR"[^ ]", &idx, msg) < 2)) {
579                 _printf(CMD_COLOR_RED, "You have to specify both identifier of the "
580                                 "pool and message to be shown each time when state of the pool "
581                                 " is changed! Message should be a single word. Format: "
582                                 CMD_SET_POOL_CB_MSG " <id> <message>\n");
583                 return FAIL;
584         }
585
586         if (idx > (MAX_POOL_CNT - 1)) {
587                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
588                                 MAX_POOL_CNT - 1);
589                 return FAIL;
590         }
591
592         _logger_log_info(CMD_SET_POOL_CB_MSG " command was called");
593         _logger_log_info("Set state changing callback (%s message) for pool with "
594                         "%zu identifier...", msg, idx);
595
596         if (pools[idx] == NULL)
597                 _logger_log_warn("Pool to set callback for is NULL");
598
599         if (messages[idx])
600                 free(messages[idx]);
601         messages[idx] = strndup(msg, MAX_MSG_LEN);
602
603         int ret = sound_pool_set_state_change_callback(pools[idx], __sp_cb_msg,
604                         messages[idx]);
605
606         if (ret == SOUND_POOL_ERROR_NONE)
607                 _logger_log_info("sound_pool_set_state_change_callback(pool, cb, "
608                                 "\"%s\") returned %s value", msg, __stringify_sound_pool_error(ret));
609         else
610                 _logger_log_err("sound_pool_set_state_change_callback(pool, cb, "
611                                 "\"%s\") returned %s value", msg, __stringify_sound_pool_error(ret));
612
613         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
614 }
615
616 /* CMD_SET_POOL_CB_SCRIPT */
617 static int __proxy_sound_pool_set_state_change_callback_script(const char *pars)
618 {
619         size_t idx = 0;
620
621         char scr[MAX_MSG_LEN] = { '\0' };
622
623         if ((pars == NULL) || (sscanf(pars, " %zu %"MAX_MSG_LEN_STR"[^ ]", &idx, scr) < 2)) {
624                 _printf(CMD_COLOR_RED, "You have to specify both identifier of the "
625                                 "pool and script file name to be executed each time when state "
626                                 "of the pool will be changed! Format: "
627                                 CMD_SET_POOL_CB_SCRIPT " <id> <script file>\n");
628                 return FAIL;
629         }
630
631         if (idx > (MAX_POOL_CNT - 1)) {
632                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
633                                 MAX_POOL_CNT - 1);
634                 return FAIL;
635         }
636
637         _logger_log_info(CMD_SET_POOL_CB_SCRIPT " command was called");
638         _logger_log_info("Set state changing callback (%s script) for pool with "
639                         "%zu identifier...", scr, idx);
640
641         if (pools[idx] == NULL)
642                 _logger_log_warn("Pool to set callback for is NULL");
643
644         if (scripts[idx])
645                 free(scripts[idx]);
646         scripts[idx] = strndup(scr, MAX_MSG_LEN);
647
648         int ret = sound_pool_set_state_change_callback(pools[idx], __sp_cb_scr,
649                         scripts[idx]);
650
651         if (ret == SOUND_POOL_ERROR_NONE)
652                 _logger_log_info("sound_pool_set_state_change_callback(pool, cb, "
653                                 "\"%s\") returned %s value", scr, __stringify_sound_pool_error(ret));
654         else
655                 _logger_log_err("sound_pool_set_state_change_callback(pool, cb, "
656                                 "\"%s\") returned %s value", scr, __stringify_sound_pool_error(ret));
657
658         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
659 }
660
661 /* CMD_UNSET_POOL_CB */
662 static int __proxy_sound_pool_unset_state_change_callback(const char *pars)
663 {
664         size_t idx = 0;
665         if ((pars == NULL) || (sscanf(pars, " %zu", &idx) < 1)) {
666                 _printf(CMD_COLOR_RED, "You have to specify identifier of the pool! "
667                                 "Format: " CMD_UNSET_POOL_CB " <id>\n");
668                 return FAIL;
669         }
670
671         if (idx > (MAX_POOL_CNT - 1)) {
672                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
673                                 MAX_POOL_CNT - 1);
674                 return FAIL;
675         }
676
677         _logger_log_info(CMD_UNSET_POOL_CB " command was called");
678         _logger_log_info("Unset state changing callback for pool with "
679                         "%zu identifier...", idx);
680
681         if (pools[idx] == NULL)
682                 _logger_log_warn("Pool to unset callback for is NULL");
683
684         int ret = sound_pool_unset_state_change_callback(pools[idx]);
685
686         if (messages[idx] != NULL)
687                 free(messages[idx]);
688         messages[idx] = NULL;
689
690         if (scripts[idx] != NULL)
691                 free(scripts[idx]);
692         scripts[idx] = NULL;
693
694         if (ret == SOUND_POOL_ERROR_NONE)
695                 _logger_log_info("sound_pool_unset_state_change_callback(pool) "
696                                 "returned %s value", __stringify_sound_pool_error(ret));
697         else
698                 _logger_log_err("sound_pool_unset_state_change_callback(pool) "
699                                 "returned %s value", __stringify_sound_pool_error(ret));
700
701         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
702 }
703
704 /* CMD_LIST_POOL */
705 static int __proxy_sound_pool_list()
706 {
707         _logger_log_info("Getting the pool identifiers...");
708
709         const size_t buffer_size = 1024;
710         char buffer[buffer_size];
711         buffer[0] = '\0';
712
713         size_t idx = 0;
714         size_t len = 0;
715         while (idx < MAX_POOL_CNT) {
716                 len = strnlen(buffer, buffer_size);
717                 if (pools[idx++] != NULL) {
718                         size_t add_len = 1;
719                         size_t id = idx - 1;
720                         do
721                                 add_len++;
722                         while ((id = id / 10) > 0);
723                         id = idx - 1;
724                         if (len + add_len + 1 > buffer_size)
725                                 break;
726                         snprintf(buffer + len, buffer_size, "%zu ", id);
727                 }
728         }
729
730         _printf(CMD_COLOR_GREEN, "Pools identifiers: %s\n", buffer);
731         _logger_log_info("Pools identifiers: %s", buffer);
732
733         _logger_log_info("Pool identifiers were retrieved...");
734
735         return OK;
736 }
737
738 /* CMD_LOAD_SOURCE */
739 static int __proxy_sound_pool_load_source_from_file(const char *pars)
740 {
741         size_t idx = 0;
742
743         char fname[MAX_PATH_LEN] = {'\0'};
744         char tag[MAX_PATH_LEN] = {'\0'};
745
746         if ((pars == NULL) || sscanf(pars, " %zu %"MAX_PATH_LEN_STR"[^ ] "
747                         "%"MAX_PATH_LEN_STR"[^ ]", &idx, fname, tag) < 2) {
748                 _printf(CMD_COLOR_RED, "You have to specify at least pool identifier and "
749                                 "file name to be loaded! Format: " CMD_LOAD_SOURCE " <pool id> "
750                                 "<file name> <source tag>\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         /* If tag wasn't specified by the user, we will use file path as a tag */
764         if (tag[0] == '\0')
765                 strncpy(tag, fname, MAX_PATH_LEN);
766
767         _logger_log_info(CMD_LOAD_SOURCE " command was called");
768         _logger_log_info("Loading source to the pool with %zu identifier from %s file. "
769                         "Tag '%s' will be assigned for the loaded source...", idx, fname, tag);
770
771         int ret = sound_pool_load_source_from_file(pools[idx], fname, tag);
772
773         if (ret == SOUND_POOL_ERROR_NONE)
774                 _logger_log_info("sound_pool_load_source_from_file(pool, \"%s\", "
775                                 "\"%s\") returned %s value", fname, tag,
776                                 __stringify_sound_pool_error(ret));
777         else
778                 _logger_log_err("sound_pool_load_source_from_file(pool, \"%s\", "
779                                 "\"%s\") returned %s value", fname, tag,
780                                 __stringify_sound_pool_error(ret));
781
782         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
783 }
784
785 /* CMD_UNLOAD_SOURCE */
786 static int __proxy_sound_pool_unload_source(const char *pars)
787 {
788         size_t idx = 0;
789
790         char tag[MAX_PATH_LEN] = {'\0'};
791
792         if ((pars == NULL) || sscanf(pars, " %zu %"MAX_PATH_LEN_STR"[^ ]", &idx, tag) < 2) {
793                 _printf(CMD_COLOR_RED, "You have to specify both pool identifier and "
794                                 "source tag to be unloaded! Format: " CMD_UNLOAD_SOURCE
795                                 " <pool id> <source tag>\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_UNLOAD_SOURCE " command was called");
809         _logger_log_info("Unloading source by '%s' tag from the pool with %zu "
810                         "identifier...", tag, idx);
811
812         int ret = sound_pool_unload_source(pools[idx], tag);
813
814         if (ret == SOUND_POOL_ERROR_NONE)
815                 _logger_log_info("sound_pool_unload_source(pool, \"%s\") returned "
816                                 "%s value", tag, __stringify_sound_pool_error(ret));
817         else
818                 _logger_log_err("sound_pool_unload_source(pool, \"%s\") returned "
819                                 "%s value", tag, __stringify_sound_pool_error(ret));
820
821         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
822 }
823
824 /* CMD_PLAY_STREAM */
825 static int __proxy_sound_pool_play_stream(const char *pars)
826 {
827         size_t idx = 0;
828         int loop = 0;
829         float volume = 1.0f;
830         unsigned rank = DEFAULT_STREAM_PRIORITY_RANK;
831     sound_pool_stream_priority_policy_e priority_policy = SOUND_POOL_STREAM_PRIORITY_POLICY_MUTE;
832
833         char tag[MAX_PATH_LEN] = {'\0'};
834
835         if ((pars == NULL) || sscanf(pars, " %zu %"MAX_PATH_LEN_STR"[^ ] %i %f %u %u",
836                                                                 &idx, tag, &loop, &volume, &rank, &priority_policy) < 2) {
837                 _printf(CMD_COLOR_RED, "You have to specify at least pool identifier and "
838                                 "source tag to be played in stream! Format: " CMD_PLAY_STREAM
839                                 " <pool id> <source tag> <loop> <volume> <priority rank> <priority_policy>... "
840                                 "0 'priority rank' value corresponds to the lowest priority.\n");
841                 return FAIL;
842         }
843
844         if (idx > (MAX_POOL_CNT - 1)) {
845                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
846                                 MAX_POOL_CNT - 1);
847                 return FAIL;
848         }
849
850         if (pools[idx] == NULL)
851                 _logger_log_warn("Pool with specified identifier is NULL");
852
853         _logger_log_info(CMD_PLAY_STREAM " command was called");
854         _logger_log_info("Playing stream based on source with '%s' tag from the pool "
855                         "with %zu identifier...", tag, idx);
856
857         unsigned stream_idx = 0;
858         int ret = sound_pool_stream_play(pools[idx], tag, loop, volume, rank, priority_policy, __s_cb_msg,
859                         NULL, &stream_idx);
860
861         if (ret == SOUND_POOL_ERROR_NONE) {
862                 _logger_log_info("sound_pool_play_stream(pool, \"%s\", %i, %f, %u,"
863                                 " %u, %p, NULL, &stream_idx) returned %s value. "
864                                 "Generated identifier is %i", tag, loop, volume, rank, priority_policy, __s_cb_msg,
865                                 __stringify_sound_pool_error(ret), stream_idx);
866                 _printf(CMD_COLOR_GREEN, "Generated stream identifier is %i\n", stream_idx);
867         } else {
868                 _logger_log_err("sound_pool_play_stream(pool, \"%s\", %i, %f, %u,"
869                                 " %u, %p, NULL, &stream_idx) returned %s value",
870                                 tag, loop, volume, rank, priority_policy, __s_cb_msg, __stringify_sound_pool_error(ret));
871         }
872
873         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
874 }
875
876 /* CMD_PAUSE_STREAM */
877 static int __proxy_sound_pool_pause_stream(const char *pars)
878 {
879         size_t idx = 0;
880         size_t stream_idx = 0;
881
882         if ((pars == NULL) || (sscanf(pars, " %zu %i", &idx, &stream_idx) < 2)) {
883                 _printf(CMD_COLOR_RED, "You have to specify both pool identifier and "
884                                 "stream to be paused identifier! Format: " CMD_PAUSE_STREAM
885                                 " <pool id> <stream id>\n");
886                 return FAIL;
887         }
888
889         if (idx > (MAX_POOL_CNT - 1)) {
890                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
891                                 MAX_POOL_CNT - 1);
892                 return FAIL;
893         }
894
895         if (pools[idx] == NULL)
896                 _logger_log_warn("Pool with specified identifier is NULL");
897
898         _logger_log_info(CMD_PAUSE_STREAM " command was called");
899
900         int ret = sound_pool_stream_pause(pools[idx], stream_idx);
901
902         if (ret == SOUND_POOL_ERROR_NONE)
903                 _logger_log_info("sound_pool_pause_stream(pool, %i) returned %s "
904                                 "value", stream_idx, __stringify_sound_pool_error(ret));
905         else
906                 _logger_log_err("sound_pool_pause_stream(pool, %i) returned %s "
907                                 "value", stream_idx, __stringify_sound_pool_error(ret));
908
909         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
910 }
911
912 /* CMD_RESUME_STREAM */
913 static int __proxy_sound_pool_resume_stream(const char *pars)
914 {
915         size_t idx = 0;
916         size_t stream_idx = 0;
917
918         if ((pars == NULL) || (sscanf(pars, " %zu %i", &idx, &stream_idx) < 2)) {
919                 _printf(CMD_COLOR_RED, "You have to specify both pool identifier and "
920                                 "stream to be resumed identifier! Format: " CMD_RESUME_STREAM
921                                 " <pool id> <stream id>\n");
922                 return FAIL;
923         }
924
925         if (idx > (MAX_POOL_CNT - 1)) {
926                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
927                                 MAX_POOL_CNT - 1);
928                 return FAIL;
929         }
930
931         if (pools[idx] == NULL)
932                 _logger_log_warn("Pool with specified identifier is NULL");
933
934         _logger_log_info(CMD_RESUME_STREAM " command was called");
935
936         int ret = sound_pool_stream_resume(pools[idx], stream_idx);
937
938         if (ret == SOUND_POOL_ERROR_NONE)
939                 _logger_log_info("sound_pool_resume_stream(pool, %i) returned %s "
940                                 "value", stream_idx, __stringify_sound_pool_error(ret));
941         else
942                 _logger_log_err("sound_pool_resume_stream(pool, %i) returned %s "
943                                 "value", stream_idx, __stringify_sound_pool_error(ret));
944
945         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
946 }
947
948 /* CMD_STOP_STREAM */
949 static int __proxy_sound_pool_stop_stream(const char *pars)
950 {
951         size_t idx = 0;
952         size_t stream_idx = 0;
953
954         if ((pars == NULL) || (sscanf(pars, " %zu %zu", &idx, &stream_idx) < 2)) {
955                 _printf(CMD_COLOR_RED, "You have to specify both pool identifier and "
956                                 "stream to be stopped identifier! Format: " CMD_STOP_STREAM
957                                 " <pool id> <stream id>\n");
958                 return FAIL;
959         }
960
961         if (idx > (MAX_POOL_CNT - 1)) {
962                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
963                                 MAX_POOL_CNT - 1);
964                 return FAIL;
965         }
966
967         if (pools[idx] == NULL)
968                 _logger_log_warn("Pool with specified identifier is NULL");
969
970         _logger_log_info(CMD_STOP_STREAM " command was called");
971
972         int ret = sound_pool_stream_stop(pools[idx], stream_idx);
973
974         if (ret == SOUND_POOL_ERROR_NONE)
975                 _logger_log_info("sound_pool_stop_stream(pool, %i) returned %s "
976                                 "value", stream_idx, __stringify_sound_pool_error(ret));
977         else
978                 _logger_log_err("sound_pool_stop_stream(pool, %i) returned %s "
979                                 "value", stream_idx, __stringify_sound_pool_error(ret));
980
981         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
982 }
983
984 /* CMD_SET_STREAM_VOLUME */
985 static int __proxy_sound_pool_stream_set_volume(const char *pars)
986 {
987         size_t idx = 0;
988         size_t stream_idx = 0;
989         float volume_val = 1.0f;
990
991         if ((pars == NULL)
992                         || (sscanf(pars, " %zu %zu %f", &idx, &stream_idx, &volume_val) < 3)) {
993                 _printf(CMD_COLOR_RED, "You have to specify all following parameters: "
994                                 "pool identifier, stream identifier! Format: "
995                                 CMD_SET_STREAM_VOLUME " <pool id> <stream id> <volume>\n");
996                 return FAIL;
997         }
998
999         if (idx > (MAX_POOL_CNT - 1)) {
1000                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
1001                                 MAX_POOL_CNT - 1);
1002                 return FAIL;
1003         }
1004
1005         if (pools[idx] == NULL)
1006                 _logger_log_warn("Pool with specified identifier is NULL");
1007
1008         if (volume_val < .0f || volume_val > 1.0f)
1009                 _logger_log_warn("Volume has to be specified in 0.0~1.0 range");
1010
1011         _logger_log_info(CMD_SET_STREAM_VOLUME " command was called");
1012
1013         int ret = sound_pool_stream_set_volume(pools[idx], stream_idx, volume_val);
1014
1015         if (ret == SOUND_POOL_ERROR_NONE)
1016                 _logger_log_info("sound_pool_stream_set_volume(pool, %i, %f) "
1017                                 "returned %s value", stream_idx, volume_val,
1018                                 __stringify_sound_pool_error(ret));
1019         else
1020                 _logger_log_err("sound_pool_stream_set_volume(pool, %i, %f) "
1021                                 "returned %s value", stream_idx, volume_val,
1022                                 __stringify_sound_pool_error(ret));
1023
1024         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
1025 }
1026
1027 /* CMD_GET_STREAM_VOLUME */
1028 static int __proxy_sound_pool_stream_get_volume(const char *pars)
1029 {
1030         size_t idx = 0;
1031         size_t stream_idx = 0;
1032         if ((pars == NULL) || (sscanf(pars, " %zu %zu", &idx, &stream_idx) < 2)) {
1033                 _printf(CMD_COLOR_RED, "You have to specify both pool and stream "
1034                                 "identifiers after command name! Format: "
1035                                 CMD_GET_STREAM_VOLUME " <pool id> <stream id>\n");
1036                 return FAIL;
1037         }
1038
1039         if (idx > (MAX_POOL_CNT - 1)) {
1040                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
1041                                 MAX_POOL_CNT - 1);
1042                 return FAIL;
1043         }
1044
1045         _logger_log_info(CMD_GET_STREAM_VOLUME " command was called");
1046         _logger_log_info("Getting the %zu stream from %zu pool volume value...",
1047                         stream_idx, idx);
1048
1049         if (pools[idx] == NULL)
1050                 _logger_log_warn("Pool to get state for is NULL");
1051
1052         float volume = .0f;
1053         int ret = sound_pool_stream_get_volume(pools[idx], stream_idx, &volume);
1054
1055         if (ret == SOUND_POOL_ERROR_NONE)
1056                 _logger_log_info("sound_pool_stream_get_volume(pool, %zu, volume) "
1057                                 "returned %s value, volume is %f", stream_idx,
1058                                 __stringify_sound_pool_error(ret), volume);
1059         else
1060                 _logger_log_err("sound_pool_stream_get_volume(pool, %zu, volume) "
1061                                 "returned %s value, volume is %f", stream_idx,
1062                                 __stringify_sound_pool_error(ret), volume);
1063
1064         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
1065 }
1066
1067 /* CMD_SET_STREAM_LOOP */
1068 static int __proxy_sound_pool_stream_set_loop(const char *pars)
1069 {
1070         size_t idx = 0;
1071         size_t stream_idx = 0;
1072         int loop_val = 1;
1073
1074         if ((pars == NULL)
1075                         || (sscanf(pars, " %zu %zu %i", &idx, &stream_idx, &loop_val) < 3)) {
1076                 _printf(CMD_COLOR_RED, "You have to specify all following parameters: "
1077                                 "pool identifier, stream identifier, and loop number! Format: "
1078                                 CMD_SET_STREAM_LOOP " <pool id> <stream id> <loop num>\n");
1079                 return FAIL;
1080         }
1081
1082         if (idx > (MAX_POOL_CNT - 1)) {
1083                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
1084                                 MAX_POOL_CNT - 1);
1085                 return FAIL;
1086         }
1087
1088         if (pools[idx] == NULL)
1089                 _logger_log_warn("Pool with specified identifier is NULL");
1090
1091         if (loop_val < 0)
1092                 _logger_log_warn("Loop number should to be greater than 0, but it's"
1093                                 "value is %i", loop_val);
1094
1095         _logger_log_info(CMD_SET_STREAM_LOOP " command was called");
1096
1097         int ret = sound_pool_stream_set_loop(pools[idx], stream_idx, loop_val);
1098
1099         if (ret == SOUND_POOL_ERROR_NONE)
1100                 _logger_log_info("sound_pool_stream_set_loop(pool, %zu, %i) "
1101                                 "returned %s value", stream_idx, loop_val,
1102                                 __stringify_sound_pool_error(ret));
1103         else
1104                 _logger_log_err("sound_pool_stream_set_loop(pool, %zu, %i) "
1105                                 "returned %s value", stream_idx, loop_val,
1106                                 __stringify_sound_pool_error(ret));
1107
1108         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
1109 }
1110
1111 /* CMD_GET_STREAM_LOOP */
1112 static int __proxy_sound_pool_stream_get_loop(const char *pars)
1113 {
1114         size_t idx = 0;
1115         size_t stream_idx = 0;
1116         if ((pars == NULL) || (sscanf(pars, " %zu %zu", &idx, &stream_idx) < 2)) {
1117                 _printf(CMD_COLOR_RED, "You have to specify both pool and stream "
1118                                 "identifiers after command name! Format: "
1119                                 CMD_GET_STREAM_LOOP " <pool id> <stream id>\n");
1120                 return FAIL;
1121         }
1122
1123         if (idx > (MAX_POOL_CNT - 1)) {
1124                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
1125                                 MAX_POOL_CNT - 1);
1126                 return FAIL;
1127         }
1128
1129         _logger_log_info(CMD_GET_STREAM_LOOP " command was called");
1130         _logger_log_info("Getting the stream state by %zu identifier in %zu "
1131                         "pool...", stream_idx, idx);
1132
1133         if (pools[idx] == NULL)
1134                 _logger_log_warn("Pool where stream should be located is NULL");
1135
1136         unsigned loop = 0;
1137         int ret = sound_pool_stream_get_loop(pools[idx], stream_idx, &loop);
1138
1139         if (ret == SOUND_POOL_ERROR_NONE)
1140                 _logger_log_info("sound_pool_stream_get_loop(pool, %zu, loop) "
1141                                 "returned %s value, loop value is %i", stream_idx,
1142                                 __stringify_sound_pool_error(ret), loop);
1143         else
1144                 _logger_log_err("sound_pool_stream_get_loop(pool, %zu, loop) "
1145                                 "returned %s value, loop value is %i", stream_idx,
1146                                 __stringify_sound_pool_error(ret), loop);
1147
1148         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
1149 }
1150
1151 /* CMD_SET_STREAM_PRIORITY */
1152 static int __proxy_sound_pool_stream_set_priority(const char *pars)
1153 {
1154         size_t idx = 0;
1155         size_t stream_idx = 0;
1156         unsigned rank = 0;
1157
1158         if ((pars == NULL)
1159                         || (sscanf(pars, " %zu %zu %u", &idx, &stream_idx, &rank) < 3)) {
1160                 _printf(CMD_COLOR_RED, "You have to specify all following parameters: "
1161                                 "pool identifier, stream identifier, and priority rank! Format: "
1162                                 CMD_SET_STREAM_PRIORITY " <pool id> <stream id> <rank>\n");
1163                 return FAIL;
1164         }
1165
1166         if (idx > (MAX_POOL_CNT - 1)) {
1167                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
1168                                 MAX_POOL_CNT - 1);
1169                 return FAIL;
1170         }
1171
1172         if (pools[idx] == NULL)
1173                 _logger_log_warn("Pool with specified identifier is NULL");
1174
1175         _logger_log_info(CMD_SET_STREAM_PRIORITY " command was called");
1176
1177         int ret = sound_pool_stream_set_priority(pools[idx], stream_idx, rank);
1178
1179         if (ret == SOUND_POOL_ERROR_NONE)
1180                 _logger_log_info("sound_pool_stream_set_priority(pool, %zu, %u) "
1181                                 "returned %s value", stream_idx, rank,
1182                                 __stringify_sound_pool_error(ret));
1183         else
1184                 _logger_log_err("sound_pool_stream_set_priority(pool, %zu, %u) "
1185                                 "returned %s value", stream_idx, rank,
1186                                 __stringify_sound_pool_error(ret));
1187
1188         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
1189 }
1190
1191 /* CMD_GET_STREAM_PRIORITY */
1192 static int __proxy_sound_pool_stream_get_priority(const char *pars)
1193 {
1194         size_t idx = 0;
1195         size_t stream_idx = 0;
1196         if ((pars == NULL) || (sscanf(pars, " %zu %zu", &idx, &stream_idx) < 2)) {
1197                 _printf(CMD_COLOR_RED, "You have to specify both pool and stream "
1198                                 "identifiers after command name! Format: "
1199                                 CMD_GET_STREAM_PRIORITY " <pool id> <stream id>\n");
1200                 return FAIL;
1201         }
1202
1203         if (idx > (MAX_POOL_CNT - 1)) {
1204                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
1205                                 MAX_POOL_CNT - 1);
1206                 return FAIL;
1207         }
1208
1209         _logger_log_info(CMD_GET_STREAM_PRIORITY " command was called");
1210         _logger_log_info("Getting the stream priority rank by %zu identifier in "
1211                         "%zu pool...", stream_idx, idx);
1212
1213         if (pools[idx] == NULL)
1214                 _logger_log_warn("Pool where stream should be located is NULL");
1215
1216         unsigned rank = 0;
1217         int ret = sound_pool_stream_get_priority(pools[idx], stream_idx, &rank);
1218
1219         if (ret == SOUND_POOL_ERROR_NONE)
1220                 _logger_log_info("sound_pool_stream_get_priority(pool, %u, rank) "
1221                                 "returned %s value, rank value is %u", stream_idx,
1222                                 __stringify_sound_pool_error(ret), rank);
1223         else
1224                 _logger_log_err("sound_pool_stream_get_priority(pool, %u, rank) "
1225                                 "returned %s value, rank value is %u", stream_idx,
1226                                 __stringify_sound_pool_error(ret), rank);
1227
1228         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
1229 }
1230
1231 /* CMD_GET_STREAM_STATE */
1232 static int __proxy_sound_pool_get_stream_state(const char *pars)
1233 {
1234         size_t idx = 0;
1235         size_t stream_idx = 0;
1236         if ((pars == NULL) || (sscanf(pars, " %zu %zu", &idx, &stream_idx) < 2)) {
1237                 _printf(CMD_COLOR_RED, "You have to specify both pool and stream "
1238                                 "identifiers after command name! Format: "
1239                                 CMD_GET_STREAM_STATE " <pool id> <stream id>\n");
1240                 return FAIL;
1241         }
1242
1243         if (idx > (MAX_POOL_CNT - 1)) {
1244                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
1245                                 MAX_POOL_CNT - 1);
1246                 return FAIL;
1247         }
1248
1249         _logger_log_info(CMD_GET_STREAM_STATE " command was called");
1250         _logger_log_info("Getting the stream state by %zu identifier in %zu "
1251                         "pool...", stream_idx, idx);
1252
1253         if (pools[idx] == NULL)
1254                 _logger_log_warn("Pool where stream should be located is NULL");
1255
1256         sound_pool_stream_state_e state = SOUND_POOL_STREAM_STATE_NONE;
1257         int ret = sound_pool_stream_get_state(pools[idx], stream_idx,  &state);
1258
1259         if (ret == SOUND_POOL_ERROR_NONE)
1260                 _logger_log_info("sound_pool_get_stream_state(pool, %zu, state) "
1261                                 "returned %s value, state is %s", stream_idx,
1262                                 __stringify_sound_pool_error(ret),
1263                                 __stringify_stream_state(state));
1264         else
1265                 _logger_log_err("sound_pool_get_stream_state(pool, %zu, state) "
1266                                 "returned %s value, state is %s", stream_idx,
1267                                 __stringify_sound_pool_error(ret),
1268                                 __stringify_stream_state(state));
1269
1270         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
1271 }
1272
1273 /* CMD_SET_STREAM_CB_MSG */
1274 static int __proxy_sound_pool_set_stream_state_change_callback_message(const char *pars)
1275 {
1276         size_t idx = 0;
1277         size_t stream_idx = 0;
1278
1279         char msg[MAX_MSG_LEN] = { '\0' };
1280
1281         if ((pars == NULL) || sscanf(pars, " %zu %zu %"MAX_MSG_LEN_STR"[^ ]",
1282                                                                 &idx, &stream_idx, msg) < 3) {
1283                 _printf(CMD_COLOR_RED, "You have to specify both identifier of the "
1284                                 "pool and stream, plus message to be shown each time when "
1285                                 "state of the stream is changed! Message should be a single "
1286                                 "word. Format: "
1287                                 CMD_SET_STREAM_CB_MSG " <pool id> <stream id> <message>\n");
1288                 return FAIL;
1289         }
1290
1291         if (idx > (MAX_POOL_CNT - 1)) {
1292                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
1293                                 MAX_POOL_CNT - 1);
1294                 return FAIL;
1295         }
1296
1297         if (stream_idx > (MAX_STREAM_CNT - 1)) {
1298                 _printf(CMD_COLOR_RED, "Stream identifier value can't be greater than %d\n",
1299                                 MAX_STREAM_CNT - 1);
1300                 return FAIL;
1301         }
1302
1303         _logger_log_info(CMD_SET_STREAM_CB_MSG " command was called");
1304         _logger_log_info("Set state changing callback (%s message) for stream %zu "
1305                         "in pool with %zu identifier...", msg, stream_idx, idx);
1306
1307         if (pools[idx] == NULL)
1308                 _logger_log_warn("Pool with stream to set callback for is NULL");
1309
1310         if (stream_messages[idx][stream_idx])
1311                 free(stream_messages[idx][stream_idx]);
1312         stream_messages[idx][stream_idx] = strndup(msg, MAX_MSG_LEN);
1313
1314         int ret = sound_pool_stream_set_state_change_callback(pools[idx], stream_idx,
1315                         __s_cb_msg, stream_messages[idx][stream_idx]);
1316
1317         if (ret == SOUND_POOL_ERROR_NONE)
1318                 _logger_log_info("sound_pool_set_stream_state_change_callback(pool, "
1319                                 "%zu, cb, \"%s\") returned %s value", stream_idx, msg,
1320                                 __stringify_sound_pool_error(ret));
1321         else
1322                 _logger_log_err("sound_pool_set_stream_state_change_callback(pool, "
1323                                 "%zu, cb, \"%s\") returned %s value", stream_idx, msg,
1324                                 __stringify_sound_pool_error(ret));
1325
1326         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
1327 }
1328
1329 /* CMD_SET_STREAM_CB_SCRIPT */
1330 static int __proxy_sound_pool_set_stream_state_change_callback_script(const char *pars)
1331 {
1332         size_t idx = 0;
1333         size_t stream_idx = 0;
1334
1335         char scr[MAX_MSG_LEN] = { '\0' };
1336
1337         if ((pars == NULL) || sscanf(pars, " %zu %zu %"MAX_MSG_LEN_STR"[^ ]",
1338                                                                 &idx, &stream_idx, scr) < 3) {
1339                 _printf(CMD_COLOR_RED, "You have to specify both identifier of the "
1340                                 "pool and stream, plus file with script to be executed each "
1341                                 "time when state of the stream is changed! Message should be a "
1342                                 "single word. Format: " CMD_SET_STREAM_CB_SCRIPT
1343                                 " <pool id> <stream id> <script file>\n");
1344                 return FAIL;
1345         }
1346
1347         if (idx > (MAX_POOL_CNT - 1)) {
1348                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
1349                                 MAX_POOL_CNT - 1);
1350                 return FAIL;
1351         }
1352
1353         if (stream_idx > (MAX_STREAM_CNT - 1)) {
1354                 _printf(CMD_COLOR_RED, "Stream identifier value can't be greater than %d\n",
1355                                 MAX_STREAM_CNT - 1);
1356                 return FAIL;
1357         }
1358
1359         _logger_log_info(CMD_SET_STREAM_CB_SCRIPT " command was called");
1360         _logger_log_info("Set state changing callback (%s script) for stream %zu "
1361                         "in pool with %zu identifier...", scr, stream_idx, idx);
1362
1363         if (pools[idx] == NULL)
1364                 _logger_log_warn("Pool with stream to set callback for is NULL");
1365
1366         if (stream_scripts[idx][stream_idx])
1367                 free(stream_scripts[idx][stream_idx]);
1368         stream_scripts[idx][stream_idx] = strndup(scr, MAX_MSG_LEN);
1369
1370         int ret = sound_pool_stream_set_state_change_callback(pools[idx], stream_idx,
1371                         __s_cb_scr, stream_scripts[idx][stream_idx]);
1372
1373         if (ret == SOUND_POOL_ERROR_NONE)
1374                 _logger_log_info("sound_pool_set_stream_state_change_callback(pool, "
1375                                 "%zu, cb, \"%s\") returned %s value", stream_idx, scr,
1376                                 __stringify_sound_pool_error(ret));
1377         else
1378                 _logger_log_err("sound_pool_set_stream_state_change_callback(pool, "
1379                                 "%zu, cb, \"%s\") returned %s value", stream_idx, scr,
1380                                 __stringify_sound_pool_error(ret));
1381
1382         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
1383 }
1384
1385 /* CMD_UNSET_STREAM_CB */
1386 static int __proxy_sound_pool_unset_stream_state_change_callback(const char *pars)
1387 {
1388         size_t idx = 0;
1389         size_t stream_idx = 0;
1390         if ((pars == NULL) || (sscanf(pars, " %zu %zu", &idx, &stream_idx) < 2)) {
1391                 _printf(CMD_COLOR_RED, "You have to specify both identifier of the "
1392                                 " pool and stream! Format: " CMD_UNSET_STREAM_CB
1393                                 " <pool id> <stream id>\n");
1394                 return FAIL;
1395         }
1396
1397         if (idx > (MAX_POOL_CNT - 1)) {
1398                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
1399                                 MAX_POOL_CNT - 1);
1400                 return FAIL;
1401         }
1402
1403         _logger_log_info(CMD_UNSET_STREAM_CB " command was called");
1404         _logger_log_info("Unset state changing callback for the stream %zu in pool "
1405                         "with %zu identifier...", stream_idx, idx);
1406
1407         if (pools[idx] == NULL)
1408                 _logger_log_warn("Pool to unset callback for is NULL");
1409
1410         int ret = sound_pool_stream_unset_state_change_callback(pools[idx], stream_idx);
1411
1412         if (stream_idx > (MAX_STREAM_CNT - 1)) {
1413                 _printf(CMD_COLOR_RED, "Stream identifier value can't be greater than %d\n",
1414                                 MAX_STREAM_CNT - 1);
1415                 return FAIL;
1416         }
1417
1418         if (stream_messages[idx][stream_idx] != NULL)
1419                 free(stream_messages[idx][stream_idx]);
1420         stream_messages[idx][stream_idx] = NULL;
1421
1422         if (stream_scripts[idx][stream_idx] != NULL)
1423                 free(stream_scripts[idx][stream_idx]);
1424         stream_scripts[idx][stream_idx] = NULL;
1425
1426         if (ret == SOUND_POOL_ERROR_NONE)
1427                 _logger_log_info("sound_pool_unset_stream_state_change_callback(pool, "
1428                                 "%zu) returned %s value", stream_idx,
1429                                 __stringify_sound_pool_error(ret));
1430         else
1431                 _logger_log_info("sound_pool_unset_stream_state_change_callback(pool, "
1432                                 "%zu) returned %s value", stream_idx,
1433                                 __stringify_sound_pool_error(ret));
1434
1435         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
1436 }
1437
1438 /* CMD_SLEEP */
1439 static int __proxy_sleep(const char *pars)
1440 {
1441         int ret = SOUND_POOL_ERROR_NONE;
1442
1443         useconds_t stime = 0;
1444
1445         if ((pars == NULL) || (sscanf(pars, " %u", &stime) < 1)) {
1446                 _printf(CMD_COLOR_RED, "You have to specify number of milliseconds "
1447                                 "for the pause duration! Format: " CMD_SLEEP " <millisecs>\n");
1448                 return FAIL;
1449         }
1450
1451         _logger_log_info(CMD_SLEEP " command was called");
1452         _logger_log_info("Start main thread sleep for %u milliseconds...", stime);
1453         stime *= MICROSECS_PER_MILLISEC;
1454         usleep(stime);
1455         _logger_log_info("Main thread sleep has been finished...", stime);
1456
1457         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
1458 }
1459
1460 /* CMD_EXECUTE_SCRIPT */
1461 static int __proxy_sound_pool_execute_script(const char *pars)
1462 {
1463         char script_file[MAX_PATH_LEN] = {'\0'};
1464
1465         if ((pars == NULL) || (sscanf(pars, " %"MAX_PATH_LEN_STR"[^ ]", script_file) < 1)) {
1466                 _printf(CMD_COLOR_RED, "You have to specify script file name to be "
1467                                 "executed after command name! Format: " CMD_EXECUTE_SCRIPT " "
1468                                 "<script file>\n");
1469                 return FAIL;
1470         }
1471
1472         _logger_log_info(CMD_EXECUTE_SCRIPT " command was called");
1473         _logger_log_info("Loading script from file...");
1474         FILE *fd = fopen(script_file, "r");
1475
1476         if (fd) {
1477                 _logger_log_info("File has been loaded...");
1478                 _logger_log_info("Reading lines...");
1479                 size_t line_len = 0;
1480                 char *line = NULL;
1481                 while ((line_len = getline(&line, &line_len, fd)) != -1) {
1482                         line[strnlen(line, MAX_COMMAND_LINE_LEN) - 1] = '\0';
1483                         _logger_log_info("Executing line: %s", line);
1484                         if (_exec_cmd(line) != OK)
1485                                 _logger_log_warn("Unknown or unsupported command! "
1486                                                 "Line was skipped.");
1487                 }
1488                 _logger_log_info("Lines were read...");
1489         } else {
1490                 _logger_log_err("File wasn't loaded...");
1491                 return FAIL;
1492         }
1493
1494         _logger_log_info("Close file...");
1495
1496         if (fd)
1497                 fclose(fd);
1498
1499         return OK;
1500 }
1501
1502 /* Number of parameters supported by each command */
1503 static int cmd_pars[MAX_COMMAND_LINE_LEN] = { /* CMD_EXIT */ 0,
1504                 /* CMD_HELP */ 0, /* CMD_CREATE_POOL */ 0, /* CMD_DESTROY_POOL */ 1,
1505                 /* CMD_ACTIVATE_POOL */ 1, /* CMD_DEACTIVATE_POOL */ 1,
1506                 /* CMD_GET_POOL_STATE */ 1, /* CMD_SET_POOL_VOLUME */ 2,
1507                 /* CMD_GET_POOL_VOLUME */ 2, /* CMD_SET_POOL_CB_MSG */ 2,
1508                 /* CMD_SET_POOL_CB_SCRIPT */ 2, /* CMD_UNSET_POOL_CB */ 1,
1509                 /* CMD_LIST_POOL */ 0, /* CMD_LOAD_SOURCE */ 3,
1510                 /* CMD_LOAD_MEDIA_PACKAGE */ 3, /* CMD_UNLOAD_SOURCE */ 2,
1511                 /* CMD_PLAY_STREAM */ 5, /* CMD_STOP_STREAM */ 2,
1512                 /* CMD_PAUSE_STREAM */ 2, /* CMD_RESUME_STREAM */ 2,
1513                 /* CMD_SET_STREAM_VOLUME */ 3, /* CMD_GET_STREAM_VOLUME */ 2,
1514                 /* CMD_SET_STREAM_LOOP */ 3, /* CMD_GET_STREAM_LOOP */ 2,
1515                 /* CMD_SET_STREAM_PRIORITY */ 3, /* CMD_GET_STREAM_PRIORITY */ 2,
1516                 /* CMD_GET_STREAM_STATE */ 2, /* CMD_SET_STREAM_CB_MSG */ 3,
1517                 /* CMD_SET_STREAM_CB_SCRIPT */ 3, /* CMD_UNSET_STREAM_CB */ 2,
1518                 /* CMD_EXECUTE_SCRIPT */ 1, /* CMD_SLEEP */ 1 };
1519
1520 /* Command -> Function mapping */
1521 static int (*cmd_fcns[MAX_COMMAND_LINE_LEN])() = {
1522                 /* CMD_EXIT */ __exit,
1523                 /* CMD_HELP */ __print_cmd_help_msg,
1524                 /* CMD_CREATE_POOL */ __proxy_sound_pool_create,
1525                 /* CMD_DESTROY_POOL */ __proxy_sound_pool_destroy,
1526                 /* CMD_ACTIVATE_POOL */ __proxy_sound_pool_activate,
1527                 /* CMD_DEACTIVATE_POOL */ __proxy_sound_pool_deactivate,
1528                 /* CMD_GET_POOL_STATE */ __proxy_sound_pool_get_state,
1529                 /* CMD_SET_POOL_VOLUME */ __proxy_sound_pool_set_volume,
1530                 /* CMD_GET_POOL_VOLUME */ __proxy_sound_pool_get_volume,
1531                 /* CMD_SET_POOL_CB_MSG */ __proxy_sound_pool_set_state_change_callback_message,
1532                 /* CMD_SET_POOL_CB_SCRIPT */ __proxy_sound_pool_set_state_change_callback_script,
1533                 /* CMD_UNSET_POOL_CB */ __proxy_sound_pool_unset_state_change_callback,
1534                 /* CMD_LIST_POOL */ __proxy_sound_pool_list,
1535                 /* CMD_LOAD_SOURCE */ __proxy_sound_pool_load_source_from_file,
1536                 /* CMD_LOAD_MEDIA_PACKAGE */ NULL,
1537                 /* CMD_UNLOAD_SOURCE */ __proxy_sound_pool_unload_source,
1538                 /* CMD_PLAY_STREAM */ __proxy_sound_pool_play_stream,
1539                 /* CMD_STOP_STREAM */ __proxy_sound_pool_stop_stream,
1540                 /* CMD_PAUSE_STREAM */ __proxy_sound_pool_pause_stream,
1541                 /* CMD_RESUME_STREAM */ __proxy_sound_pool_resume_stream,
1542                 /* CMD_SET_STREAM_VOLUME */ __proxy_sound_pool_stream_set_volume,
1543                 /* CMD_GET_STREAM_VOLUME */ __proxy_sound_pool_stream_get_volume,
1544                 /* CMD_SET_STREAM_LOOP */ __proxy_sound_pool_stream_set_loop,
1545                 /* CMD_GET_STREAM_LOOP */ __proxy_sound_pool_stream_get_loop,
1546                 /* CMD_SET_STREAM_PRIORITY */ __proxy_sound_pool_stream_set_priority,
1547                 /* CMD_GET_STREAM_PRIORITY */ __proxy_sound_pool_stream_get_priority,
1548                 /* CMD_GET_STREAM_STATE */ __proxy_sound_pool_get_stream_state,
1549                 /* CMD_SET_STREAM_CB_MSG */ __proxy_sound_pool_set_stream_state_change_callback_message,
1550                 /* CMD_SET_STREAM_CB_SCRIPT */ __proxy_sound_pool_set_stream_state_change_callback_script,
1551                 /* CMD_UNSET_STREAM_CB */ __proxy_sound_pool_unset_stream_state_change_callback,
1552                 /* CMD_EXECUTE_SCRIPT */ __proxy_sound_pool_execute_script,
1553                 /* CMD_SLEEP */ __proxy_sleep };
1554
1555 int _exec_cmd(const char *cmd_line)
1556 {
1557         /* User just pressed enter: */
1558         if (strlen(cmd_line) == 0) return OK;
1559
1560         size_t trim_len = 0;
1561         while ((cmd_line + trim_len)[0] == ' ')
1562                 trim_len++;
1563
1564         const char *cmd = cmd_line + trim_len;
1565
1566         /* Macro for checking command correctness */
1567 #   define CHECK_CMD(ccmd, line) \
1568                         (strncmp(ccmd, line, strnlen(ccmd, MAX_COMMAND_LINE_LEN)) == 0)
1569
1570         int idx = 0;
1571         for (; idx < CMD_COUNT; ++idx) {
1572                 if (CHECK_CMD(cmd_list[idx], cmd)) {
1573                         if (cmd_pars[idx] > 0) {
1574                                 if (cmd_fcns[idx])
1575                                         return cmd_fcns[idx](cmd + strlen(cmd_list[idx]));
1576                         } else {
1577                                 return cmd_fcns[idx]();
1578                         }
1579                 }
1580         }
1581
1582         return UCMD;
1583 }