Fix segmentation fault in ttsd_data.cpp
[platform/core/uifw/tts.git] / server / ttsd_data.cpp
1 /*
2 *  Copyright (c) 2011-2016 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 #include <list>
15 #include <pthread.h>
16 #include <vector>
17
18 #include "ttsd_main.h"
19 #include "ttsd_data.h"
20
21 using namespace std;
22
23 typedef struct 
24 {
25         char*   lang;
26         int     vctype;
27 }used_voice_s;
28
29 typedef struct 
30 {
31         int             pid;
32         int             uid;
33         int             utt_id_stopped;
34         app_state_e     state;
35
36         std::list<speak_data_s*> m_speak_data;
37         std::list<sound_data_s*> m_wav_data;
38
39         std::list<used_voice_s> m_used_voice;
40 }app_data_s;
41
42 static vector<app_data_s> g_app_list;
43
44 static pthread_mutex_t g_sound_data_mutex = PTHREAD_MUTEX_INITIALIZER;
45
46 /*
47 * functions for debug
48 */
49 int __data_show_list()
50 {
51         int vsize = g_app_list.size();
52
53         SLOG(LOG_DEBUG, tts_tag(), "----- client list -----");
54
55         for (int i=0; i < vsize; i++) {
56                 SECURE_SLOG(LOG_DEBUG, tts_tag(), "[%dth] pid(%d), uid(%d), state(%d)", i, g_app_list[i].pid, g_app_list[i].uid, g_app_list[i].state);
57         }
58
59         if (0 == vsize) {
60                 SLOG(LOG_DEBUG, tts_tag(), "No Client");
61         }
62
63         SLOG(LOG_DEBUG, tts_tag(), "-----------------------");
64
65         return TTSD_ERROR_NONE;
66 }
67
68 int __data_show_sound_list(int index)
69 {
70         SLOG(LOG_DEBUG, tts_tag(), "----- Sound list -----");
71         
72         unsigned int i = 0;
73         std::list<sound_data_s*>::iterator iter;
74         for (iter = g_app_list[index].m_wav_data.begin(); iter != g_app_list[index].m_wav_data.end(); iter++) {
75                 SLOG(LOG_DEBUG, tts_tag(), "[%dth][%p] data(%p) data size(%ld), uttid(%d), type(%d)", 
76                         i, *iter, (*iter)->data, (*iter)->data_size, (*iter)->utt_id, (*iter)->audio_type);
77                 i++;
78         }
79
80         if (i == 0) {
81                 SLOG(LOG_DEBUG, tts_tag(), "No Sound Data");
82         }
83
84         SLOG(LOG_DEBUG, tts_tag(), "----------------------");
85         return TTSD_ERROR_NONE;
86 }
87
88 int __data_show_text_list(int index)
89 {
90         SLOG(LOG_DEBUG, tts_tag(), "----- Text list -----");
91
92         unsigned int i = 0;
93         std::list<speak_data_s*>::iterator iter;
94         for (iter = g_app_list[index].m_speak_data.begin(); iter != g_app_list[index].m_speak_data.end(); iter++) {
95                 SLOG(LOG_DEBUG, tts_tag(), "[%dth][%p] lang(%s), vctype(%d), speed(%d), uttid(%d), text(%s)", 
96                         i + 1, *iter, (*iter)->lang, (*iter)->vctype, (*iter)->speed, (*iter)->utt_id, (*iter)->text);
97                 i++;
98         }
99
100         if (0 == i) {
101                 SLOG(LOG_DEBUG, tts_tag(), "No Text Data");
102         }
103
104         SLOG(LOG_DEBUG, tts_tag(), "---------------------");
105         return TTSD_ERROR_NONE;
106 }
107
108 int __data_show_used_voice_list(int index)
109 {
110         SLOG(LOG_DEBUG, tts_tag(), "----- Used voice list -----");
111
112         unsigned int i = 0;
113         std::list<used_voice_s>::iterator iter;
114         for (iter = g_app_list[index].m_used_voice.begin(); iter != g_app_list[index].m_used_voice.end(); iter++) {
115                 SLOG(LOG_DEBUG, tts_tag(), "[%dth] lang(%s), vctype(%d)", i + 1, iter->lang, iter->vctype);
116                 i++;
117         }
118
119         if (0 == i) {
120                 SLOG(LOG_DEBUG, tts_tag(), "No Voice Data");
121         }
122
123         SLOG(LOG_DEBUG, tts_tag(), "---------------------------");
124         return TTSD_ERROR_NONE;
125 }
126
127 /*
128 * ttsd data functions
129 */
130
131 int ttsd_data_new_client(int pid, int uid)
132 {
133         if( -1 != ttsd_data_is_client(uid) ) {
134                 SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
135                 return TTSD_ERROR_INVALID_PARAMETER;
136         }
137
138         app_data_s app;
139         app.pid = pid;
140         app.uid = uid;
141         app.utt_id_stopped = 0;
142         app.state = APP_STATE_READY;
143
144         g_app_list.insert(g_app_list.end(), app);
145
146 #ifdef DATA_DEBUG
147         __data_show_list();
148 #endif 
149         return TTSD_ERROR_NONE;
150 }
151
152 int ttsd_data_delete_client(int uid)
153 {
154         int index = 0;
155
156         index = ttsd_data_is_client(uid);
157         
158         if (index < 0) {
159                 SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
160                 return -1;
161         }
162
163         if (0 != ttsd_data_clear_data(uid)) {
164                 SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] Fail to clear data");
165                 return -1;
166         }
167
168         g_app_list.erase(g_app_list.begin()+index);
169
170 #ifdef DATA_DEBUG
171         __data_show_list();
172 #endif 
173         return TTSD_ERROR_NONE;
174 }
175
176 int ttsd_data_is_client(int uid)
177 {
178         int vsize = g_app_list.size();
179
180         for (int i = 0; i < vsize; i++) {
181                 if(g_app_list[i].uid == uid) {
182                         return i;               
183                 }
184         }
185
186         return -1;
187 }
188
189 int ttsd_data_get_client_count()
190 {
191         return g_app_list.size();
192 }
193
194 int ttsd_data_get_pid(int uid)
195 {
196         int index;
197
198         index = ttsd_data_is_client(uid);
199         
200         if (index < 0)  {
201                 SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
202                 return TTSD_ERROR_INVALID_PARAMETER;
203         }
204
205         return g_app_list[index].pid;
206 }
207
208 int ttsd_data_get_speak_data_size(int uid)
209 {
210         int index = 0;
211         index = ttsd_data_is_client(uid);
212         
213         if (index < 0) {
214                 SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
215                 return TTSD_ERROR_INVALID_PARAMETER;
216         }
217
218         int size = g_app_list[index].m_speak_data.size();
219         return size;
220 }
221
222 int ttsd_data_set_used_voice(int uid, const char* lang, int type)
223 {
224         int index = 0;
225         index = ttsd_data_is_client(uid);
226
227         if (index < 0) {
228                 SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
229                 return TTSD_ERROR_INVALID_PARAMETER;
230         }
231
232         /* Find voice */
233         std::list<used_voice_s>::iterator iter;
234
235         for (iter = g_app_list[index].m_used_voice.begin();iter != g_app_list[index].m_used_voice.end();iter++) {
236                 if (0 == strcmp(lang, iter->lang) && type == iter->vctype) {
237                         SLOG(LOG_DEBUG, tts_tag(), "[DATA] The voice is already registered (%s)(%d)", lang, type);
238                         return 0;
239                 }
240         }
241
242         /* Add voice */
243         used_voice_s used_voice;
244         used_voice.lang = strdup(lang);
245         used_voice.vctype = type;
246
247         g_app_list[index].m_used_voice.insert(g_app_list[index].m_used_voice.end(), used_voice);
248
249 #ifdef DATA_DEBUG
250         __data_show_used_voice_list(index);
251 #endif
252
253         return -1;      /* Need to load voice*/
254 }
255
256 int ttsd_data_reset_used_voice(int uid, ttsd_used_voice_cb callback)
257 {
258         int index = 0;
259         index = ttsd_data_is_client(uid);
260
261         if (index < 0) {
262                 SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
263                 return TTSD_ERROR_INVALID_PARAMETER;
264         }
265
266         if (NULL == callback) {
267                 SLOG(LOG_WARN, tts_tag(), "[DATA WARNING] Used voice callback is NULL");
268         }
269
270         /* Find voice */
271         std::list<used_voice_s>::iterator iter;
272
273         for (iter = g_app_list[index].m_used_voice.begin(); iter != g_app_list[index].m_used_voice.end(); iter++) {
274                 if (NULL != callback) {
275                         callback(iter->lang, iter->vctype);
276                 }
277
278                 if (NULL != iter->lang) {
279                         free(iter->lang);
280                 }
281         } 
282
283         g_app_list[index].m_used_voice.clear();
284
285 #ifdef DATA_DEBUG
286         __data_show_used_voice_list(index);
287 #endif
288
289         return TTSD_ERROR_NONE;
290 }
291
292 int ttsd_data_add_speak_data(int uid, speak_data_s* data)
293 {
294         int index = 0;
295         index = ttsd_data_is_client(uid);
296
297         if (index < 0) {
298                 SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
299                 return TTSD_ERROR_INVALID_PARAMETER;
300         }
301         
302         g_app_list[index].m_speak_data.insert(g_app_list[index].m_speak_data.end(), data);
303
304         if (1 == data->utt_id)
305                 g_app_list[index].utt_id_stopped = 0;
306
307 #ifdef DATA_DEBUG
308         __data_show_text_list(index);
309 #endif 
310         return TTSD_ERROR_NONE;
311 }
312
313 int ttsd_data_get_speak_data(int uid, speak_data_s** data)
314 {
315         int index = 0;
316         index = ttsd_data_is_client(uid);
317
318         if (index < 0) {
319                 SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid(%d)", uid);
320                 return TTSD_ERROR_INVALID_PARAMETER;
321         }
322
323         if (0 == g_app_list[index].m_speak_data.size()) {
324 #ifdef DATA_DEBUG
325                 SLOG(LOG_WARN, tts_tag(), "[DATA WARNING] There is no speak data"); 
326 #endif 
327                 return -1;
328         }
329
330         std::list<speak_data_s*>::iterator iter = g_app_list[index].m_speak_data.begin();
331         *data = *iter;
332         g_app_list[index].m_speak_data.pop_front();
333
334 #ifdef DATA_DEBUG
335         __data_show_text_list(index);
336 #endif 
337         return TTSD_ERROR_NONE;
338 }
339
340 int ttsd_data_add_sound_data(int uid, sound_data_s* data)
341 {
342         int index = 0;
343         index = ttsd_data_is_client(uid);
344
345         if(index < 0) {
346                 SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
347                 return TTSD_ERROR_INVALID_PARAMETER;
348         }
349
350         if (NULL == data) {
351                 SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] sound data is NULL");
352                 return TTSD_ERROR_INVALID_PARAMETER;
353         }
354         /* mutex is locked */
355         pthread_mutex_lock(&g_sound_data_mutex);
356
357         g_app_list[index].m_wav_data.insert(g_app_list[index].m_wav_data.end(), data);
358
359 #ifdef DATA_DEBUG
360         __data_show_sound_list(index);
361 #endif 
362
363         /* mutex is unlocked */
364         pthread_mutex_unlock(&g_sound_data_mutex);
365
366         return TTSD_ERROR_NONE;
367 }
368
369 int ttsd_data_get_sound_data(int uid, sound_data_s** data)
370 {
371         int index = 0;
372         index = ttsd_data_is_client(uid);
373
374         if (index < 0)  {
375                 SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
376                 return TTSD_ERROR_INVALID_PARAMETER;
377         }
378
379         /* mutex is locked */
380         pthread_mutex_lock(&g_sound_data_mutex);
381
382         if (0 == g_app_list[index].m_wav_data.size()) {
383 #ifdef DATA_DEBUG
384                 SLOG(LOG_DEBUG, tts_tag(), "[DATA] There is no wav data");
385 #endif
386                 /* mutex is unlocked */
387                 pthread_mutex_unlock(&g_sound_data_mutex);
388                 return -1;
389         }
390
391         std::list<sound_data_s*>::iterator iter = g_app_list[index].m_wav_data.begin();
392         *data = *iter;
393         g_app_list[index].m_wav_data.pop_front();
394
395 #ifdef DATA_DEBUG
396         __data_show_sound_list(index);
397 #endif 
398
399         /* mutex is unlocked */
400         pthread_mutex_unlock(&g_sound_data_mutex);
401
402         return TTSD_ERROR_NONE;
403 }
404
405 int ttsd_data_get_sound_data_size(int uid)
406 {
407         int index = 0;
408         int data_size = 0;
409         index = ttsd_data_is_client(uid);
410
411         if (index < 0)  {
412                 SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
413                 return TTSD_ERROR_INVALID_PARAMETER;
414         }
415
416         /* mutex is locked */
417         pthread_mutex_lock(&g_sound_data_mutex);
418         data_size = g_app_list[index].m_wav_data.size();
419
420         /* mutex is unlocked */
421         pthread_mutex_unlock(&g_sound_data_mutex);
422
423         return data_size;
424 }
425
426 int ttsd_data_clear_data(int uid)
427 {
428         int index = 0;
429
430         index = ttsd_data_is_client(uid);
431         if (index < 0) {
432                 SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
433                 return TTSD_ERROR_INVALID_PARAMETER;
434         }
435
436         int removed_last_uttid = -1;
437         speak_data_s* temp_speak = NULL;
438         sound_data_s* temp_sound = NULL;
439
440         /* free allocated data */
441         while(1) {
442                 if (0 != ttsd_data_get_speak_data(uid, &temp_speak)) {
443                         break;
444                 }
445
446                 if (NULL != temp_speak) {
447                         SLOG(LOG_DEBUG, tts_tag(), "[DEBUG] utt(%d), text(%s), lang(%s), vctype(%d) speed(%d)", 
448                                         temp_speak->utt_id, temp_speak->text, temp_speak->lang, temp_speak->vctype, temp_speak->speed);
449
450                         if (NULL != temp_speak->text) {
451                                 free(temp_speak->text);
452                                 temp_speak->text = NULL;
453                         }
454                         if (NULL != temp_speak->lang) {
455                                 free(temp_speak->lang);
456                                 temp_speak->lang = NULL;
457                         }
458                         removed_last_uttid = temp_speak->utt_id;
459
460                         free(temp_speak);
461                         temp_speak = NULL;
462                 }
463         }
464
465         if (-1 != removed_last_uttid) {
466                 g_app_list[index].utt_id_stopped = removed_last_uttid;
467         }
468
469         while(1) {
470                 if (0 != ttsd_data_get_sound_data(uid, &temp_sound)) {
471                         break;
472                 }
473
474                 if (NULL != temp_sound) {
475                         SLOG(LOG_ERROR, tts_tag(), "[DEBUG][%p] uid(%d), event(%d) data(%p) size(%d) rate(%d) utt(%d)", 
476                                 temp_sound, uid, temp_sound->event, temp_sound->data, temp_sound->data_size, temp_sound->rate, temp_sound->utt_id);
477
478                         if (NULL != temp_sound->data) {
479                                 free(temp_sound->data);
480                                 temp_sound->data = NULL;
481                         }
482
483                         free(temp_sound);
484                         temp_sound = NULL;
485                 }
486         }
487
488         g_app_list[index].m_speak_data.clear();
489         g_app_list[index].m_wav_data.clear();
490
491         return TTSD_ERROR_NONE;
492 }
493
494 int ttsd_data_get_client_state(int uid, app_state_e* state)
495 {
496         int index = 0;
497
498         index = ttsd_data_is_client(uid);
499         if (index < 0)  {
500                 SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
501                 return TTSD_ERROR_INVALID_PARAMETER;
502         }
503
504         *state = g_app_list[index].state;
505
506         return TTSD_ERROR_NONE;
507 }
508
509 int ttsd_data_set_client_state(int uid, app_state_e state)
510 {
511         int index = 0;
512
513         index = ttsd_data_is_client(uid);
514         if (index < 0)  {
515                 SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
516                 return TTSD_ERROR_INVALID_PARAMETER;
517         }
518
519         /* The client of playing state of all clients is only one. need to check state. */
520         if (APP_STATE_PLAYING == state) {
521                 int vsize = g_app_list.size();
522                 for (int i = 0; i < vsize; i++) {
523                         if(g_app_list[i].state == APP_STATE_PLAYING) {
524                                 SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] A playing client has already existed.");
525                                 return -1;
526                         }
527                 }
528         }
529
530         g_app_list[index].state = state;
531
532         return TTSD_ERROR_NONE;
533 }
534
535 int ttsd_data_get_current_playing()
536 {
537         int vsize = g_app_list.size();
538
539         for (int i = 0; i < vsize; i++) {
540                 if (APP_STATE_PLAYING == g_app_list[i].state) {
541                         SLOG(LOG_DEBUG, tts_tag(), "[DATA] uid(%d) is playing", g_app_list[i].uid);
542                         return g_app_list[i].uid;
543                 }
544         }
545
546         return -1;
547 }
548
549 int ttsd_data_foreach_clients(ttsd_data_get_client_cb callback, void* user_data)
550 {
551         if (NULL == callback) {
552                 SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] input data is NULL!!");
553                 return -1;
554         }
555
556 #ifdef DATA_DEBUG
557         __data_show_list();
558 #endif 
559         
560         /* Copy app info */
561         vector<app_data_s> temp_app_list;
562         int vsize = g_app_list.size();
563
564         int i = 0;
565         for (i = 0;i < vsize;i++) {
566                 app_data_s app;
567                 app.pid = g_app_list[i].pid;
568                 app.uid = g_app_list[i].uid;
569                 app.utt_id_stopped = 0;
570                 app.state = g_app_list[i].state;
571
572                 temp_app_list.insert(temp_app_list.end(), app);
573         }
574
575         for (i = 0;i < vsize;i++) {
576                 SECURE_SLOG(LOG_DEBUG, tts_tag(), "[%dth] pid(%d), uid(%d), state(%d)", i, temp_app_list[i].pid, temp_app_list[i].uid, temp_app_list[i].state);
577                 if (false == callback(temp_app_list[i].pid, temp_app_list[i].uid, temp_app_list[i].state, user_data)) {
578                         break;
579                 }
580         }
581
582         for (i = 0;i < vsize;i++) {
583                 temp_app_list.erase(temp_app_list.begin());
584         }
585         
586         return 0;
587 }
588
589 bool ttsd_data_is_uttid_valid(int uid, int uttid)
590 {
591         int index = 0;
592
593         index = ttsd_data_is_client(uid);
594         if (index < 0)  {
595                 SECURE_SLOG(LOG_ERROR, tts_tag(), "[DATA ERROR] uid is not valid (%d)", uid);
596                 return TTSD_ERROR_INVALID_PARAMETER;
597         }
598
599         if (uttid < g_app_list[index].utt_id_stopped)
600                 return false;
601
602         return true;
603 }
604
605 int ttsd_data_is_current_playing()
606 {
607         int vsize = g_app_list.size();
608
609         for (int i = 0; i < vsize; i++) {
610                 if(g_app_list[i].state == APP_STATE_PLAYING) {
611                         return g_app_list[i].uid;               
612                 }
613         }
614
615         return -1;
616 }
617
618 int ttsd_data_get_same_pid_client_count(int pid)
619 {
620         int vsize = g_app_list.size();
621         int number = 0;
622
623         for (int i = 0;i < vsize;i++) {
624                 if(g_app_list[i].pid == pid) {
625                         number++;               
626                 }
627         }
628
629         return number;
630 }
631
632 int ttsd_data_save_error_log(int uid, FILE* fp)
633 {
634         int ret;
635         int pid;
636         /* pid */
637         pid = ttsd_data_get_pid(uid);
638         if (0 > pid) {
639                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to get pid");
640         } else {
641                 fprintf(fp, "pid - %d", pid);
642         }
643         /* app state */
644         app_state_e state;
645         ret = ttsd_data_get_client_state(uid, &state);
646         if (0 != ret) {
647                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Fail to get app state");
648         } else {
649                 fprintf(fp, "app state - %d", state);
650         }
651
652         int index = 0;
653         unsigned int i;
654
655         index = ttsd_data_is_client(uid);
656         if (0 > index) {
657                 SLOG(LOG_ERROR, tts_tag(), "[ERROR] Invalid client");
658                 return -1;
659         }
660
661         /* get sound data */
662         fprintf(fp, "----- Sound list -----");
663
664         i = 0;
665         std::list<sound_data_s*>::iterator iter;
666         for (iter = g_app_list[index].m_wav_data.begin(); iter != g_app_list[index].m_wav_data.end(); iter++) {
667                 SLOG(LOG_DEBUG, tts_tag(), "[%dth][%p] data(%p) data size(%ld), uttid(%d), type(%d)",
668                         i, *iter, (*iter)->data, (*iter)->data_size, (*iter)->utt_id, (*iter)->audio_type);
669                 i++;
670         }
671
672         fprintf(fp, "----------------------");
673         
674         /* get speck data */
675         fprintf(fp, "----- Text list -----");
676
677         i = 0;
678         std::list<speak_data_s*>::iterator iter_speak;
679         for (iter_speak = g_app_list[index].m_speak_data.begin(); iter_speak != g_app_list[index].m_speak_data.end(); iter_speak++) {
680                 SLOG(LOG_DEBUG, tts_tag(), "[%dth][%p] lang(%s), vctype(%d), speed(%d), uttid(%d), text(%s)",
681                         i, *iter_speak, (*iter_speak)->lang, (*iter_speak)->vctype, (*iter_speak)->speed, (*iter_speak)->utt_id, (*iter_speak)->text);
682                 i++;
683         }
684         fprintf(fp, "---------------------");
685         
686         return 0;
687 }