Fix for coding rule
[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
832         char tag[MAX_PATH_LEN] = {'\0'};
833
834         if ((pars == NULL) || sscanf(pars, " %zu %"MAX_PATH_LEN_STR"[^ ] %i %f %u",
835                                                                 &idx, tag, &loop, &volume, &rank) < 2) {
836                 _printf(CMD_COLOR_RED, "You have to specify at least pool identifier and "
837                                 "source tag to be played in stream! Format: " CMD_PLAY_STREAM
838                                 " <pool id> <source tag> <loop> <volume> <priority rank>... "
839                                 "0 'priority rank' value corresponds to the lowest priority.\n");
840                 return FAIL;
841         }
842
843         if (idx > (MAX_POOL_CNT - 1)) {
844                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
845                                 MAX_POOL_CNT - 1);
846                 return FAIL;
847         }
848
849         if (pools[idx] == NULL)
850                 _logger_log_warn("Pool with specified identifier is NULL");
851
852         _logger_log_info(CMD_PLAY_STREAM " command was called");
853         _logger_log_info("Playing stream based on source with '%s' tag from the pool "
854                         "with %zu identifier...", tag, idx);
855
856         unsigned stream_idx = 0;
857         int ret = sound_pool_stream_play(pools[idx], tag, loop, volume, rank, NULL,
858                         NULL, &stream_idx);
859
860         if (ret == SOUND_POOL_ERROR_NONE) {
861                 _logger_log_info("sound_pool_play_stream(pool, \"%s\", %i, %f, %u,"
862                                 " NULL, NULL, &stream_idx) returned %s value. "
863                                 "Generated identifier is %i", tag, loop, volume, rank,
864                                 __stringify_sound_pool_error(ret), stream_idx);
865                 _printf(CMD_COLOR_GREEN, "Generated stream identifier is %i\n", stream_idx);
866         } else {
867                 _logger_log_err("sound_pool_play_stream(pool, \"%s\", %i, %f, %u,"
868                                 " NULL, NULL, &stream_idx) returned %s value",
869                                 tag, loop, volume, rank, __stringify_sound_pool_error(ret));
870         }
871
872         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
873 }
874
875 /* CMD_PAUSE_STREAM */
876 static int __proxy_sound_pool_pause_stream(const char *pars)
877 {
878         size_t idx = 0;
879         size_t stream_idx = 0;
880
881         if ((pars == NULL) || (sscanf(pars, " %zu %i", &idx, &stream_idx) < 2)) {
882                 _printf(CMD_COLOR_RED, "You have to specify both pool identifier and "
883                                 "stream to be paused identifier! Format: " CMD_PAUSE_STREAM
884                                 " <pool id> <stream id>\n");
885                 return FAIL;
886         }
887
888         if (idx > (MAX_POOL_CNT - 1)) {
889                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
890                                 MAX_POOL_CNT - 1);
891                 return FAIL;
892         }
893
894         if (pools[idx] == NULL)
895                 _logger_log_warn("Pool with specified identifier is NULL");
896
897         _logger_log_info(CMD_PAUSE_STREAM " command was called");
898
899         int ret = sound_pool_stream_pause(pools[idx], stream_idx);
900
901         if (ret == SOUND_POOL_ERROR_NONE)
902                 _logger_log_info("sound_pool_pause_stream(pool, %i) returned %s "
903                                 "value", stream_idx, __stringify_sound_pool_error(ret));
904         else
905                 _logger_log_err("sound_pool_pause_stream(pool, %i) returned %s "
906                                 "value", stream_idx, __stringify_sound_pool_error(ret));
907
908         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
909 }
910
911 /* CMD_RESUME_STREAM */
912 static int __proxy_sound_pool_resume_stream(const char *pars)
913 {
914         size_t idx = 0;
915         size_t stream_idx = 0;
916
917         if ((pars == NULL) || (sscanf(pars, " %zu %i", &idx, &stream_idx) < 2)) {
918                 _printf(CMD_COLOR_RED, "You have to specify both pool identifier and "
919                                 "stream to be resumed identifier! Format: " CMD_RESUME_STREAM
920                                 " <pool id> <stream id>\n");
921                 return FAIL;
922         }
923
924         if (idx > (MAX_POOL_CNT - 1)) {
925                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
926                                 MAX_POOL_CNT - 1);
927                 return FAIL;
928         }
929
930         if (pools[idx] == NULL)
931                 _logger_log_warn("Pool with specified identifier is NULL");
932
933         _logger_log_info(CMD_RESUME_STREAM " command was called");
934
935         int ret = sound_pool_stream_resume(pools[idx], stream_idx);
936
937         if (ret == SOUND_POOL_ERROR_NONE)
938                 _logger_log_info("sound_pool_resume_stream(pool, %i) returned %s "
939                                 "value", stream_idx, __stringify_sound_pool_error(ret));
940         else
941                 _logger_log_err("sound_pool_resume_stream(pool, %i) returned %s "
942                                 "value", stream_idx, __stringify_sound_pool_error(ret));
943
944         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
945 }
946
947 /* CMD_STOP_STREAM */
948 static int __proxy_sound_pool_stop_stream(const char *pars)
949 {
950         size_t idx = 0;
951         size_t stream_idx = 0;
952
953         if ((pars == NULL) || (sscanf(pars, " %zu %zu", &idx, &stream_idx) < 2)) {
954                 _printf(CMD_COLOR_RED, "You have to specify both pool identifier and "
955                                 "stream to be stopped identifier! Format: " CMD_STOP_STREAM
956                                 " <pool id> <stream id>\n");
957                 return FAIL;
958         }
959
960         if (idx > (MAX_POOL_CNT - 1)) {
961                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
962                                 MAX_POOL_CNT - 1);
963                 return FAIL;
964         }
965
966         if (pools[idx] == NULL)
967                 _logger_log_warn("Pool with specified identifier is NULL");
968
969         _logger_log_info(CMD_STOP_STREAM " command was called");
970
971         int ret = sound_pool_stream_stop(pools[idx], stream_idx);
972
973         if (ret == SOUND_POOL_ERROR_NONE)
974                 _logger_log_info("sound_pool_stop_stream(pool, %i) returned %s "
975                                 "value", stream_idx, __stringify_sound_pool_error(ret));
976         else
977                 _logger_log_err("sound_pool_stop_stream(pool, %i) returned %s "
978                                 "value", stream_idx, __stringify_sound_pool_error(ret));
979
980         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
981 }
982
983 /* CMD_SET_STREAM_VOLUME */
984 static int __proxy_sound_pool_stream_set_volume(const char *pars)
985 {
986         size_t idx = 0;
987         size_t stream_idx = 0;
988         float volume_val = 1.0f;
989
990         if ((pars == NULL)
991                         || (sscanf(pars, " %zu %zu %f", &idx, &stream_idx, &volume_val) < 3)) {
992                 _printf(CMD_COLOR_RED, "You have to specify all following parameters: "
993                                 "pool identifier, stream identifier! Format: "
994                                 CMD_SET_STREAM_VOLUME " <pool id> <stream id> <volume>\n");
995                 return FAIL;
996         }
997
998         if (idx > (MAX_POOL_CNT - 1)) {
999                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
1000                                 MAX_POOL_CNT - 1);
1001                 return FAIL;
1002         }
1003
1004         if (pools[idx] == NULL)
1005                 _logger_log_warn("Pool with specified identifier is NULL");
1006
1007         if (volume_val < .0f || volume_val > 1.0f)
1008                 _logger_log_warn("Volume has to be specified in 0.0~1.0 range");
1009
1010         _logger_log_info(CMD_SET_STREAM_VOLUME " command was called");
1011
1012         int ret = sound_pool_stream_set_volume(pools[idx], stream_idx, volume_val);
1013
1014         if (ret == SOUND_POOL_ERROR_NONE)
1015                 _logger_log_info("sound_pool_stream_set_volume(pool, %i, %f) "
1016                                 "returned %s value", stream_idx, volume_val,
1017                                 __stringify_sound_pool_error(ret));
1018         else
1019                 _logger_log_err("sound_pool_stream_set_volume(pool, %i, %f) "
1020                                 "returned %s value", stream_idx, volume_val,
1021                                 __stringify_sound_pool_error(ret));
1022
1023         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
1024 }
1025
1026 /* CMD_GET_STREAM_VOLUME */
1027 static int __proxy_sound_pool_stream_get_volume(const char *pars)
1028 {
1029         size_t idx = 0;
1030         size_t stream_idx = 0;
1031         if ((pars == NULL) || (sscanf(pars, " %zu %zu", &idx, &stream_idx) < 2)) {
1032                 _printf(CMD_COLOR_RED, "You have to specify both pool and stream "
1033                                 "identifiers after command name! Format: "
1034                                 CMD_GET_STREAM_VOLUME " <pool id> <stream id>\n");
1035                 return FAIL;
1036         }
1037
1038         if (idx > (MAX_POOL_CNT - 1)) {
1039                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
1040                                 MAX_POOL_CNT - 1);
1041                 return FAIL;
1042         }
1043
1044         _logger_log_info(CMD_GET_STREAM_VOLUME " command was called");
1045         _logger_log_info("Getting the %zu stream from %zu pool volume value...",
1046                         stream_idx, idx);
1047
1048         if (pools[idx] == NULL)
1049                 _logger_log_warn("Pool to get state for is NULL");
1050
1051         float volume = .0f;
1052         int ret = sound_pool_stream_get_volume(pools[idx], stream_idx, &volume);
1053
1054         if (ret == SOUND_POOL_ERROR_NONE)
1055                 _logger_log_info("sound_pool_stream_get_volume(pool, %zu, volume) "
1056                                 "returned %s value, volume is %f", stream_idx,
1057                                 __stringify_sound_pool_error(ret), volume);
1058         else
1059                 _logger_log_err("sound_pool_stream_get_volume(pool, %zu, volume) "
1060                                 "returned %s value, volume is %f", stream_idx,
1061                                 __stringify_sound_pool_error(ret), volume);
1062
1063         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
1064 }
1065
1066 /* CMD_SET_STREAM_LOOP */
1067 static int __proxy_sound_pool_stream_set_loop(const char *pars)
1068 {
1069         size_t idx = 0;
1070         size_t stream_idx = 0;
1071         int loop_val = 1;
1072
1073         if ((pars == NULL)
1074                         || (sscanf(pars, " %zu %zu %i", &idx, &stream_idx, &loop_val) < 3)) {
1075                 _printf(CMD_COLOR_RED, "You have to specify all following parameters: "
1076                                 "pool identifier, stream identifier, and loop number! Format: "
1077                                 CMD_SET_STREAM_LOOP " <pool id> <stream id> <loop num>\n");
1078                 return FAIL;
1079         }
1080
1081         if (idx > (MAX_POOL_CNT - 1)) {
1082                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
1083                                 MAX_POOL_CNT - 1);
1084                 return FAIL;
1085         }
1086
1087         if (pools[idx] == NULL)
1088                 _logger_log_warn("Pool with specified identifier is NULL");
1089
1090         if (loop_val < 0)
1091                 _logger_log_warn("Loop number should to be greater than 0, but it's"
1092                                 "value is %i", loop_val);
1093
1094         _logger_log_info(CMD_SET_STREAM_LOOP " command was called");
1095
1096         int ret = sound_pool_stream_set_loop(pools[idx], stream_idx, loop_val);
1097
1098         if (ret == SOUND_POOL_ERROR_NONE)
1099                 _logger_log_info("sound_pool_stream_set_loop(pool, %zu, %i) "
1100                                 "returned %s value", stream_idx, loop_val,
1101                                 __stringify_sound_pool_error(ret));
1102         else
1103                 _logger_log_err("sound_pool_stream_set_loop(pool, %zu, %i) "
1104                                 "returned %s value", stream_idx, loop_val,
1105                                 __stringify_sound_pool_error(ret));
1106
1107         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
1108 }
1109
1110 /* CMD_GET_STREAM_LOOP */
1111 static int __proxy_sound_pool_stream_get_loop(const char *pars)
1112 {
1113         size_t idx = 0;
1114         size_t stream_idx = 0;
1115         if ((pars == NULL) || (sscanf(pars, " %zu %zu", &idx, &stream_idx) < 2)) {
1116                 _printf(CMD_COLOR_RED, "You have to specify both pool and stream "
1117                                 "identifiers after command name! Format: "
1118                                 CMD_GET_STREAM_LOOP " <pool id> <stream id>\n");
1119                 return FAIL;
1120         }
1121
1122         if (idx > (MAX_POOL_CNT - 1)) {
1123                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
1124                                 MAX_POOL_CNT - 1);
1125                 return FAIL;
1126         }
1127
1128         _logger_log_info(CMD_GET_STREAM_LOOP " command was called");
1129         _logger_log_info("Getting the stream state by %zu identifier in %zu "
1130                         "pool...", stream_idx, idx);
1131
1132         if (pools[idx] == NULL)
1133                 _logger_log_warn("Pool where stream should be located is NULL");
1134
1135         unsigned loop = 0;
1136         int ret = sound_pool_stream_get_loop(pools[idx], stream_idx, &loop);
1137
1138         if (ret == SOUND_POOL_ERROR_NONE)
1139                 _logger_log_info("sound_pool_stream_get_loop(pool, %zu, loop) "
1140                                 "returned %s value, loop value is %i", stream_idx,
1141                                 __stringify_sound_pool_error(ret), loop);
1142         else
1143                 _logger_log_err("sound_pool_stream_get_loop(pool, %zu, loop) "
1144                                 "returned %s value, loop value is %i", stream_idx,
1145                                 __stringify_sound_pool_error(ret), loop);
1146
1147         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
1148 }
1149
1150 /* CMD_SET_STREAM_PRIORITY */
1151 static int __proxy_sound_pool_stream_set_priority(const char *pars)
1152 {
1153         size_t idx = 0;
1154         size_t stream_idx = 0;
1155         unsigned rank = 0;
1156
1157         if ((pars == NULL)
1158                         || (sscanf(pars, " %zu %zu %u", &idx, &stream_idx, &rank) < 3)) {
1159                 _printf(CMD_COLOR_RED, "You have to specify all following parameters: "
1160                                 "pool identifier, stream identifier, and priority rank! Format: "
1161                                 CMD_SET_STREAM_PRIORITY " <pool id> <stream id> <rank>\n");
1162                 return FAIL;
1163         }
1164
1165         if (idx > (MAX_POOL_CNT - 1)) {
1166                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
1167                                 MAX_POOL_CNT - 1);
1168                 return FAIL;
1169         }
1170
1171         if (pools[idx] == NULL)
1172                 _logger_log_warn("Pool with specified identifier is NULL");
1173
1174         if (rank < 0)
1175                 _logger_log_warn("Priority rank should to be greater or equal 0, but "
1176                                 "it's value is %i", rank);
1177
1178         _logger_log_info(CMD_SET_STREAM_PRIORITY " command was called");
1179
1180         int ret = sound_pool_stream_set_priority(pools[idx], stream_idx, rank);
1181
1182         if (ret == SOUND_POOL_ERROR_NONE)
1183                 _logger_log_info("sound_pool_stream_set_priority(pool, %zu, %u) "
1184                                 "returned %s value", stream_idx, rank,
1185                                 __stringify_sound_pool_error(ret));
1186         else
1187                 _logger_log_err("sound_pool_stream_set_priority(pool, %zu, %u) "
1188                                 "returned %s value", stream_idx, rank,
1189                                 __stringify_sound_pool_error(ret));
1190
1191         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
1192 }
1193
1194 /* CMD_GET_STREAM_PRIORITY */
1195 static int __proxy_sound_pool_stream_get_priority(const char *pars)
1196 {
1197         size_t idx = 0;
1198         size_t stream_idx = 0;
1199         if ((pars == NULL) || (sscanf(pars, " %zu %zu", &idx, &stream_idx) < 2)) {
1200                 _printf(CMD_COLOR_RED, "You have to specify both pool and stream "
1201                                 "identifiers after command name! Format: "
1202                                 CMD_GET_STREAM_PRIORITY " <pool id> <stream id>\n");
1203                 return FAIL;
1204         }
1205
1206         if (idx > (MAX_POOL_CNT - 1)) {
1207                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
1208                                 MAX_POOL_CNT - 1);
1209                 return FAIL;
1210         }
1211
1212         _logger_log_info(CMD_GET_STREAM_PRIORITY " command was called");
1213         _logger_log_info("Getting the stream priority rank by %zu identifier in "
1214                         "%zu pool...", stream_idx, idx);
1215
1216         if (pools[idx] == NULL)
1217                 _logger_log_warn("Pool where stream should be located is NULL");
1218
1219         unsigned rank = 0;
1220         int ret = sound_pool_stream_get_priority(pools[idx], stream_idx, &rank);
1221
1222         if (ret == SOUND_POOL_ERROR_NONE)
1223                 _logger_log_info("sound_pool_stream_get_priority(pool, %u, rank) "
1224                                 "returned %s value, rank value is %u", stream_idx,
1225                                 __stringify_sound_pool_error(ret), rank);
1226         else
1227                 _logger_log_err("sound_pool_stream_get_priority(pool, %u, rank) "
1228                                 "returned %s value, rank value is %u", stream_idx,
1229                                 __stringify_sound_pool_error(ret), rank);
1230
1231         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
1232 }
1233
1234 /* CMD_GET_STREAM_STATE */
1235 static int __proxy_sound_pool_get_stream_state(const char *pars)
1236 {
1237         size_t idx = 0;
1238         size_t stream_idx = 0;
1239         if ((pars == NULL) || (sscanf(pars, " %zu %zu", &idx, &stream_idx) < 2)) {
1240                 _printf(CMD_COLOR_RED, "You have to specify both pool and stream "
1241                                 "identifiers after command name! Format: "
1242                                 CMD_GET_STREAM_STATE " <pool id> <stream id>\n");
1243                 return FAIL;
1244         }
1245
1246         if (idx > (MAX_POOL_CNT - 1)) {
1247                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
1248                                 MAX_POOL_CNT - 1);
1249                 return FAIL;
1250         }
1251
1252         _logger_log_info(CMD_GET_STREAM_STATE " command was called");
1253         _logger_log_info("Getting the stream state by %zu identifier in %zu "
1254                         "pool...", stream_idx, idx);
1255
1256         if (pools[idx] == NULL)
1257                 _logger_log_warn("Pool where stream should be located is NULL");
1258
1259         sound_pool_stream_state_e state = SOUND_POOL_STREAM_STATE_NONE;
1260         int ret = sound_pool_stream_get_state(pools[idx], stream_idx,  &state);
1261
1262         if (ret == SOUND_POOL_ERROR_NONE)
1263                 _logger_log_info("sound_pool_get_stream_state(pool, %zu, state) "
1264                                 "returned %s value, state is %s", stream_idx,
1265                                 __stringify_sound_pool_error(ret),
1266                                 __stringify_stream_state(state));
1267         else
1268                 _logger_log_err("sound_pool_get_stream_state(pool, %zu, state) "
1269                                 "returned %s value, state is %s", stream_idx,
1270                                 __stringify_sound_pool_error(ret),
1271                                 __stringify_stream_state(state));
1272
1273         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
1274 }
1275
1276 /* CMD_SET_STREAM_CB_MSG */
1277 static int __proxy_sound_pool_set_stream_state_change_callback_message(const char *pars)
1278 {
1279         size_t idx = 0;
1280         size_t stream_idx = 0;
1281
1282         char msg[MAX_MSG_LEN] = { '\0' };
1283
1284         if ((pars == NULL) || sscanf(pars, " %zu %zu %"MAX_MSG_LEN_STR"[^ ]",
1285                                                                 &idx, &stream_idx, msg) < 3) {
1286                 _printf(CMD_COLOR_RED, "You have to specify both identifier of the "
1287                                 "pool and stream, plus message to be shown each time when "
1288                                 "state of the stream is changed! Message should be a single "
1289                                 "word. Format: "
1290                                 CMD_SET_STREAM_CB_MSG " <pool id> <stream id> <message>\n");
1291                 return FAIL;
1292         }
1293
1294         if (idx > (MAX_POOL_CNT - 1)) {
1295                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
1296                                 MAX_POOL_CNT - 1);
1297                 return FAIL;
1298         }
1299
1300         if (stream_idx > (MAX_STREAM_CNT - 1)) {
1301                 _printf(CMD_COLOR_RED, "Stream identifier value can't be greater than %d\n",
1302                                 MAX_STREAM_CNT - 1);
1303                 return FAIL;
1304         }
1305
1306         _logger_log_info(CMD_SET_STREAM_CB_MSG " command was called");
1307         _logger_log_info("Set state changing callback (%s message) for stream %zu "
1308                         "in pool with %zu identifier...", msg, stream_idx, idx);
1309
1310         if (pools[idx] == NULL)
1311                 _logger_log_warn("Pool with stream to set callback for is NULL");
1312
1313         if (stream_messages[idx][stream_idx])
1314                 free(stream_messages[idx][stream_idx]);
1315         stream_messages[idx][stream_idx] = strndup(msg, MAX_MSG_LEN);
1316
1317         int ret = sound_pool_stream_set_state_change_callback(pools[idx], stream_idx,
1318                         __s_cb_msg, stream_messages[idx][stream_idx]);
1319
1320         if (ret == SOUND_POOL_ERROR_NONE)
1321                 _logger_log_info("sound_pool_set_stream_state_change_callback(pool, "
1322                                 "%zu, cb, \"%s\") returned %s value", stream_idx, msg,
1323                                 __stringify_sound_pool_error(ret));
1324         else
1325                 _logger_log_err("sound_pool_set_stream_state_change_callback(pool, "
1326                                 "%zu, cb, \"%s\") returned %s value", stream_idx, msg,
1327                                 __stringify_sound_pool_error(ret));
1328
1329         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
1330 }
1331
1332 /* CMD_SET_STREAM_CB_SCRIPT */
1333 static int __proxy_sound_pool_set_stream_state_change_callback_script(const char *pars)
1334 {
1335         size_t idx = 0;
1336         size_t stream_idx = 0;
1337
1338         char scr[MAX_MSG_LEN] = { '\0' };
1339
1340         if ((pars == NULL) || sscanf(pars, " %zu %zu %"MAX_MSG_LEN_STR"[^ ]",
1341                                                                 &idx, &stream_idx, scr) < 3) {
1342                 _printf(CMD_COLOR_RED, "You have to specify both identifier of the "
1343                                 "pool and stream, plus file with script to be executed each "
1344                                 "time when state of the stream is changed! Message should be a "
1345                                 "single word. Format: " CMD_SET_STREAM_CB_SCRIPT
1346                                 " <pool id> <stream id> <script file>\n");
1347                 return FAIL;
1348         }
1349
1350         if (idx > (MAX_POOL_CNT - 1)) {
1351                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
1352                                 MAX_POOL_CNT - 1);
1353                 return FAIL;
1354         }
1355
1356         if (stream_idx > (MAX_STREAM_CNT - 1)) {
1357                 _printf(CMD_COLOR_RED, "Stream identifier value can't be greater than %d\n",
1358                                 MAX_STREAM_CNT - 1);
1359                 return FAIL;
1360         }
1361
1362         _logger_log_info(CMD_SET_STREAM_CB_SCRIPT " command was called");
1363         _logger_log_info("Set state changing callback (%s script) for stream %zu "
1364                         "in pool with %zu identifier...", scr, stream_idx, idx);
1365
1366         if (pools[idx] == NULL)
1367                 _logger_log_warn("Pool with stream to set callback for is NULL");
1368
1369         if (stream_scripts[idx][stream_idx])
1370                 free(stream_scripts[idx][stream_idx]);
1371         stream_scripts[idx][stream_idx] = strndup(scr, MAX_MSG_LEN);
1372
1373         int ret = sound_pool_stream_set_state_change_callback(pools[idx], stream_idx,
1374                         __s_cb_scr, stream_scripts[idx][stream_idx]);
1375
1376         if (ret == SOUND_POOL_ERROR_NONE)
1377                 _logger_log_info("sound_pool_set_stream_state_change_callback(pool, "
1378                                 "%zu, cb, \"%s\") returned %s value", stream_idx, scr,
1379                                 __stringify_sound_pool_error(ret));
1380         else
1381                 _logger_log_err("sound_pool_set_stream_state_change_callback(pool, "
1382                                 "%zu, cb, \"%s\") returned %s value", stream_idx, scr,
1383                                 __stringify_sound_pool_error(ret));
1384
1385         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
1386 }
1387
1388 /* CMD_UNSET_STREAM_CB */
1389 static int __proxy_sound_pool_unset_stream_state_change_callback(const char *pars)
1390 {
1391         size_t idx = 0;
1392         size_t stream_idx = 0;
1393         if ((pars == NULL) || (sscanf(pars, " %zu %zu", &idx, &stream_idx) < 2)) {
1394                 _printf(CMD_COLOR_RED, "You have to specify both identifier of the "
1395                                 " pool and stream! Format: " CMD_UNSET_STREAM_CB
1396                                 " <pool id> <stream id>\n");
1397                 return FAIL;
1398         }
1399
1400         if (idx > (MAX_POOL_CNT - 1)) {
1401                 _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n",
1402                                 MAX_POOL_CNT - 1);
1403                 return FAIL;
1404         }
1405
1406         _logger_log_info(CMD_UNSET_STREAM_CB " command was called");
1407         _logger_log_info("Unset state changing callback for the stream %zu in pool "
1408                         "with %zu identifier...", stream_idx, idx);
1409
1410         if (pools[idx] == NULL)
1411                 _logger_log_warn("Pool to unset callback for is NULL");
1412
1413         int ret = sound_pool_stream_unset_state_change_callback(pools[idx], stream_idx);
1414
1415         if (stream_idx > (MAX_STREAM_CNT - 1)) {
1416                 _printf(CMD_COLOR_RED, "Stream identifier value can't be greater than %d\n",
1417                                 MAX_STREAM_CNT - 1);
1418                 return FAIL;
1419         }
1420
1421         if (stream_messages[idx][stream_idx] != NULL)
1422                 free(stream_messages[idx][stream_idx]);
1423         stream_messages[idx][stream_idx] = NULL;
1424
1425         if (stream_scripts[idx][stream_idx] != NULL)
1426                 free(stream_scripts[idx][stream_idx]);
1427         stream_scripts[idx][stream_idx] = NULL;
1428
1429         if (ret == SOUND_POOL_ERROR_NONE)
1430                 _logger_log_info("sound_pool_unset_stream_state_change_callback(pool, "
1431                                 "%zu) returned %s value", stream_idx,
1432                                 __stringify_sound_pool_error(ret));
1433         else
1434                 _logger_log_info("sound_pool_unset_stream_state_change_callback(pool, "
1435                                 "%zu) returned %s value", stream_idx,
1436                                 __stringify_sound_pool_error(ret));
1437
1438         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
1439 }
1440
1441 /* CMD_SLEEP */
1442 static int __proxy_sleep(const char *pars)
1443 {
1444         int ret = SOUND_POOL_ERROR_NONE;
1445
1446         useconds_t stime = 0;
1447
1448         if ((pars == NULL) || (sscanf(pars, " %u", &stime) < 1)) {
1449                 _printf(CMD_COLOR_RED, "You have to specify number of milliseconds "
1450                                 "for the pause duration! Format: " CMD_SLEEP " <millisecs>\n");
1451                 return FAIL;
1452         }
1453
1454         _logger_log_info(CMD_SLEEP " command was called");
1455         _logger_log_info("Start main thread sleep for %u milliseconds...", stime);
1456         stime *= MICROSECS_PER_MILLISEC;
1457         usleep(stime);
1458         _logger_log_info("Main thread sleep has been finished...", stime);
1459
1460         return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL);
1461 }
1462
1463 /* CMD_EXECUTE_SCRIPT */
1464 static int __proxy_sound_pool_execute_script(const char *pars)
1465 {
1466         char script_file[MAX_PATH_LEN] = {'\0'};
1467
1468         if ((pars == NULL) || (sscanf(pars, " %"MAX_PATH_LEN_STR"[^ ]", script_file) < 1)) {
1469                 _printf(CMD_COLOR_RED, "You have to specify script file name to be "
1470                                 "executed after command name! Format: " CMD_EXECUTE_SCRIPT " "
1471                                 "<script file>\n");
1472                 return FAIL;
1473         }
1474
1475         _logger_log_info(CMD_EXECUTE_SCRIPT " command was called");
1476         _logger_log_info("Loading script from file...");
1477         FILE *fd = fopen(script_file, "r");
1478
1479         if (fd) {
1480                 _logger_log_info("File has been loaded...");
1481                 _logger_log_info("Reading lines...");
1482                 size_t line_len = 0;
1483                 char *line = NULL;
1484                 while ((line_len = getline(&line, &line_len, fd)) != -1) {
1485                         line[strnlen(line, MAX_COMMAND_LINE_LEN) - 1] = '\0';
1486                         _logger_log_info("Executing line: %s", line);
1487                         if (_exec_cmd(line) != OK)
1488                                 _logger_log_warn("Unknown or unsupported command! "
1489                                                 "Line was skipped.");
1490                 }
1491                 _logger_log_info("Lines were read...");
1492         } else {
1493                 _logger_log_err("File wasn't loaded...");
1494                 return FAIL;
1495         }
1496
1497         _logger_log_info("Close file...");
1498
1499         if (fd)
1500                 fclose(fd);
1501
1502         return OK;
1503 }
1504
1505 /* Number of parameters supported by each command */
1506 static int cmd_pars[MAX_COMMAND_LINE_LEN] = { /* CMD_EXIT */ 0,
1507                 /* CMD_HELP */ 0, /* CMD_CREATE_POOL */ 0, /* CMD_DESTROY_POOL */ 1,
1508                 /* CMD_ACTIVATE_POOL */ 1, /* CMD_DEACTIVATE_POOL */ 1,
1509                 /* CMD_GET_POOL_STATE */ 1, /* CMD_SET_POOL_VOLUME */ 2,
1510                 /* CMD_GET_POOL_VOLUME */ 2, /* CMD_SET_POOL_CB_MSG */ 2,
1511                 /* CMD_SET_POOL_CB_SCRIPT */ 2, /* CMD_UNSET_POOL_CB */ 1,
1512                 /* CMD_LIST_POOL */ 0, /* CMD_LOAD_SOURCE */ 3,
1513                 /* CMD_LOAD_MEDIA_PACKAGE */ 3, /* CMD_UNLOAD_SOURCE */ 2,
1514                 /* CMD_PLAY_STREAM */ 5, /* CMD_STOP_STREAM */ 2,
1515                 /* CMD_PAUSE_STREAM */ 2, /* CMD_RESUME_STREAM */ 2,
1516                 /* CMD_SET_STREAM_VOLUME */ 3, /* CMD_GET_STREAM_VOLUME */ 2,
1517                 /* CMD_SET_STREAM_LOOP */ 3, /* CMD_GET_STREAM_LOOP */ 2,
1518                 /* CMD_SET_STREAM_PRIORITY */ 3, /* CMD_GET_STREAM_PRIORITY */ 2,
1519                 /* CMD_GET_STREAM_STATE */ 2, /* CMD_SET_STREAM_CB_MSG */ 3,
1520                 /* CMD_SET_STREAM_CB_SCRIPT */ 3, /* CMD_UNSET_STREAM_CB */ 2,
1521                 /* CMD_EXECUTE_SCRIPT */ 1, /* CMD_SLEEP */ 1 };
1522
1523 /* Command -> Function mapping */
1524 static int (*cmd_fcns[MAX_COMMAND_LINE_LEN])() = {
1525                 /* CMD_EXIT */ __exit,
1526                 /* CMD_HELP */ __print_cmd_help_msg,
1527                 /* CMD_CREATE_POOL */ __proxy_sound_pool_create,
1528                 /* CMD_DESTROY_POOL */ __proxy_sound_pool_destroy,
1529                 /* CMD_ACTIVATE_POOL */ __proxy_sound_pool_activate,
1530                 /* CMD_DEACTIVATE_POOL */ __proxy_sound_pool_deactivate,
1531                 /* CMD_GET_POOL_STATE */ __proxy_sound_pool_get_state,
1532                 /* CMD_SET_POOL_VOLUME */ __proxy_sound_pool_set_volume,
1533                 /* CMD_GET_POOL_VOLUME */ __proxy_sound_pool_get_volume,
1534                 /* CMD_SET_POOL_CB_MSG */ __proxy_sound_pool_set_state_change_callback_message,
1535                 /* CMD_SET_POOL_CB_SCRIPT */ __proxy_sound_pool_set_state_change_callback_script,
1536                 /* CMD_UNSET_POOL_CB */ __proxy_sound_pool_unset_state_change_callback,
1537                 /* CMD_LIST_POOL */ __proxy_sound_pool_list,
1538                 /* CMD_LOAD_SOURCE */ __proxy_sound_pool_load_source_from_file,
1539                 /* CMD_LOAD_MEDIA_PACKAGE */ NULL,
1540                 /* CMD_UNLOAD_SOURCE */ __proxy_sound_pool_unload_source,
1541                 /* CMD_PLAY_STREAM */ __proxy_sound_pool_play_stream,
1542                 /* CMD_STOP_STREAM */ __proxy_sound_pool_stop_stream,
1543                 /* CMD_PAUSE_STREAM */ __proxy_sound_pool_pause_stream,
1544                 /* CMD_RESUME_STREAM */ __proxy_sound_pool_resume_stream,
1545                 /* CMD_SET_STREAM_VOLUME */ __proxy_sound_pool_stream_set_volume,
1546                 /* CMD_GET_STREAM_VOLUME */ __proxy_sound_pool_stream_get_volume,
1547                 /* CMD_SET_STREAM_LOOP */ __proxy_sound_pool_stream_set_loop,
1548                 /* CMD_GET_STREAM_LOOP */ __proxy_sound_pool_stream_get_loop,
1549                 /* CMD_SET_STREAM_PRIORITY */ __proxy_sound_pool_stream_set_priority,
1550                 /* CMD_GET_STREAM_PRIORITY */ __proxy_sound_pool_stream_get_priority,
1551                 /* CMD_GET_STREAM_STATE */ __proxy_sound_pool_get_stream_state,
1552                 /* CMD_SET_STREAM_CB_MSG */ __proxy_sound_pool_set_stream_state_change_callback_message,
1553                 /* CMD_SET_STREAM_CB_SCRIPT */ __proxy_sound_pool_set_stream_state_change_callback_script,
1554                 /* CMD_UNSET_STREAM_CB */ __proxy_sound_pool_unset_stream_state_change_callback,
1555                 /* CMD_EXECUTE_SCRIPT */ __proxy_sound_pool_execute_script,
1556                 /* CMD_SLEEP */ __proxy_sleep };
1557
1558 int _exec_cmd(const char *cmd_line)
1559 {
1560         /* User just pressed enter: */
1561         if (strlen(cmd_line) == 0) return OK;
1562
1563         size_t trim_len = 0;
1564         while ((cmd_line + trim_len)[0] == ' ')
1565                 trim_len++;
1566
1567         const char *cmd = cmd_line + trim_len;
1568
1569         /* Macro for checking command correctness */
1570 #   define CHECK_CMD(ccmd, line) \
1571                         (strncmp(ccmd, line, strnlen(ccmd, MAX_COMMAND_LINE_LEN)) == 0)
1572
1573         int idx = 0;
1574         for (; idx < CMD_COUNT; ++idx) {
1575                 if (CHECK_CMD(cmd_list[idx], cmd)) {
1576                         if (cmd_pars[idx] > 0) {
1577                                 if (cmd_fcns[idx])
1578                                         return cmd_fcns[idx](cmd + strlen(cmd_list[idx]));
1579                         } else {
1580                                 return cmd_fcns[idx]();
1581                         }
1582                 }
1583         }
1584
1585         return UCMD;
1586 }