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