Add handler for player error
[platform/core/uifw/tts.git] / server / ttsd_player.c
1 /*
2 *  Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd All Rights Reserved 
3 *  Licensed under the Apache License, Version 2.0 (the "License");
4 *  you may not use this file except in compliance with the License.
5 *  You may obtain a copy of the License at
6 *  http://www.apache.org/licenses/LICENSE-2.0
7 *  Unless required by applicable law or agreed to in writing, software
8 *  distributed under the License is distributed on an "AS IS" BASIS,
9 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 *  See the License for the specific language governing permissions and
11 *  limitations under the License.
12 */
13
14
15 #include <mm_types.h>
16 #include <mm_player.h>
17 #include <mm_player_internal.h>
18 #include <mm_session.h>
19 #include <mm_error.h>
20 #include <Ecore.h>
21
22 #include "ttsd_main.h"
23 #include "ttsd_player.h"
24 #include "ttsd_data.h"
25 #include "ttsd_dbus.h"
26
27
28 /*
29 * Internal data structure
30 */
31
32 #define TEMP_FILE_MAX   36
33
34 typedef struct {
35         char    riff[4];
36         int     file_size;
37         char    wave[4];
38         char    fmt[4];
39         int     header_size;
40         short   sample_format;
41         short   n_channels;
42         int     sample_rate;
43         int     bytes_per_second;
44         short   block_align;
45         short   bits_per_sample;
46         char    data[4];
47         int     data_size;
48 } WavHeader;
49
50 typedef struct {
51         int             uid;            /** client id */
52         MMHandleType    player_handle;  /** mm player handle */
53         int             utt_id;         /** utt_id of next file */
54         ttsp_result_event_e event;      /** event of callback */
55         bool            pause_after_complete;   /** For resume when the 'Paused' state of player after end callback */
56 } player_s;
57
58 typedef struct {
59         int  uid;
60         int  utt_id;
61         ttsp_result_event_e event;
62         char filename[TEMP_FILE_MAX];
63 } user_data_s;
64
65
66 /*
67 * static data
68 */
69
70 #define TEMP_FILE_PATH  "/tmp"
71 #define FILE_PATH_SIZE  256
72 #define DEFAULT_FILE_SIZE 10
73
74 /** player init info */
75 static bool g_player_init = false;
76
77 /** tts engine list */
78 static GList *g_player_list;
79
80 /** current player information */
81 static player_s* g_playing_info;
82
83 /** player callback function */
84 static player_result_callback_func g_result_callback;
85
86 /** numbering for temp file */
87 static unsigned int g_index;              
88
89 /*
90 * Internal Interfaces 
91 */
92 player_s* __player_get_item(int uid);
93
94 int __save_file(int uid, int index, sound_data_s data, char** filename);
95
96 int __set_and_start(player_s* player);
97
98 int __init_wave_header(WavHeader* hdr, size_t nsamples, size_t sampling_rate, int channel);
99
100 static int msg_callback(int message, void *data, void *user_param) ;
101
102
103 /*
104 * Player Interfaces 
105 */
106
107 int ttsd_player_init(player_result_callback_func result_cb)
108 {
109         if (NULL == result_cb) {
110                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] invalid parameter");
111                 return TTSD_ERROR_INVALID_PARAMETER;
112         }
113
114         g_result_callback = result_cb;
115
116         g_playing_info = NULL;
117         
118         g_index = 1;
119         g_player_init = true;
120
121         if (TTSD_MODE_DEFAULT == ttsd_get_mode()) {
122                 if (MM_ERROR_NONE != mm_session_init(MM_SESSION_TYPE_EXCLUSIVE)) {
123                         SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail mm_session_init(MM_SESSION_TYPE_EXCLUSIVE)");   
124                 } else {
125                         SLOG(LOG_ERROR, get_tag(), "[Player SUCCESS] mm_session_init(MM_SESSION_TYPE_EXCLUSIVE)");      
126                 }
127         }
128
129         return 0;
130 }
131
132 int ttsd_player_release(void)
133 {
134         if (false == g_player_init) {
135                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized");
136                 return TTSD_ERROR_OPERATION_FAILED;
137         }
138
139         /* clear g_player_list */
140         g_playing_info = NULL;
141         g_player_init = false;
142
143         return 0;
144 }
145
146 int ttsd_player_create_instance(int uid)
147 {
148         if (false == g_player_init) {
149                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" );
150                 return -1;
151         }
152         
153         /* Check uid is duplicated */
154         if (NULL != __player_get_item(uid)) {
155                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is already registered", uid); 
156                 return -1;
157         }
158
159         int ret = MM_ERROR_NONE; 
160         MMHandleType player_handle;
161         
162         ret = mm_player_create(&player_handle);
163         if (ret != MM_ERROR_NONE || 0 == player_handle) {
164                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_create() : %x", ret);
165                 return -2;
166         }
167
168         player_s* new_client = (player_s*)g_malloc0( sizeof(player_s) * 1);
169
170         new_client->uid = uid;
171         new_client->player_handle = player_handle;
172         new_client->utt_id = -1;
173         new_client->event = TTSP_RESULT_EVENT_FINISH;
174         new_client->pause_after_complete = false;
175         
176         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Player] Create player : uid(%d), handle(%d)", uid, player_handle );
177
178         g_player_list = g_list_append(g_player_list, new_client);
179
180         return 0;
181 }
182
183 int ttsd_player_destroy_instance(int uid)
184 {
185         if (false == g_player_init) {
186                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" );
187                 return -1;
188         }
189
190         player_s* current;
191         current = __player_get_item(uid);
192         if (NULL == current) {
193                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is not valid", uid); 
194                 return -1;
195         }
196
197         if (NULL != g_playing_info) {
198                 if (uid == g_playing_info->uid) {
199                         g_playing_info = NULL;
200                 }
201         }
202
203         MMPlayerStateType player_state;
204         mm_player_get_state(current->player_handle, &player_state);
205
206         SLOG(LOG_DEBUG, get_tag(), "[PLAYER] State changed : state(%d)", player_state);
207
208         int ret = -1;
209         /* destroy player */
210         switch (player_state) {
211                 case MM_PLAYER_STATE_PLAYING:
212                 case MM_PLAYER_STATE_PAUSED:
213                 case MM_PLAYER_STATE_READY:
214                         ret = mm_player_unrealize(current->player_handle);
215                         if (MM_ERROR_NONE != ret) {
216                                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_unrealize() : %x", ret);
217                         } 
218                         /* NO break for destroy */
219
220                 case MM_PLAYER_STATE_NULL:
221                         ret = mm_player_destroy(current->player_handle);
222                         if (MM_ERROR_NONE != ret) {
223                                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_destroy() : %x", ret);
224                         } 
225                         break;
226
227                 default:
228                         break;
229         }
230                 
231         GList *iter = NULL;
232         player_s *data = NULL;
233
234         if (0 < g_list_length(g_player_list)) {
235                 /* Get a first item */
236                 iter = g_list_first(g_player_list);
237
238                 while (NULL != iter) {
239                         /* Get handle data from list */
240                         data = (player_s*)iter->data;
241
242                         if (NULL != data) {
243                                 /* compare uid */
244                                 if (uid == data->uid) {
245                                         g_player_list = g_list_remove_link(g_player_list, iter);                                
246                                         g_free(data);
247                                         break;
248                                 }
249                         }
250                                 
251                         /* Get next item */
252                         iter = g_list_next(iter);
253                 }
254         }
255
256         SLOG(LOG_DEBUG, get_tag(), "[PLAYER Success] Destroy instance");
257
258         return 0;
259 }
260
261 int ttsd_player_play(int uid)
262 {
263         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Player] start play : uid(%d)", uid );
264
265         if (false == g_player_init) {
266                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" );
267                 return -1;
268         }
269
270         if (NULL != g_playing_info) {
271                 if (uid == g_playing_info->uid) {
272                         SECURE_SLOG(LOG_WARN, get_tag(), "[Player WARNING] uid(%d) has already played", g_playing_info->uid); 
273                         return 0;
274                 }
275         }
276
277         /* Check sound queue size */
278         if (0 == ttsd_data_get_sound_data_size(uid)) {
279                 SECURE_SLOG(LOG_WARN, get_tag(), "[Player WARNING] A sound queue of current player(%d) is empty", uid); 
280                 return -1;
281         }
282
283         /* Check uid */
284         player_s* current;
285         current = __player_get_item(uid);
286         if (NULL == current) {
287                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is not valid", uid); 
288                 return -1;
289         }
290
291         MMPlayerStateType player_state;
292         mm_player_get_state(current->player_handle, &player_state);
293
294         SLOG(LOG_DEBUG, get_tag(), "[PLAYER] State changed : state(%d)", player_state);
295
296         switch (player_state) {
297                 case MM_PLAYER_STATE_PLAYING:
298                         SLOG(LOG_WARN, get_tag(), "[Player] Current player is playing. Do not start new sound.");
299                         return 0;
300
301                 case MM_PLAYER_STATE_PAUSED:
302                         SLOG(LOG_WARN, get_tag(), "[Player] Player is paused. Do not start new sound.");
303                         return -1;
304
305                 case MM_PLAYER_STATE_READY:
306                         SLOG(LOG_WARN, get_tag(), "[Player] Player is ready for next play. Do not start new sound.");
307                         return -1;
308
309                 case MM_PLAYER_STATE_NULL:
310                         break;
311
312                 case MM_PLAYER_STATE_NONE:
313                         SLOG(LOG_WARN, get_tag(), "[Player] Player is created. Do not start new sound.");
314                         return -1;
315
316                 default:
317                         return -1;
318         }
319
320         int ret;
321         ret = __set_and_start(current);
322         if (0 != ret) {
323                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail to set or start mm_player");
324                 return ret;
325         }
326
327         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Player] Started play and wait for played callback : uid(%d)", uid);
328
329         return 0;
330 }
331
332 int __ttsd_player_next_play(int uid)
333 {
334         if (false == g_player_init) {
335                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" );
336                 return -1;
337         }
338
339         /* Check uid */
340         player_s* current;
341         current = __player_get_item(uid);
342         if (NULL == current) {
343                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is not valid", uid); 
344                 g_playing_info = NULL;
345                 return -1;
346         }
347
348         if (NULL != g_playing_info) {
349                 if (uid != g_playing_info->uid) {
350                         SECURE_SLOG(LOG_WARN, get_tag(), "[Player WARNING] Current player(%d) is NOT uid(%d)", g_playing_info->uid, uid); 
351                         return 0;
352                 }
353         } else {
354                 SLOG(LOG_WARN, get_tag(), "[Player WARNING] Current player do NOT exist"); 
355                 return -1;
356         }
357
358         MMPlayerStateType player_state;
359         mm_player_get_state(current->player_handle, &player_state);
360
361         SLOG(LOG_DEBUG, get_tag(), "[PLAYER] State changed : state(%d)", player_state);
362
363         int ret = -1;
364         /* stop player */
365         switch (player_state) {
366                 case MM_PLAYER_STATE_PLAYING:
367                 case MM_PLAYER_STATE_PAUSED:
368                 case MM_PLAYER_STATE_READY:
369                         ret = mm_player_unrealize(current->player_handle);
370                         if (MM_ERROR_NONE != ret) {
371                                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_unrealize() : %x", ret);
372                                 return -1;
373                         } 
374                         break;
375
376                 case MM_PLAYER_STATE_NULL:
377                         break;
378
379                 default:
380                         break;
381         }
382
383         /* Check sound queue size */
384         if (0 == ttsd_data_get_sound_data_size(uid)) {
385                 SECURE_SLOG(LOG_WARN, get_tag(), "[Player WARNING] A sound queue of current player(%d) is empty", uid); 
386                 g_playing_info = NULL;
387                 return -1;
388         }
389
390         ret = __set_and_start(current);
391         if (0 != ret) {
392                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail to set or start mm_player");
393                 return ret;
394         }
395
396         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Player] Started play and wait for played callback : uid(%d)", uid);
397
398         return 0;
399 }
400
401
402 int ttsd_player_stop(int uid)
403 {
404         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Player] stop player : uid(%d)", uid );
405
406         if (false == g_player_init) {
407                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" );
408                 return -1;
409         }
410
411         /* Check uid */
412         player_s* current;
413         current = __player_get_item(uid);
414         if (NULL == current) {
415                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is not valid", uid); 
416                 return -1;
417         }
418
419         /* check whether uid is current playing or not */
420         if (NULL != g_playing_info) {
421                 if (uid == g_playing_info->uid) {
422                         /* release current playing info */
423                         g_playing_info = NULL;
424                 }
425         } else {
426                 SLOG(LOG_DEBUG, get_tag(), "[Player] No current playing"); 
427         }
428
429         current->utt_id = -1;
430         current->pause_after_complete = false;
431
432         MMPlayerStateType player_state;
433         mm_player_get_state(current->player_handle, &player_state);
434
435         SLOG(LOG_DEBUG, get_tag(), "[PLAYER] Current state(%d)", player_state);
436
437         int ret = -1;
438         switch (player_state) {
439                 case MM_PLAYER_STATE_PLAYING:
440                 case MM_PLAYER_STATE_PAUSED:
441                 case MM_PLAYER_STATE_READY:
442                         ret = mm_player_unrealize(current->player_handle);
443                         if (MM_ERROR_NONE != ret) {
444                                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_unrealize() : %x", ret);
445                                 return -1;
446                         } 
447                         break;
448
449                 case MM_PLAYER_STATE_NULL:
450                         break;
451                 
452                 default:
453                         break;
454         }
455
456         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Player SUCCESS] Stop player : uid(%d)", uid);
457
458         return 0;
459 }
460
461 int ttsd_player_pause(int uid)
462 {
463         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Player] pause player : uid(%d)", uid );
464
465         if (false == g_player_init) {
466                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" );
467                 return -1;
468         }
469
470         /* Check uid */
471         player_s* current;
472         current = __player_get_item(uid);
473         if (NULL == current) {
474                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] ttsd_player_pause() : uid(%d) is not valid", uid); 
475                 return -1;
476         }
477
478         /* check whether uid is current playing or not */
479         if (NULL != g_playing_info) {
480                 if (uid == g_playing_info->uid) {
481                         /* release current playing info */
482                         g_playing_info = NULL;
483                 } else {
484                         /* error case */
485                 }
486         }
487
488         MMPlayerStateType player_state;
489         mm_player_get_state(current->player_handle, &player_state);
490
491         SLOG(LOG_DEBUG, get_tag(), "[PLAYER] Current state(%d)", player_state);
492
493         int ret = 0;
494         if (MM_PLAYER_STATE_PLAYING == player_state) {
495                 ret = mm_player_pause(current->player_handle);
496                 if (MM_ERROR_NONE != ret) {
497                         SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_pause : %x ", ret);
498                 }
499         } else {
500                 SLOG(LOG_WARN, get_tag(), "[Player WARNING] Current player is NOT 'playing'");
501         }
502         
503
504         return 0;
505 }
506
507 int ttsd_player_resume(int uid)
508 {
509         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Player] Resume player : uid(%d)", uid );
510
511         if (false == g_player_init) {
512                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" );
513                 return -1;
514         }
515
516         /* Check id */
517         player_s* current;
518         current = __player_get_item(uid);
519         if (NULL == current) {
520                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is not valid", uid); 
521                 return -1;
522         }
523
524         /* check current player */
525         if (NULL != g_playing_info)
526                 g_playing_info = NULL;
527
528         
529         MMPlayerStateType player_state;
530         mm_player_get_state(current->player_handle, &player_state);
531
532         SLOG(LOG_DEBUG, get_tag(), "[PLAYER] Current state(%d)", player_state);
533
534         int ret = -1;
535         if (MM_PLAYER_STATE_PAUSED == player_state) {
536                 /* When the 'Paused' state of player after end of play */
537                 if (true == current->pause_after_complete) {
538                         g_playing_info = current;
539
540                         current->pause_after_complete = false;
541                         
542                         /* Current state need load and play */
543                         ret = __ttsd_player_next_play(uid);
544                         if (0 != ret) {
545                                 SLOG(LOG_ERROR, get_tag(), "[player] Fail to next play in resume function");
546                         }
547                 } else {
548                         ret = mm_player_resume(current->player_handle);
549                         if (MM_ERROR_NONE != ret) {
550                                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_resume() : %d", ret);
551                                 return -1;
552                         } else {
553                                 SLOG(LOG_DEBUG, get_tag(), "[Player] Resume player");
554                         }
555
556                         g_playing_info = current;
557                 }
558         } else {
559                 SLOG(LOG_WARN, get_tag(), "[Player WARNING] Current uid is NOT paused state.");
560         }
561
562         return 0;
563 }
564
565 int ttsd_player_get_state(int uid, ttsd_player_state_e* state)
566 {
567         if (false == g_player_init) {
568                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" );
569                 return -1;
570         }
571
572         player_s* current;
573         current = __player_get_item(uid);
574         if (NULL == current) {
575                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is not valid", uid); 
576                 return -1;
577         }
578
579         MMPlayerStateType player_state;
580         mm_player_get_state(current->player_handle, &player_state);
581
582         SLOG(LOG_DEBUG, get_tag(), "[PLAYER] State changed : state(%d)", player_state);
583
584         /* destroy player */
585         switch (player_state) {
586                 case MM_PLAYER_STATE_PLAYING:
587                         *state = TTSD_PLAYER_STATE_PLAYING;
588                         break;
589                 case MM_PLAYER_STATE_PAUSED:
590                         *state = TTSD_PLAYER_STATE_PAUSED;
591                         break;
592                 
593                 case MM_PLAYER_STATE_NULL:
594                         *state = TTSD_PLAYER_STATE_NULL;
595                         break;
596
597                 case MM_PLAYER_STATE_READY:
598                 default:
599                         SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] player state of uid(%d) is not valid", uid); 
600                         return -1;
601                         break;
602         }
603
604         return 0;
605 }
606
607 int ttsd_player_get_current_client()
608 {
609         if (false == g_player_init) {
610                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" );
611                 return -1;
612         }
613
614         if (NULL != g_playing_info) 
615                 return g_playing_info->uid;
616
617         SLOG(LOG_WARN, get_tag(), "[Player WARNING] No current player"); 
618
619         return 0;
620 }
621
622 int ttsd_player_get_current_utterance_id(int uid)
623 {
624         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Player] get current utt id : uid(%d)", uid );
625
626         if (false == g_player_init) {
627                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" );
628                 return -1;
629         }
630
631         /* Check uid */
632         player_s* current;
633         current = __player_get_item(uid);
634         if (NULL == current) {
635                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is not valid", uid); 
636                 return -1;
637         }
638
639         return current->utt_id;
640 }
641
642 int ttsd_player_all_stop()
643 {
644         if (false == g_player_init) {
645                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" );
646                 return -1;
647         }
648
649         g_playing_info = NULL;
650
651         int ret = -1;
652         GList *iter = NULL;
653         player_s *data = NULL;
654
655         if (0 < g_list_length(g_player_list)) {
656                 /* Get a first item */
657                 iter = g_list_first(g_player_list);
658
659                 while (NULL != iter) {
660                         /* Get handle data from list */
661                         data = (player_s*)iter->data;
662
663                         app_state_e state;
664                         if (0 > ttsd_data_get_client_state(data->uid, &state)) {
665                                 SLOG(LOG_ERROR, get_tag(), "[player ERROR] ttsd_player_all_stop : uid is not valid ");
666                                 ttsd_player_destroy_instance(data->uid);
667                                 iter = g_list_next(iter);
668                                 continue;
669                         }
670
671                         if (APP_STATE_PLAYING == state || APP_STATE_PAUSED == state) {
672                                 /* unrealize player */
673                                 ret = mm_player_unrealize(data->player_handle);
674                                 if (MM_ERROR_NONE != ret) {
675                                         SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_unrealize() : %x", ret);
676                                 } 
677
678                                 data->utt_id = -1;
679                                 data->event = TTSP_RESULT_EVENT_FINISH;
680                         }
681                         
682                         /* Get next item */
683                         iter = g_list_next(iter);
684                 }
685         }
686
687         SLOG(LOG_DEBUG, get_tag(), "[Player SUCCESS] player all stop!! ");
688
689         return 0;
690 }
691
692 static Eina_Bool __player_next_play(void *data)
693 {
694         SLOG(LOG_DEBUG, get_tag(), "===== PLAYER NEXT PLAY");
695
696         int* uid = (int*)data;
697
698         if (NULL == uid) {
699                 SLOG(LOG_ERROR, get_tag(), "[PLAYER ERROR] uid is NULL");
700                 SLOG(LOG_DEBUG, get_tag(), "=====");
701                 SLOG(LOG_DEBUG, get_tag(), "  ");
702                 return EINA_FALSE;
703         }
704
705         SECURE_SLOG(LOG_DEBUG, get_tag(), "[PLAYER] uid = %d", *uid);
706         
707         if (0 != __ttsd_player_next_play(*uid)) {
708                 SLOG(LOG_WARN, get_tag(), "[PLAYER WARNING] Fail to play next");
709         }
710
711         free(uid);
712
713         SLOG(LOG_DEBUG, get_tag(), "=====");
714         SLOG(LOG_DEBUG, get_tag(), "  ");
715
716         return EINA_FALSE;
717 }
718
719 static int msg_callback(int message, void *data, void *user_param) 
720 {
721         user_data_s* user_data = NULL;
722
723         user_data = (user_data_s*)user_param;
724
725         if (NULL == user_data) {
726                 SLOG(LOG_ERROR, get_tag(), "[PLAYER ERROR] user_param is NULL");
727                 return -1;
728         }
729
730         int uid = user_data->uid;
731         int utt_id = user_data->utt_id;
732
733         MMMessageParamType *msg = (MMMessageParamType*)data;
734
735         switch (message) {
736         case MM_MESSAGE_ERROR:
737                 {
738                         SLOG(LOG_DEBUG, get_tag(), "===== PLAYER ERROR CALLBACK");
739                         SECURE_SLOG(LOG_ERROR, get_tag(), "[PLAYER ERROR] Info : uid(%d), utt id(%d), error file(%s)", uid, utt_id, user_data->filename);
740
741                         /* send error info */
742                         g_result_callback(PLAYER_ERROR, uid, utt_id);
743
744                         player_s* current;
745                         current = __player_get_item(uid);
746                         if (NULL == current) {
747                                 SECURE_SLOG(LOG_ERROR, get_tag(), "[PLAYER ERROR] uid(%d) is NOT valid ", uid); 
748                         } else {
749                                 current->event = TTSP_RESULT_EVENT_FINISH;
750                         }
751
752                         if (NULL != user_data) 
753                                 g_free(user_data);
754
755                         /* check current player */
756                         if (NULL != g_playing_info) {
757                                 if (uid == g_playing_info->uid) {
758                                         g_playing_info = NULL;
759                                         SECURE_SLOG(LOG_WARN, get_tag(), "[PLAYER] Current Player is NOT uid(%d)", uid);
760                                 }
761                         }
762
763                         SLOG(LOG_DEBUG, get_tag(), "=====");
764                         SLOG(LOG_DEBUG, get_tag(), "  ");
765                 }
766                 break;  /*MM_MESSAGE_ERROR*/
767
768         case MM_MESSAGE_BEGIN_OF_STREAM:
769
770                 break;
771
772         case MM_MESSAGE_END_OF_STREAM:
773                 {
774                         SLOG(LOG_DEBUG, get_tag(), "===== END OF STREAM CALLBACK");
775
776                         if (-1 == remove(user_data->filename)) {
777                                 SECURE_SLOG(LOG_WARN, get_tag(), "[PLAYER WARNING] Fail to remove temp file", user_data->filename); 
778                         }
779
780                         /* Check uid */
781                         player_s* current;
782                         current = __player_get_item(uid);
783                         if (NULL == current) {
784                                 SECURE_SLOG(LOG_ERROR, get_tag(), "[PLAYER ERROR] uid(%d) is NOT valid", uid); 
785                                 if (NULL != g_playing_info) {
786                                         if (uid == g_playing_info->uid) {
787                                                 g_playing_info = NULL;
788                                                 SECURE_SLOG(LOG_WARN, get_tag(), "[PLAYER] Current Player is NOT uid(%d)", uid);
789                                         }
790                                 }
791                                 SLOG(LOG_DEBUG, get_tag(), "=====");
792                                 SLOG(LOG_DEBUG, get_tag(), "  ");
793                                 return -1;
794                         }
795
796                         g_free(user_data);
797
798                         int pid = ttsd_data_get_pid(uid);
799
800                         /* send utterence finish signal */
801                         if (TTSP_RESULT_EVENT_FINISH == current->event) {
802                                 if (0 == ttsdc_send_utt_finish_message(pid, uid, utt_id))
803                                         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Send SUCCESS] Send Utterance Completed Signal : pid(%d), uid(%d), uttid(%d)", pid, uid, utt_id);
804                                 else 
805                                         SECURE_SLOG(LOG_ERROR, get_tag(), "[Send ERROR] Fail to send Utterance Completed Signal : pid(%d), uid(%d), uttid(%d)", pid, uid, utt_id);
806                         }
807
808                         /* for sync problem */
809                         MMPlayerStateType player_state;
810                         mm_player_get_state(current->player_handle, &player_state);
811                         
812                         if (MM_PLAYER_STATE_PAUSED == player_state) {
813                                 /* The current state of player is 'Paused' */
814                                 current->pause_after_complete = true;
815                         } else {
816                                 /* play state */
817                                 int* uid_data = (int*) g_malloc0(sizeof(int));
818                                 *uid_data = uid;
819
820                                 SECURE_SLOG(LOG_DEBUG, get_tag(), "[PLAYER] uid = %d", *uid_data);
821
822                                 ecore_timer_add(0, __player_next_play, (void*)uid_data);
823                         }
824
825                         SLOG(LOG_DEBUG, get_tag(), "=====");
826                         SLOG(LOG_DEBUG, get_tag(), "  ");
827                 }
828                 break;  /*MM_MESSAGE_END_OF_STREAM*/
829
830         case MM_MESSAGE_STATE_CHANGED:
831                 break;
832
833         case MM_MESSAGE_STATE_INTERRUPTED:
834                 if (MM_PLAYER_STATE_PAUSED == msg->state.current) {
835
836                         SLOG(LOG_DEBUG, get_tag(), "===== INTERRUPTED CALLBACK");
837
838                         ttsd_data_set_client_state(uid, APP_STATE_PAUSED);
839
840                         int pid = ttsd_data_get_pid(uid);
841                         /* send message to client about changing state */
842                         ttsdc_send_set_state_message (pid, uid, APP_STATE_PAUSED);
843
844                         SLOG(LOG_DEBUG, get_tag(), "=====");
845                         SLOG(LOG_DEBUG, get_tag(), "  ");
846                 }
847                 break;
848
849         default:
850                 break;
851         }
852
853         return TRUE;
854 }
855
856 player_s* __player_get_item(int uid)
857 {
858         GList *iter = NULL;
859         player_s *data = NULL;
860
861         if (0 < g_list_length(g_player_list)) {
862                 /* Get a first item */
863                 iter = g_list_first(g_player_list);
864
865                 while (NULL != iter) {
866                         /* Get handle data from list */
867                         data = (player_s*)iter->data;
868
869                         /* compare uid */
870                         if (uid == data->uid)   
871                                 return data;
872
873                         /* Get next item */
874                         iter = g_list_next(iter);
875                 }
876         }
877
878         return NULL;
879 }
880
881 int __save_file(int uid, int index, sound_data_s data, char** filename)
882 {
883         char postfix[5];
884         memset(postfix, '\0', 5);
885
886         switch (data.audio_type) {
887         case TTSP_AUDIO_TYPE_RAW:
888         case TTSP_AUDIO_TYPE_WAV:
889                 strcpy(postfix, "wav");
890                 break;
891         case TTSP_AUDIO_TYPE_MP3:
892                 strcpy(postfix, "mp3");
893                 break;
894         case TTSP_AUDIO_TYPE_AMR:
895                 strcpy(postfix, "amr");
896                 break;
897         default:
898                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Audio type(%d) is NOT valid", data.audio_type); 
899                 return -1;
900         }
901
902         /* make filename to save */
903         char* temp;
904         temp = (char*)g_malloc0(sizeof(char) * FILE_PATH_SIZE);
905         if (NULL == temp) {
906                 SLOG(LOG_ERROR, get_tag(), "[Player Error] make buf is failed");
907                 return -1;
908         }
909
910         int ret = snprintf(temp, FILE_PATH_SIZE, "%s/ttstemp%d_%d.%s", TEMP_FILE_PATH, uid, index, postfix);
911
912         if (0 >= ret) {
913                 if (NULL != temp)
914                         g_free(temp);
915                 return -1;
916         }
917
918         FILE* fp;
919         fp = fopen(temp, "wb");
920
921         if (fp == NULL) {
922                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] temp file open error");
923                 if (NULL != temp)
924                         g_free(temp);
925                 return -1;
926         }
927
928         if (data.audio_type == TTSP_AUDIO_TYPE_RAW) {
929                 WavHeader header;
930                 if (0 != __init_wave_header(&header, data.data_size, data.rate, data.channels)) {
931                         fclose(fp);
932                         if (NULL != temp)
933                                 g_free(temp);
934                         return -1;
935                 }
936
937                 if (0 >= fwrite(&header, sizeof(WavHeader), 1, fp)) {
938                         SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail to write wav header to file");
939                         fclose(fp);
940                         if (NULL != temp)
941                                 g_free(temp);
942                         return -1;
943                 }
944         }
945
946         int size = fwrite(data.data, data.data_size, 1,  fp);
947         if (size <= 0) {
948                 size = fwrite("0000000000", DEFAULT_FILE_SIZE, 1,  fp);
949                 if (size <= 0) {
950                         SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail to write date");
951                         fclose(fp);
952                         if (NULL != temp)
953                                 g_free(temp);
954                         return -1;
955                 }       
956         } 
957
958         fclose(fp);
959         *filename = temp;
960         
961         SLOG(LOG_DEBUG, get_tag(), " ");
962         SECURE_SLOG(LOG_DEBUG, get_tag(), "Filepath : %s ", *filename);
963         SECURE_SLOG(LOG_DEBUG, get_tag(), "Header : Data size(%d), Sample rate(%d), Channel(%d) ", data.data_size, data.rate, data.channels);
964
965         return 0;
966 }
967
968 int __init_wave_header (WavHeader* hdr, size_t nsamples, size_t sampling_rate, int channel)
969 {
970         if (hdr == NULL || sampling_rate <= 0 || channel <= 0) {
971                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] __init_wave_header : input parameter invalid");
972                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] hdr : %p", hdr);
973                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] nsample : %d", nsamples);
974                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] sampling_rate : %", sampling_rate);
975                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] channel : %", channel);
976                 return TTSD_ERROR_INVALID_PARAMETER;
977         }
978
979         size_t bytesize = DEFAULT_FILE_SIZE;
980
981         if (0 < nsamples) {
982                 bytesize = nsamples;    
983         } 
984
985         /* NOT include \0(NULL) */
986         strncpy(hdr->riff, "RIFF", 4);  
987         hdr->file_size = (int)(bytesize  + 36);
988         strncpy(hdr->wave, "WAVE", 4);
989         strncpy(hdr->fmt, "fmt ", 4);   /* fmt + space */
990         hdr->header_size = 16;
991         hdr->sample_format = 1;         /* WAVE_FORMAT_PCM */
992         hdr->n_channels = channel;
993         hdr->sample_rate = (int)(sampling_rate);
994         hdr->bytes_per_second = (int)sampling_rate * sizeof(short);
995         hdr->block_align =  sizeof(short);
996         hdr->bits_per_sample = sizeof(short)*8;
997         strncpy(hdr->data, "data", 4);  
998         hdr->data_size = (int)bytesize;
999
1000         return 0;
1001 }
1002
1003 int __set_and_start(player_s* player)
1004 {
1005         /* get sound data */
1006         sound_data_s wdata;
1007         if (0 != ttsd_data_get_sound_data(player->uid, &wdata)) {
1008                 SECURE_SLOG(LOG_WARN, get_tag(), "[Player WARNING] A sound queue of current player(%d) is empty", player->uid); 
1009                 return -1;
1010         }
1011
1012         g_index++;
1013         if (10000 <= g_index)   {
1014                 g_index = 1;
1015         }
1016
1017         int ret;
1018
1019         /* make sound file for mmplayer */
1020         char* sound_file = NULL;
1021         ret = __save_file(player->uid, g_index, wdata, &sound_file);
1022         if (0 != ret || NULL == sound_file) {
1023                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail to make sound file");
1024                 return -1;
1025         }
1026         
1027         user_data_s* user_data = (user_data_s*)g_malloc0(sizeof(user_data_s));
1028         user_data->uid = player->uid;
1029         user_data->utt_id = wdata.utt_id;
1030         user_data->event = wdata.event;
1031         memset(user_data->filename, 0, TEMP_FILE_MAX); 
1032         strncpy( user_data->filename, sound_file, strlen(sound_file) );
1033
1034         SECURE_SLOG(LOG_DEBUG, get_tag(), "Info : uid(%d), utt(%d), filename(%s) , event(%d)", 
1035                 user_data->uid, user_data->utt_id, user_data->filename, user_data->event);
1036         SLOG(LOG_DEBUG, get_tag(), " ");
1037
1038         
1039         /* set callback func */
1040         ret = mm_player_set_message_callback(player->player_handle, msg_callback, (void*)user_data);
1041         if (MM_ERROR_NONE != ret) {
1042                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail mm_player_set_message_callback() : %x ", ret);
1043                 if (NULL != user_data)  g_free(user_data);
1044                 return -1;
1045         }
1046
1047         /* set playing info to mm player */
1048         char* err_attr_name = NULL;
1049
1050         if (0 != access(sound_file, R_OK)) {
1051                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail to read sound file (%s)", sound_file);
1052                 if (NULL != user_data)  g_free(user_data);
1053                 return -1;
1054         }
1055
1056         ret = mm_player_set_attribute(player->player_handle, &err_attr_name,
1057                 "profile_uri", sound_file , strlen(sound_file) + 1,
1058                 "sound_volume_type", MM_SOUND_VOLUME_TYPE_MEDIA,
1059                 "sound_route", MM_AUDIOROUTE_PLAYBACK_NORMAL,
1060                 NULL );
1061
1062         if (MM_ERROR_NONE != ret) {
1063                 if (NULL != err_attr_name) {
1064                         SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail mm_player_set_attribute() : msg(%s), result(%x) ", err_attr_name, ret);
1065                 }
1066                 if (NULL != user_data)  g_free(user_data);
1067                 return -1;
1068         }
1069
1070         if (TTSD_MODE_DEFAULT != ttsd_get_mode()) {
1071                 ret = mm_player_ignore_session(player->player_handle);
1072                 if (MM_ERROR_NONE != ret) {
1073                         SLOG(LOG_WARN, get_tag(), "[Player WARNING] fail mm_player_ignore_session() : %x", ret);
1074                 }
1075         }
1076         
1077         /* realize and start mm player */ 
1078         ret = mm_player_realize(player->player_handle);
1079         if (MM_ERROR_NONE != ret) {
1080                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_realize() : %x", ret);
1081
1082                 if (NULL != user_data)  g_free(user_data);
1083                 return -2;
1084         }
1085
1086         ret = mm_player_start(player->player_handle);
1087         if (MM_ERROR_NONE != ret) {
1088                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_start() : %x", ret);
1089                 mm_player_unrealize(player->player_handle);
1090
1091                 int reason;
1092                 if (MM_ERROR_POLICY_BLOCKED == ret) {
1093                         SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Blocked to start player by policy : %x", ret);
1094                         reason = TTSD_ERROR_AUDIO_POLICY_BLOCKED;
1095                 } else {
1096                         reason = TTSD_ERROR_OPERATION_FAILED;
1097                 }
1098
1099                 if (NULL != user_data) {
1100                         ttsd_data_set_error_data(user_data->uid, user_data->utt_id, reason);
1101                         g_free(user_data);
1102                 }
1103                 return -3;
1104         }
1105
1106         /* If wdata's event is 'start', current wdata is first data of engine for synthesis. 
1107          * If wdata's event is 'finish', player should check previous event to know whether this wdata is first or not.
1108          * When previous wdata's event is 'finish' and current wdata's event is 'finish', 
1109          * the player should send utt started event. 
1110          */
1111         if (TTSP_RESULT_EVENT_START == wdata.event ||
1112             (TTSP_RESULT_EVENT_FINISH == player->event && TTSP_RESULT_EVENT_FINISH == wdata.event)) {
1113                 int pid;
1114                 pid = ttsd_data_get_pid(player->uid);
1115
1116                 /* send utterance start message */
1117                 if (0 != ttsdc_send_utt_start_message(pid, player->uid, wdata.utt_id)) {
1118                         SECURE_SLOG(LOG_ERROR, get_tag(), "[Send ERROR] Fail to send Utterance Start Signal : pid(%d), uid(%d), uttid(%d)", pid, player->uid, wdata.utt_id);
1119                 }
1120         } else {
1121                 SLOG(LOG_DEBUG, get_tag(), "[PLAYER] Don't need to send Utterance Start Signal");
1122         }
1123
1124         g_playing_info = player;
1125
1126         if (NULL != sound_file) 
1127                 g_free(sound_file);
1128         if (NULL != wdata.data) 
1129                 g_free(wdata.data);
1130
1131         return 0;
1132 }
1133
1134