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