Fix to remove timer when daemon is destroyed
[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         /* destroy player */
586         switch (player_state) {
587                 case MM_PLAYER_STATE_PLAYING:
588                         *state = TTSD_PLAYER_STATE_PLAYING;
589                         break;
590                 case MM_PLAYER_STATE_PAUSED:
591                         *state = TTSD_PLAYER_STATE_PAUSED;
592                         break;
593                 
594                 case MM_PLAYER_STATE_NULL:
595                         *state = TTSD_PLAYER_STATE_NULL;
596                         break;
597
598                 case MM_PLAYER_STATE_READY:
599                 default:
600                         SLOG(LOG_ERROR, get_tag(), "[Player ERROR] player state of uid(%d) is not valid", uid); 
601                         return -1;
602                         break;
603         }
604
605         return 0;
606 }
607
608 int ttsd_player_get_current_client()
609 {
610         if (false == g_player_init) {
611                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" );
612                 return -1;
613         }
614
615         if (NULL != g_playing_info) 
616                 return g_playing_info->uid;
617
618         SLOG(LOG_WARN, get_tag(), "[Player WARNING] No current player"); 
619
620         return 0;
621 }
622
623 int ttsd_player_get_current_utterance_id(int uid)
624 {
625         SLOG(LOG_DEBUG, get_tag(), "[Player] get current utt id : uid(%d)", uid );
626
627         if (false == g_player_init) {
628                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" );
629                 return -1;
630         }
631
632         /* Check uid */
633         player_s* current;
634         current = __player_get_item(uid);
635         if (NULL == current) {
636                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] uid(%d) is not valid", uid); 
637                 return -1;
638         }
639
640         return current->utt_id;
641 }
642
643 int ttsd_player_all_stop()
644 {
645         if (false == g_player_init) {
646                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Not Initialized" );
647                 return -1;
648         }
649
650         g_playing_info = NULL;
651
652         int ret = -1;
653         GList *iter = NULL;
654         player_s *data = NULL;
655
656         if (0 < g_list_length(g_player_list)) {
657                 /* Get a first item */
658                 iter = g_list_first(g_player_list);
659
660                 while (NULL != iter) {
661                         /* Get handle data from list */
662                         data = (player_s*)iter->data;
663
664                         app_state_e state;
665                         if (0 > ttsd_data_get_client_state(data->uid, &state)) {
666                                 SLOG(LOG_ERROR, get_tag(), "[player ERROR] ttsd_player_all_stop : uid is not valid ");
667                                 ttsd_player_destroy_instance(data->uid);
668                                 iter = g_list_next(iter);
669                                 continue;
670                         }
671
672                         if (APP_STATE_PLAYING == state || APP_STATE_PAUSED == state) {
673                                 /* unrealize player */
674                                 ret = mm_player_unrealize(data->player_handle);
675                                 if (MM_ERROR_NONE != ret) {
676                                         SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_unrealize() : %x", ret);
677                                 } 
678
679                                 data->utt_id = -1;
680                                 data->event = TTSP_RESULT_EVENT_FINISH;
681                         }
682                         
683                         /* Get next item */
684                         iter = g_list_next(iter);
685                 }
686         }
687
688         SLOG(LOG_DEBUG, get_tag(), "[Player SUCCESS] player all stop!! ");
689
690         return 0;
691 }
692
693 static Eina_Bool __player_next_play(void *data)
694 {
695         SLOG(LOG_DEBUG, get_tag(), "===== PLAYER NEXT PLAY");
696
697         int* uid = (int*)data;
698
699         if (NULL == uid) {
700                 SLOG(LOG_ERROR, get_tag(), "[PLAYER ERROR] uid is NULL");
701                 SLOG(LOG_DEBUG, get_tag(), "=====");
702                 SLOG(LOG_DEBUG, get_tag(), "  ");
703                 return EINA_FALSE;
704         }
705
706         SLOG(LOG_DEBUG, get_tag(), "[PLAYER] uid = %d", *uid);
707         
708         if (0 != ttsd_player_next_play(*uid)) {
709                 SLOG(LOG_WARN, get_tag(), "[PLAYER WARNING] Fail to play next");
710         }
711
712         free(uid);
713
714         SLOG(LOG_DEBUG, get_tag(), "=====");
715         SLOG(LOG_DEBUG, get_tag(), "  ");
716
717         return EINA_FALSE;
718 }
719
720 static int msg_callback(int message, void *data, void *user_param) 
721 {
722         user_data_s* user_data = NULL;
723
724         user_data = (user_data_s*)user_param;
725
726         if (NULL == user_data) {
727                 SLOG(LOG_ERROR, get_tag(), "[PLAYER ERROR] user_param is NULL");
728                 return -1;
729         }
730
731         int uid = user_data->uid;
732         int utt_id = user_data->utt_id;
733
734         MMMessageParamType *msg = (MMMessageParamType*)data;
735
736         switch (message) {
737         case MM_MESSAGE_ERROR:
738                 {
739                         SLOG(LOG_DEBUG, get_tag(), "===== PLAYER ERROR CALLBACK");
740                         SLOG(LOG_ERROR, get_tag(), "[PLAYER ERROR] Info : uid(%d), utt id(%d), error file(%s)", uid, utt_id, user_data->filename);
741
742                         /* send error info */
743                         g_result_callback(PLAYER_ERROR, uid, utt_id);
744
745                         player_s* current;
746                         current = __player_get_item(uid);
747                         if (NULL == current) {
748                                 SLOG(LOG_ERROR, get_tag(), "[PLAYER ERROR] uid(%d) is NOT valid ", uid); 
749                         } else {
750                                 current->event = TTSP_RESULT_EVENT_FINISH;
751                         }
752
753                         if (NULL != user_data) 
754                                 g_free(user_data);
755
756                         /* check current player */
757                         if (NULL != g_playing_info) {
758                                 if (uid == g_playing_info->uid) {
759                                         g_playing_info = NULL;
760                                         SLOG(LOG_WARN, get_tag(), "[PLAYER] Current Player is NOT uid(%d)", uid);
761                                 }
762                         }
763
764                         SLOG(LOG_DEBUG, get_tag(), "=====");
765                         SLOG(LOG_DEBUG, get_tag(), "  ");
766                 }
767                 break;  /*MM_MESSAGE_ERROR*/
768
769         case MM_MESSAGE_BEGIN_OF_STREAM:
770
771                 break;
772
773         case MM_MESSAGE_END_OF_STREAM:
774                 {
775                         SLOG(LOG_DEBUG, get_tag(), "===== END OF STREAM CALLBACK");
776
777                         if (-1 == remove(user_data->filename)) {
778                                 SLOG(LOG_WARN, get_tag(), "[PLAYER WARNING] Fail to remove temp file", user_data->filename); 
779                         }
780
781                         /* Check uid */
782                         player_s* current;
783                         current = __player_get_item(uid);
784                         if (NULL == current) {
785                                 SLOG(LOG_ERROR, get_tag(), "[PLAYER ERROR] uid(%d) is NOT valid", uid); 
786                                 if (NULL != g_playing_info) {
787                                         if (uid == g_playing_info->uid) {
788                                                 g_playing_info = NULL;
789                                                 SLOG(LOG_WARN, get_tag(), "[PLAYER] Current Player is NOT uid(%d)", uid);
790                                         }
791                                 }
792                                 SLOG(LOG_DEBUG, get_tag(), "=====");
793                                 SLOG(LOG_DEBUG, get_tag(), "  ");
794                                 return -1;
795                         }
796
797                         g_free(user_data);
798
799                         int pid = ttsd_data_get_pid(uid);
800
801                         /* send utterence finish signal */
802                         if (TTSP_RESULT_EVENT_FINISH == current->event) {
803                                 if (0 == ttsdc_send_utt_finish_message(pid, uid, utt_id))
804                                         SLOG(LOG_DEBUG, get_tag(), "[Send SUCCESS] Send Utterance Completed Signal : pid(%d), uid(%d), uttid(%d)", pid, uid, utt_id);
805                                 else 
806                                         SLOG(LOG_ERROR, get_tag(), "[Send ERROR] Fail to send Utterance Completed Signal : pid(%d), uid(%d), uttid(%d)", pid, uid, utt_id);
807                         }
808
809                         /* for sync problem */
810                         MMPlayerStateType player_state;
811                         mm_player_get_state(current->player_handle, &player_state);
812                         
813                         if (MM_PLAYER_STATE_PAUSED == player_state) {
814                                 g_pause_info = true;    /* The current state of player is 'Paused' */
815                                 g_paused_uid = uid;     /* The current uid when the current state player is 'Paused' */
816                         } else {
817                                 /* play state */
818                                 int* uid_data = (int*) g_malloc0(sizeof(int));
819                                 *uid_data = uid;
820
821                                 SLOG(LOG_DEBUG, get_tag(), "[PLAYER] uid = %d", *uid_data);
822
823                                 ecore_timer_add(0, __player_next_play, (void*)uid_data);
824                         }
825
826                         SLOG(LOG_DEBUG, get_tag(), "=====");
827                         SLOG(LOG_DEBUG, get_tag(), "  ");
828                 }
829                 break;  /*MM_MESSAGE_END_OF_STREAM*/
830
831         case MM_MESSAGE_STATE_CHANGED:
832                 break;
833
834         case MM_MESSAGE_STATE_INTERRUPTED:
835                 if (MM_PLAYER_STATE_PAUSED == msg->state.current) {
836
837                         SLOG(LOG_DEBUG, get_tag(), "===== INTERRUPTED CALLBACK");
838
839                         ttsd_data_set_client_state(uid, APP_STATE_PAUSED);
840
841                         int pid = ttsd_data_get_pid(uid);
842                         /* send message to client about changing state */
843                         ttsdc_send_set_state_message (pid, uid, APP_STATE_PAUSED);
844
845                         SLOG(LOG_DEBUG, get_tag(), "=====");
846                         SLOG(LOG_DEBUG, get_tag(), "  ");
847                 }
848                 break;
849
850         default:
851                 break;
852         }
853
854         return TRUE;
855 }
856
857 player_s* __player_get_item(int uid)
858 {
859         GList *iter = NULL;
860         player_s *data = NULL;
861
862         if (0 < g_list_length(g_player_list)) {
863                 /* Get a first item */
864                 iter = g_list_first(g_player_list);
865
866                 while (NULL != iter) {
867                         /* Get handle data from list */
868                         data = (player_s*)iter->data;
869
870                         /* compare uid */
871                         if (uid == data->uid)   
872                                 return data;
873
874                         /* Get next item */
875                         iter = g_list_next(iter);
876                 }
877         }
878
879         return NULL;
880 }
881
882 int __save_file(int uid, int index, sound_data_s data, char** filename)
883 {
884         char postfix[5];
885         memset(postfix, '\0', 5);
886
887         switch (data.audio_type) {
888         case TTSP_AUDIO_TYPE_RAW:
889         case TTSP_AUDIO_TYPE_WAV:
890                 strcpy(postfix, "wav");
891                 break;
892         case TTSP_AUDIO_TYPE_MP3:
893                 strcpy(postfix, "mp3");
894                 break;
895         case TTSP_AUDIO_TYPE_AMR:
896                 strcpy(postfix, "amr");
897                 break;
898         default:
899                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Audio type(%d) is NOT valid", data.audio_type); 
900                 return -1;
901         }
902
903         /* make filename to save */
904         char* temp;
905         temp = (char*)g_malloc0(sizeof(char) * FILE_PATH_SIZE);
906         if (NULL == temp) {
907                 SLOG(LOG_ERROR, get_tag(), "[Player Error] make buf is failed");
908                 return -1;
909         }
910
911         int ret = snprintf(temp, FILE_PATH_SIZE, "%s/ttstemp%d_%d.%s", TEMP_FILE_PATH, uid, index, postfix);
912
913         if (0 >= ret) {
914                 if (NULL != temp)
915                         g_free(temp);
916                 return -1;
917         }
918
919         FILE* fp;
920         fp = fopen(temp, "wb");
921
922         if (fp == NULL) {
923                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] temp file open error");
924                 if (NULL != temp)
925                         g_free(temp);
926                 return -1;
927         }
928
929         if (data.audio_type == TTSP_AUDIO_TYPE_RAW) {
930                 WavHeader header;
931                 if (0 != __init_wave_header(&header, data.data_size, data.rate, data.channels)) {
932                         fclose(fp);
933                         if (NULL != temp)
934                                 g_free(temp);
935                         return -1;
936                 }
937
938                 if (0 >= fwrite(&header, sizeof(WavHeader), 1, fp)) {
939                         SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail to write wav header to file");
940                         fclose(fp);
941                         if (NULL != temp)
942                                 g_free(temp);
943                         return -1;
944                 }
945         }
946
947         int size = fwrite(data.data, data.data_size, 1,  fp);
948         if (size <= 0) {
949                 size = fwrite("0000000000", DEFAULT_FILE_SIZE, 1,  fp);
950                 if (size <= 0) {
951                         SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail to write date");
952                         fclose(fp);
953                         if (NULL != temp)
954                                 g_free(temp);
955                         return -1;
956                 }       
957         } 
958
959         fclose(fp);
960         *filename = temp;
961         
962         SLOG(LOG_DEBUG, get_tag(), " ");
963         SLOG(LOG_DEBUG, get_tag(), "Filepath : %s ", *filename);
964         SLOG(LOG_DEBUG, get_tag(), "Header : Data size(%d), Sample rate(%d), Channel(%d) ", data.data_size, data.rate, data.channels);
965
966         return 0;
967 }
968
969 int __init_wave_header (WavHeader* hdr, size_t nsamples, size_t sampling_rate, int channel)
970 {
971         if (hdr == NULL || sampling_rate <= 0 || channel <= 0) {
972                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] __init_wave_header : input parameter invalid");
973                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] hdr : %p", hdr);
974                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] nsample : %d", nsamples);
975                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] sampling_rate : %", sampling_rate);
976                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] channel : %", channel);
977                 return TTSD_ERROR_INVALID_PARAMETER;
978         }
979
980         size_t bytesize = DEFAULT_FILE_SIZE;
981
982         if (0 < nsamples) {
983                 bytesize = nsamples;    
984         } 
985
986         /* NOT include \0(NULL) */
987         strncpy(hdr->riff, "RIFF", 4);  
988         hdr->file_size = (int)(bytesize  + 36);
989         strncpy(hdr->wave, "WAVE", 4);
990         strncpy(hdr->fmt, "fmt ", 4);   /* fmt + space */
991         hdr->header_size = 16;
992         hdr->sample_format = 1;         /* WAVE_FORMAT_PCM */
993         hdr->n_channels = channel;
994         hdr->sample_rate = (int)(sampling_rate);
995         hdr->bytes_per_second = (int)sampling_rate * sizeof(short);
996         hdr->block_align =  sizeof(short);
997         hdr->bits_per_sample = sizeof(short)*8;
998         strncpy(hdr->data, "data", 4);  
999         hdr->data_size = (int)bytesize;
1000
1001         return 0;
1002 }
1003
1004 int __set_and_start(player_s* player)
1005 {
1006         /* get sound data */
1007         sound_data_s wdata;
1008         if (0 != ttsd_data_get_sound_data(player->uid, &wdata)) {
1009                 SLOG(LOG_WARN, get_tag(), "[Player WARNING] A sound queue of current player(%d) is empty", player->uid); 
1010                 return -1;
1011         }
1012
1013         g_index++;
1014         if (10000 <= g_index)   {
1015                 g_index = 1;
1016         }
1017
1018         int ret;
1019
1020         /* make sound file for mmplayer */
1021         char* sound_file = NULL;
1022         ret = __save_file(player->uid, g_index, wdata, &sound_file);
1023         if (0 != ret || NULL == sound_file) {
1024                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail to make sound file");
1025                 return -1;
1026         }
1027         
1028         user_data_s* user_data = (user_data_s*)g_malloc0(sizeof(user_data_s));
1029         user_data->uid = player->uid;
1030         user_data->utt_id = wdata.utt_id;
1031         user_data->event = wdata.event;
1032         memset(user_data->filename, 0, TEMP_FILE_MAX); 
1033         strncpy( user_data->filename, sound_file, strlen(sound_file) );
1034
1035         SLOG(LOG_DEBUG, get_tag(), "Info : uid(%d), utt(%d), filename(%s) , event(%d)", 
1036                 user_data->uid, user_data->utt_id, user_data->filename, user_data->event);
1037         SLOG(LOG_DEBUG, get_tag(), " ");
1038
1039         
1040         /* set callback func */
1041         ret = mm_player_set_message_callback(player->player_handle, msg_callback, (void*)user_data);
1042         if (MM_ERROR_NONE != ret) {
1043                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail mm_player_set_message_callback() : %x ", ret);
1044                 return -1;
1045         }
1046
1047         /* set playing info to mm player */
1048         char* err_attr_name = NULL;
1049
1050         if (0 != access(sound_file, R_OK)) {
1051                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail to read sound file (%s)", sound_file);
1052                 return -1;
1053         }
1054         
1055         ret = mm_player_set_attribute(player->player_handle, &err_attr_name,
1056                 "profile_uri", sound_file , strlen(sound_file) + 1,
1057                 "sound_volume_type", MM_SOUND_VOLUME_TYPE_MEDIA,
1058                 "sound_route", MM_AUDIOROUTE_PLAYBACK_NORMAL,
1059                 NULL );
1060
1061         if (MM_ERROR_NONE != ret) {
1062                 if (NULL != err_attr_name) {
1063                         SLOG(LOG_ERROR, get_tag(), "[Player ERROR] Fail mm_player_set_attribute() : msg(%s), result(%x) ", err_attr_name, ret);
1064                 }
1065                 return -1;
1066         }
1067
1068         if (TTSD_MODE_DEFAULT != ttsd_get_mode()) {
1069                 ret = mm_player_ignore_session(player->player_handle);
1070                 if (MM_ERROR_NONE != ret) {
1071                         SLOG(LOG_WARN, get_tag(), "[Player WARNING] fail mm_player_ignore_session() : %x", ret);
1072                 }
1073         }
1074         
1075         /* realize and start mm player */ 
1076         ret = mm_player_realize(player->player_handle);
1077         if (MM_ERROR_NONE != ret) {
1078                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_realize() : %x", ret);
1079                 return -2;
1080         }
1081
1082         ret = mm_player_start(player->player_handle);
1083         if (MM_ERROR_NONE != ret) {
1084                 SLOG(LOG_ERROR, get_tag(), "[Player ERROR] fail mm_player_start() : %x", ret);
1085
1086                 mm_player_unrealize(player->player_handle);
1087                 return -3;
1088         }
1089
1090         /* If wdata's event is 'start', current wdata is first data of engine for synthesis. 
1091          * If wdata's event is 'finish', player should check previous event to know whether this wdata is first or not.
1092          * When previous wdata's event is 'finish' and current wdata's event is 'finish', 
1093          * the player should send utt started event. 
1094          */
1095         if (TTSP_RESULT_EVENT_START == wdata.event ||
1096             (TTSP_RESULT_EVENT_FINISH == player->event && TTSP_RESULT_EVENT_FINISH == wdata.event)) {
1097                 int pid;
1098                 pid = ttsd_data_get_pid(player->uid);
1099
1100                 /* send utterance start message */
1101                 if (0 != ttsdc_send_utt_start_message(pid, player->uid, wdata.utt_id)) {
1102                         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);
1103                 }
1104         } else {
1105                 SLOG(LOG_DEBUG, get_tag(), "[PLAYER] Don't need to send Utterance Start Signal");
1106         }
1107
1108         g_playing_info = player;
1109
1110         if (NULL != sound_file) 
1111                 g_free(sound_file);
1112         if (NULL != wdata.data) 
1113                 g_free(wdata.data);
1114
1115         return 0;
1116 }
1117
1118