Fix player bug
[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         }
325
326         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Player] Started play and wait for played callback : uid(%d)", uid);
327
328         return 0;
329 }
330
331 int __ttsd_player_next_play(int uid)
332 {
333         if (false == g_player_init) {
334                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" );
335                 return -1;
336         }
337
338         /* Check uid */
339         player_s* current;
340         current = __player_get_item(uid);
341         if (NULL == current) {
342                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is not valid", uid); 
343                 g_playing_info = NULL;
344                 return -1;
345         }
346
347         if (NULL != g_playing_info) {
348                 if (uid != g_playing_info->uid) {
349                         SECURE_SLOG(LOG_WARN, get_tag(), "[Player WARNING] Current player(%d) is NOT uid(%d)", g_playing_info->uid, uid); 
350                         return 0;
351                 }
352         } else {
353                 SLOG(LOG_WARN, get_tag(), "[Player WARNING] Current player do NOT exist"); 
354                 return -1;
355         }
356
357         MMPlayerStateType player_state;
358         mm_player_get_state(current->player_handle, &player_state);
359
360         SLOG(LOG_DEBUG, get_tag(), "[PLAYER] State changed : state(%d)", player_state);
361
362         int ret = -1;
363         /* stop player */
364         switch (player_state) {
365                 case MM_PLAYER_STATE_PLAYING:
366                 case MM_PLAYER_STATE_PAUSED:
367                 case MM_PLAYER_STATE_READY:
368                         ret = mm_player_unrealize(current->player_handle);
369                         if (MM_ERROR_NONE != ret) {
370                                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_unrealize() : %x", ret);
371                                 return -1;
372                         } 
373                         break;
374
375                 case MM_PLAYER_STATE_NULL:
376                         break;
377
378                 default:
379                         break;
380         }
381
382         /* Check sound queue size */
383         if (0 == ttsd_data_get_sound_data_size(uid)) {
384                 SECURE_SLOG(LOG_WARN, get_tag(), "[Player WARNING] A sound queue of current player(%d) is empty", uid); 
385                 g_playing_info = NULL;
386                 return -1;
387         }
388
389         ret = __set_and_start(current);
390         if (0 != ret) {
391                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail to set or start mm_player");
392         }
393
394         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Player] Started play and wait for played callback : uid(%d)", uid);
395
396         return 0;
397 }
398
399
400 int ttsd_player_stop(int uid)
401 {
402         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Player] stop player : uid(%d)", uid );
403
404         if (false == g_player_init) {
405                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" );
406                 return -1;
407         }
408
409         /* Check uid */
410         player_s* current;
411         current = __player_get_item(uid);
412         if (NULL == current) {
413                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is not valid", uid); 
414                 return -1;
415         }
416
417         /* check whether uid is current playing or not */
418         if (NULL != g_playing_info) {
419                 if (uid == g_playing_info->uid) {
420                         /* release current playing info */
421                         g_playing_info = NULL;
422                 }
423         } else {
424                 SLOG(LOG_DEBUG, get_tag(), "[Player] No current playing"); 
425         }
426
427         current->utt_id = -1;
428         current->pause_after_complete = false;
429
430         MMPlayerStateType player_state;
431         mm_player_get_state(current->player_handle, &player_state);
432
433         SLOG(LOG_DEBUG, get_tag(), "[PLAYER] Current state(%d)", player_state);
434
435         int ret = -1;
436         switch (player_state) {
437                 case MM_PLAYER_STATE_PLAYING:
438                 case MM_PLAYER_STATE_PAUSED:
439                 case MM_PLAYER_STATE_READY:
440                         ret = mm_player_unrealize(current->player_handle);
441                         if (MM_ERROR_NONE != ret) {
442                                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_unrealize() : %x", ret);
443                                 return -1;
444                         } 
445                         break;
446
447                 case MM_PLAYER_STATE_NULL:
448                         break;
449                 
450                 default:
451                         break;
452         }
453
454         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Player SUCCESS] Stop player : uid(%d)", uid);
455
456         return 0;
457 }
458
459 int ttsd_player_pause(int uid)
460 {
461         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Player] pause player : uid(%d)", uid );
462
463         if (false == g_player_init) {
464                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" );
465                 return -1;
466         }
467
468         /* Check uid */
469         player_s* current;
470         current = __player_get_item(uid);
471         if (NULL == current) {
472                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] ttsd_player_pause() : uid(%d) is not valid", uid); 
473                 return -1;
474         }
475
476         /* check whether uid is current playing or not */
477         if (NULL != g_playing_info) {
478                 if (uid == g_playing_info->uid) {
479                         /* release current playing info */
480                         g_playing_info = NULL;
481                 } else {
482                         /* error case */
483                 }
484         }
485
486         MMPlayerStateType player_state;
487         mm_player_get_state(current->player_handle, &player_state);
488
489         SLOG(LOG_DEBUG, get_tag(), "[PLAYER] Current state(%d)", player_state);
490
491         int ret = 0;
492         if (MM_PLAYER_STATE_PLAYING == player_state) {
493                 ret = mm_player_pause(current->player_handle);
494                 if (MM_ERROR_NONE != ret) {
495                         SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_pause : %x ", ret);
496                 }
497         } else {
498                 SLOG(LOG_WARN, get_tag(), "[Player WARNING] Current player is NOT 'playing'");
499         }
500         
501
502         return 0;
503 }
504
505 int ttsd_player_resume(int uid)
506 {
507         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Player] Resume player : uid(%d)", uid );
508
509         if (false == g_player_init) {
510                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" );
511                 return -1;
512         }
513
514         /* Check id */
515         player_s* current;
516         current = __player_get_item(uid);
517         if (NULL == current) {
518                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is not valid", uid); 
519                 return -1;
520         }
521
522         /* check current player */
523         if (NULL != g_playing_info)
524                 g_playing_info = NULL;
525
526         
527         MMPlayerStateType player_state;
528         mm_player_get_state(current->player_handle, &player_state);
529
530         SLOG(LOG_DEBUG, get_tag(), "[PLAYER] Current state(%d)", player_state);
531
532         int ret = -1;
533         if (MM_PLAYER_STATE_PAUSED == player_state) {
534                 /* When the 'Paused' state of player after end of play */
535                 if (true == current->pause_after_complete) {
536                         g_playing_info = current;
537
538                         current->pause_after_complete = false;
539                         
540                         /* Current state need load and play */
541                         ret = __ttsd_player_next_play(uid);
542                         if (0 != ret) {
543                                 SLOG(LOG_ERROR, get_tag(), "[player] Fail to next play in resume function");
544                         }
545                 } else {
546                         ret = mm_player_resume(current->player_handle);
547                         if (MM_ERROR_NONE != ret) {
548                                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_resume() : %d", ret);
549                                 return -1;
550                         } else {
551                                 SLOG(LOG_DEBUG, get_tag(), "[Player] Resume player");
552                         }
553
554                         g_playing_info = current;
555                 }
556         } else {
557                 SLOG(LOG_WARN, get_tag(), "[Player WARNING] Current uid is NOT paused state.");
558         }
559
560         return 0;
561 }
562
563 int ttsd_player_get_state(int uid, ttsd_player_state_e* state)
564 {
565         if (false == g_player_init) {
566                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" );
567                 return -1;
568         }
569
570         player_s* current;
571         current = __player_get_item(uid);
572         if (NULL == current) {
573                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is not valid", uid); 
574                 return -1;
575         }
576
577         MMPlayerStateType player_state;
578         mm_player_get_state(current->player_handle, &player_state);
579
580         SLOG(LOG_DEBUG, get_tag(), "[PLAYER] State changed : state(%d)", player_state);
581
582         /* destroy player */
583         switch (player_state) {
584                 case MM_PLAYER_STATE_PLAYING:
585                         *state = TTSD_PLAYER_STATE_PLAYING;
586                         break;
587                 case MM_PLAYER_STATE_PAUSED:
588                         *state = TTSD_PLAYER_STATE_PAUSED;
589                         break;
590                 
591                 case MM_PLAYER_STATE_NULL:
592                         *state = TTSD_PLAYER_STATE_NULL;
593                         break;
594
595                 case MM_PLAYER_STATE_READY:
596                 default:
597                         SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] player state of uid(%d) is not valid", uid); 
598                         return -1;
599                         break;
600         }
601
602         return 0;
603 }
604
605 int ttsd_player_get_current_client()
606 {
607         if (false == g_player_init) {
608                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" );
609                 return -1;
610         }
611
612         if (NULL != g_playing_info) 
613                 return g_playing_info->uid;
614
615         SLOG(LOG_WARN, get_tag(), "[Player WARNING] No current player"); 
616
617         return 0;
618 }
619
620 int ttsd_player_get_current_utterance_id(int uid)
621 {
622         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Player] get current utt id : uid(%d)", uid );
623
624         if (false == g_player_init) {
625                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" );
626                 return -1;
627         }
628
629         /* Check uid */
630         player_s* current;
631         current = __player_get_item(uid);
632         if (NULL == current) {
633                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is not valid", uid); 
634                 return -1;
635         }
636
637         return current->utt_id;
638 }
639
640 int ttsd_player_all_stop()
641 {
642         if (false == g_player_init) {
643                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" );
644                 return -1;
645         }
646
647         g_playing_info = NULL;
648
649         int ret = -1;
650         GList *iter = NULL;
651         player_s *data = NULL;
652
653         if (0 < g_list_length(g_player_list)) {
654                 /* Get a first item */
655                 iter = g_list_first(g_player_list);
656
657                 while (NULL != iter) {
658                         /* Get handle data from list */
659                         data = (player_s*)iter->data;
660
661                         app_state_e state;
662                         if (0 > ttsd_data_get_client_state(data->uid, &state)) {
663                                 SLOG(LOG_ERROR, get_tag(), "[player ERROR] ttsd_player_all_stop : uid is not valid ");
664                                 ttsd_player_destroy_instance(data->uid);
665                                 iter = g_list_next(iter);
666                                 continue;
667                         }
668
669                         if (APP_STATE_PLAYING == state || APP_STATE_PAUSED == state) {
670                                 /* unrealize player */
671                                 ret = mm_player_unrealize(data->player_handle);
672                                 if (MM_ERROR_NONE != ret) {
673                                         SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_unrealize() : %x", ret);
674                                 } 
675
676                                 data->utt_id = -1;
677                                 data->event = TTSP_RESULT_EVENT_FINISH;
678                         }
679                         
680                         /* Get next item */
681                         iter = g_list_next(iter);
682                 }
683         }
684
685         SLOG(LOG_DEBUG, get_tag(), "[Player SUCCESS] player all stop!! ");
686
687         return 0;
688 }
689
690 static Eina_Bool __player_next_play(void *data)
691 {
692         SLOG(LOG_DEBUG, get_tag(), "===== PLAYER NEXT PLAY");
693
694         int* uid = (int*)data;
695
696         if (NULL == uid) {
697                 SLOG(LOG_ERROR, get_tag(), "[PLAYER ERROR] uid is NULL");
698                 SLOG(LOG_DEBUG, get_tag(), "=====");
699                 SLOG(LOG_DEBUG, get_tag(), "  ");
700                 return EINA_FALSE;
701         }
702
703         SECURE_SLOG(LOG_DEBUG, get_tag(), "[PLAYER] uid = %d", *uid);
704         
705         if (0 != __ttsd_player_next_play(*uid)) {
706                 SLOG(LOG_WARN, get_tag(), "[PLAYER WARNING] Fail to play next");
707         }
708
709         free(uid);
710
711         SLOG(LOG_DEBUG, get_tag(), "=====");
712         SLOG(LOG_DEBUG, get_tag(), "  ");
713
714         return EINA_FALSE;
715 }
716
717 static int msg_callback(int message, void *data, void *user_param) 
718 {
719         user_data_s* user_data = NULL;
720
721         user_data = (user_data_s*)user_param;
722
723         if (NULL == user_data) {
724                 SLOG(LOG_ERROR, get_tag(), "[PLAYER ERROR] user_param is NULL");
725                 return -1;
726         }
727
728         int uid = user_data->uid;
729         int utt_id = user_data->utt_id;
730
731         MMMessageParamType *msg = (MMMessageParamType*)data;
732
733         switch (message) {
734         case MM_MESSAGE_ERROR:
735                 {
736                         SLOG(LOG_DEBUG, get_tag(), "===== PLAYER ERROR CALLBACK");
737                         SECURE_SLOG(LOG_ERROR, get_tag(), "[PLAYER ERROR] Info : uid(%d), utt id(%d), error file(%s)", uid, utt_id, user_data->filename);
738
739                         /* send error info */
740                         g_result_callback(PLAYER_ERROR, uid, utt_id);
741
742                         player_s* current;
743                         current = __player_get_item(uid);
744                         if (NULL == current) {
745                                 SECURE_SLOG(LOG_ERROR, get_tag(), "[PLAYER ERROR] uid(%d) is NOT valid ", uid); 
746                         } else {
747                                 current->event = TTSP_RESULT_EVENT_FINISH;
748                         }
749
750                         if (NULL != user_data) 
751                                 g_free(user_data);
752
753                         /* check current player */
754                         if (NULL != g_playing_info) {
755                                 if (uid == g_playing_info->uid) {
756                                         g_playing_info = NULL;
757                                         SECURE_SLOG(LOG_WARN, get_tag(), "[PLAYER] Current Player is NOT uid(%d)", uid);
758                                 }
759                         }
760
761                         SLOG(LOG_DEBUG, get_tag(), "=====");
762                         SLOG(LOG_DEBUG, get_tag(), "  ");
763                 }
764                 break;  /*MM_MESSAGE_ERROR*/
765
766         case MM_MESSAGE_BEGIN_OF_STREAM:
767
768                 break;
769
770         case MM_MESSAGE_END_OF_STREAM:
771                 {
772                         SLOG(LOG_DEBUG, get_tag(), "===== END OF STREAM CALLBACK");
773
774                         if (-1 == remove(user_data->filename)) {
775                                 SECURE_SLOG(LOG_WARN, get_tag(), "[PLAYER WARNING] Fail to remove temp file", user_data->filename); 
776                         }
777
778                         /* Check uid */
779                         player_s* current;
780                         current = __player_get_item(uid);
781                         if (NULL == current) {
782                                 SECURE_SLOG(LOG_ERROR, get_tag(), "[PLAYER ERROR] uid(%d) is NOT valid", uid); 
783                                 if (NULL != g_playing_info) {
784                                         if (uid == g_playing_info->uid) {
785                                                 g_playing_info = NULL;
786                                                 SECURE_SLOG(LOG_WARN, get_tag(), "[PLAYER] Current Player is NOT uid(%d)", uid);
787                                         }
788                                 }
789                                 SLOG(LOG_DEBUG, get_tag(), "=====");
790                                 SLOG(LOG_DEBUG, get_tag(), "  ");
791                                 return -1;
792                         }
793
794                         g_free(user_data);
795
796                         int pid = ttsd_data_get_pid(uid);
797
798                         /* send utterence finish signal */
799                         if (TTSP_RESULT_EVENT_FINISH == current->event) {
800                                 if (0 == ttsdc_send_utt_finish_message(pid, uid, utt_id))
801                                         SECURE_SLOG(LOG_DEBUG, get_tag(), "[Send SUCCESS] Send Utterance Completed Signal : pid(%d), uid(%d), uttid(%d)", pid, uid, utt_id);
802                                 else 
803                                         SECURE_SLOG(LOG_ERROR, get_tag(), "[Send ERROR] Fail to send Utterance Completed Signal : pid(%d), uid(%d), uttid(%d)", pid, uid, utt_id);
804                         }
805
806                         /* for sync problem */
807                         MMPlayerStateType player_state;
808                         mm_player_get_state(current->player_handle, &player_state);
809                         
810                         if (MM_PLAYER_STATE_PAUSED == player_state) {
811                                 /* The current state of player is 'Paused' */
812                                 current->pause_after_complete = true;
813                         } else {
814                                 /* play state */
815                                 int* uid_data = (int*) g_malloc0(sizeof(int));
816                                 *uid_data = uid;
817
818                                 SECURE_SLOG(LOG_DEBUG, get_tag(), "[PLAYER] uid = %d", *uid_data);
819
820                                 ecore_timer_add(0, __player_next_play, (void*)uid_data);
821                         }
822
823                         SLOG(LOG_DEBUG, get_tag(), "=====");
824                         SLOG(LOG_DEBUG, get_tag(), "  ");
825                 }
826                 break;  /*MM_MESSAGE_END_OF_STREAM*/
827
828         case MM_MESSAGE_STATE_CHANGED:
829                 break;
830
831         case MM_MESSAGE_STATE_INTERRUPTED:
832                 if (MM_PLAYER_STATE_PAUSED == msg->state.current) {
833
834                         SLOG(LOG_DEBUG, get_tag(), "===== INTERRUPTED CALLBACK");
835
836                         ttsd_data_set_client_state(uid, APP_STATE_PAUSED);
837
838                         int pid = ttsd_data_get_pid(uid);
839                         /* send message to client about changing state */
840                         ttsdc_send_set_state_message (pid, uid, APP_STATE_PAUSED);
841
842                         SLOG(LOG_DEBUG, get_tag(), "=====");
843                         SLOG(LOG_DEBUG, get_tag(), "  ");
844                 }
845                 break;
846
847         default:
848                 break;
849         }
850
851         return TRUE;
852 }
853
854 player_s* __player_get_item(int uid)
855 {
856         GList *iter = NULL;
857         player_s *data = NULL;
858
859         if (0 < g_list_length(g_player_list)) {
860                 /* Get a first item */
861                 iter = g_list_first(g_player_list);
862
863                 while (NULL != iter) {
864                         /* Get handle data from list */
865                         data = (player_s*)iter->data;
866
867                         /* compare uid */
868                         if (uid == data->uid)   
869                                 return data;
870
871                         /* Get next item */
872                         iter = g_list_next(iter);
873                 }
874         }
875
876         return NULL;
877 }
878
879 int __save_file(int uid, int index, sound_data_s data, char** filename)
880 {
881         char postfix[5];
882         memset(postfix, '\0', 5);
883
884         switch (data.audio_type) {
885         case TTSP_AUDIO_TYPE_RAW:
886         case TTSP_AUDIO_TYPE_WAV:
887                 strcpy(postfix, "wav");
888                 break;
889         case TTSP_AUDIO_TYPE_MP3:
890                 strcpy(postfix, "mp3");
891                 break;
892         case TTSP_AUDIO_TYPE_AMR:
893                 strcpy(postfix, "amr");
894                 break;
895         default:
896                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Audio type(%d) is NOT valid", data.audio_type); 
897                 return -1;
898         }
899
900         /* make filename to save */
901         char* temp;
902         temp = (char*)g_malloc0(sizeof(char) * FILE_PATH_SIZE);
903         if (NULL == temp) {
904                 SLOG(LOG_ERROR, get_tag(), "[Player Error] make buf is failed");
905                 return -1;
906         }
907
908         int ret = snprintf(temp, FILE_PATH_SIZE, "%s/ttstemp%d_%d.%s", TEMP_FILE_PATH, uid, index, postfix);
909
910         if (0 >= ret) {
911                 if (NULL != temp)
912                         g_free(temp);
913                 return -1;
914         }
915
916         FILE* fp;
917         fp = fopen(temp, "wb");
918
919         if (fp == NULL) {
920                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] temp file open error");
921                 if (NULL != temp)
922                         g_free(temp);
923                 return -1;
924         }
925
926         if (data.audio_type == TTSP_AUDIO_TYPE_RAW) {
927                 WavHeader header;
928                 if (0 != __init_wave_header(&header, data.data_size, data.rate, data.channels)) {
929                         fclose(fp);
930                         if (NULL != temp)
931                                 g_free(temp);
932                         return -1;
933                 }
934
935                 if (0 >= fwrite(&header, sizeof(WavHeader), 1, fp)) {
936                         SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail to write wav header to file");
937                         fclose(fp);
938                         if (NULL != temp)
939                                 g_free(temp);
940                         return -1;
941                 }
942         }
943
944         int size = fwrite(data.data, data.data_size, 1,  fp);
945         if (size <= 0) {
946                 size = fwrite("0000000000", DEFAULT_FILE_SIZE, 1,  fp);
947                 if (size <= 0) {
948                         SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail to write date");
949                         fclose(fp);
950                         if (NULL != temp)
951                                 g_free(temp);
952                         return -1;
953                 }       
954         } 
955
956         fclose(fp);
957         *filename = temp;
958         
959         SLOG(LOG_DEBUG, get_tag(), " ");
960         SECURE_SLOG(LOG_DEBUG, get_tag(), "Filepath : %s ", *filename);
961         SECURE_SLOG(LOG_DEBUG, get_tag(), "Header : Data size(%d), Sample rate(%d), Channel(%d) ", data.data_size, data.rate, data.channels);
962
963         return 0;
964 }
965
966 int __init_wave_header (WavHeader* hdr, size_t nsamples, size_t sampling_rate, int channel)
967 {
968         if (hdr == NULL || sampling_rate <= 0 || channel <= 0) {
969                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] __init_wave_header : input parameter invalid");
970                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] hdr : %p", hdr);
971                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] nsample : %d", nsamples);
972                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] sampling_rate : %", sampling_rate);
973                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] channel : %", channel);
974                 return TTSD_ERROR_INVALID_PARAMETER;
975         }
976
977         size_t bytesize = DEFAULT_FILE_SIZE;
978
979         if (0 < nsamples) {
980                 bytesize = nsamples;    
981         } 
982
983         /* NOT include \0(NULL) */
984         strncpy(hdr->riff, "RIFF", 4);  
985         hdr->file_size = (int)(bytesize  + 36);
986         strncpy(hdr->wave, "WAVE", 4);
987         strncpy(hdr->fmt, "fmt ", 4);   /* fmt + space */
988         hdr->header_size = 16;
989         hdr->sample_format = 1;         /* WAVE_FORMAT_PCM */
990         hdr->n_channels = channel;
991         hdr->sample_rate = (int)(sampling_rate);
992         hdr->bytes_per_second = (int)sampling_rate * sizeof(short);
993         hdr->block_align =  sizeof(short);
994         hdr->bits_per_sample = sizeof(short)*8;
995         strncpy(hdr->data, "data", 4);  
996         hdr->data_size = (int)bytesize;
997
998         return 0;
999 }
1000
1001 int __set_and_start(player_s* player)
1002 {
1003         /* get sound data */
1004         sound_data_s wdata;
1005         if (0 != ttsd_data_get_sound_data(player->uid, &wdata)) {
1006                 SECURE_SLOG(LOG_WARN, get_tag(), "[Player WARNING] A sound queue of current player(%d) is empty", player->uid); 
1007                 return -1;
1008         }
1009
1010         g_index++;
1011         if (10000 <= g_index)   {
1012                 g_index = 1;
1013         }
1014
1015         int ret;
1016
1017         /* make sound file for mmplayer */
1018         char* sound_file = NULL;
1019         ret = __save_file(player->uid, g_index, wdata, &sound_file);
1020         if (0 != ret || NULL == sound_file) {
1021                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail to make sound file");
1022                 return -1;
1023         }
1024         
1025         user_data_s* user_data = (user_data_s*)g_malloc0(sizeof(user_data_s));
1026         user_data->uid = player->uid;
1027         user_data->utt_id = wdata.utt_id;
1028         user_data->event = wdata.event;
1029         memset(user_data->filename, 0, TEMP_FILE_MAX); 
1030         strncpy( user_data->filename, sound_file, strlen(sound_file) );
1031
1032         SECURE_SLOG(LOG_DEBUG, get_tag(), "Info : uid(%d), utt(%d), filename(%s) , event(%d)", 
1033                 user_data->uid, user_data->utt_id, user_data->filename, user_data->event);
1034         SLOG(LOG_DEBUG, get_tag(), " ");
1035
1036         
1037         /* set callback func */
1038         ret = mm_player_set_message_callback(player->player_handle, msg_callback, (void*)user_data);
1039         if (MM_ERROR_NONE != ret) {
1040                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail mm_player_set_message_callback() : %x ", ret);
1041                 return -1;
1042         }
1043
1044         /* set playing info to mm player */
1045         char* err_attr_name = NULL;
1046
1047         if (0 != access(sound_file, R_OK)) {
1048                 SECURE_SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail to read sound file (%s)", sound_file);
1049                 return -1;
1050         }
1051         
1052         ret = mm_player_set_attribute(player->player_handle, &err_attr_name,
1053                 "profile_uri", sound_file , strlen(sound_file) + 1,
1054                 "sound_volume_type", MM_SOUND_VOLUME_TYPE_MEDIA,
1055                 "sound_route", MM_AUDIOROUTE_PLAYBACK_NORMAL,
1056                 NULL );
1057
1058         if (MM_ERROR_NONE != ret) {
1059                 if (NULL != err_attr_name) {
1060                         SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail mm_player_set_attribute() : msg(%s), result(%x) ", err_attr_name, ret);
1061                 }
1062                 return -1;
1063         }
1064
1065         if (TTSD_MODE_DEFAULT != ttsd_get_mode()) {
1066                 ret = mm_player_ignore_session(player->player_handle);
1067                 if (MM_ERROR_NONE != ret) {
1068                         SLOG(LOG_WARN, get_tag(), "[Player WARNING] fail mm_player_ignore_session() : %x", ret);
1069                 }
1070         }
1071         
1072         /* realize and start mm player */ 
1073         ret = mm_player_realize(player->player_handle);
1074         if (MM_ERROR_NONE != ret) {
1075                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_realize() : %x", ret);
1076                 return -2;
1077         }
1078
1079         ret = mm_player_start(player->player_handle);
1080         if (MM_ERROR_NONE != ret) {
1081                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_start() : %x", ret);
1082
1083                 mm_player_unrealize(player->player_handle);
1084                 return -3;
1085         }
1086
1087         /* If wdata's event is 'start', current wdata is first data of engine for synthesis. 
1088          * If wdata's event is 'finish', player should check previous event to know whether this wdata is first or not.
1089          * When previous wdata's event is 'finish' and current wdata's event is 'finish', 
1090          * the player should send utt started event. 
1091          */
1092         if (TTSP_RESULT_EVENT_START == wdata.event ||
1093             (TTSP_RESULT_EVENT_FINISH == player->event && TTSP_RESULT_EVENT_FINISH == wdata.event)) {
1094                 int pid;
1095                 pid = ttsd_data_get_pid(player->uid);
1096
1097                 /* send utterance start message */
1098                 if (0 != ttsdc_send_utt_start_message(pid, player->uid, wdata.utt_id)) {
1099                         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);
1100                 }
1101         } else {
1102                 SLOG(LOG_DEBUG, get_tag(), "[PLAYER] Don't need to send Utterance Start Signal");
1103         }
1104
1105         g_playing_info = player;
1106
1107         if (NULL != sound_file) 
1108                 g_free(sound_file);
1109         if (NULL != wdata.data) 
1110                 g_free(wdata.data);
1111
1112         return 0;
1113 }
1114
1115