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