Fix SVACE issue
[platform/core/uifw/dali-adaptor.git] / adaptors / tizen / tts-player-impl-tizen.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include "tts-player-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <tts.h>
23 #include <stdio.h>
24
25 #include <dali/public-api/object/type-registry.h>
26
27
28 namespace Dali
29 {
30
31 namespace Internal
32 {
33
34 namespace Adaptor
35 {
36
37 namespace // unnamed namespace
38 {
39
40 /**
41  * Helper function to convert Tizen-specific TTS state to external state.
42  * @param state The Tizen TTS state.
43  * @return The external TTS state.
44  */
45 Dali::TtsPlayer::State InternalToExternalState( tts_state_e state )
46 {
47   switch( state )
48   {
49     case TTS_STATE_CREATED:
50     {
51       return Dali::TtsPlayer::UNAVAILABLE;
52     }
53     case TTS_STATE_READY:
54     {
55       return Dali::TtsPlayer::READY;
56     }
57     case TTS_STATE_PLAYING:
58     {
59       return Dali::TtsPlayer::PLAYING;
60     }
61     case TTS_STATE_PAUSED:
62     {
63       return Dali::TtsPlayer::PAUSED;
64     }
65   }
66
67   return Dali::TtsPlayer::UNAVAILABLE;
68 }
69
70 } // unnamed namespace
71
72 #if defined(DEBUG_ENABLED)
73 Debug::Filter* TtsPlayer::gLogFilter = Debug::Filter::New(Debug::Concise, false, "LOG_TTS_PLAYER");
74 #endif
75
76 Dali::TtsPlayer TtsPlayer::New(Dali::TtsPlayer::Mode mode)
77 {
78   Dali::TtsPlayer player = Dali::TtsPlayer(new TtsPlayer(mode));
79
80   return player;
81 }
82
83 TtsPlayer::TtsPlayer(Dali::TtsPlayer::Mode mode)
84 : mInitialized(false),
85   mUnplayedString(""),
86   mTtsHandle(),
87   mUtteranceId(0),
88   mTtsMode(mode)
89 {
90   Initialize();
91 }
92
93 TtsPlayer::~TtsPlayer()
94 {
95   // If it is playing, stop it
96   Stop();
97
98   // Unset the callback funtion for TTS state change
99   int retVal = tts_unset_state_changed_cb(mTtsHandle);
100   if( retVal != TTS_ERROR_NONE )
101   {
102     LogErrorCode(static_cast<tts_error_e>(retVal));
103   }
104
105   // Destroy the TTS handle and disconnects the daemon
106   retVal = tts_destroy(mTtsHandle);
107   if( retVal != TTS_ERROR_NONE )
108   {
109     LogErrorCode(static_cast<tts_error_e>(retVal));
110   }
111 }
112
113 void TtsPlayer::Initialize()
114 {
115   // Create the TTS handle
116   int retVal = tts_create(&mTtsHandle);
117
118   if( retVal != TTS_ERROR_NONE )
119   {
120     LogErrorCode(static_cast<tts_error_e>(retVal));
121   }
122   else
123   {
124     // Set the callback funtion for TTS state change
125     retVal = tts_set_state_changed_cb(mTtsHandle, &StateChangedCallback, this);
126     if( retVal != TTS_ERROR_NONE )
127     {
128       LogErrorCode(static_cast<tts_error_e>(retVal));
129     }
130
131     // Check tts mode
132     tts_mode_e ttsMode = TTS_MODE_DEFAULT;
133     switch (mTtsMode)
134     {
135       case Dali::TtsPlayer::DEFAULT:
136         ttsMode = TTS_MODE_DEFAULT;
137       break;
138       case Dali::TtsPlayer::NOTIFICATION:
139         ttsMode = TTS_MODE_NOTIFICATION;
140       break;
141       case Dali::TtsPlayer::SCREEN_READER:
142         ttsMode = TTS_MODE_SCREEN_READER;
143       break;
144       default:
145       break;
146     }
147
148     // Set mode
149     retVal = tts_set_mode(mTtsHandle, ttsMode);
150     if(retVal != TTS_ERROR_NONE)
151     {
152       LogErrorCode(static_cast<tts_error_e>(retVal));
153     }
154
155     // Connect the TTS daemon asynchronously
156     retVal = tts_prepare(mTtsHandle);
157     if(retVal != TTS_ERROR_NONE)
158     {
159       LogErrorCode(static_cast<tts_error_e>(retVal));
160     }
161   }
162 }
163
164 void TtsPlayer::Play(const std::string& text)
165 {
166   if(mInitialized)
167   {
168     Stop();
169
170     // Add text to the queue, and use normal speed, default language and default voice set by the user
171     int retVal = tts_add_text(mTtsHandle, text.c_str(), NULL, TTS_VOICE_TYPE_AUTO, TTS_SPEED_AUTO, &mUtteranceId);
172     if(retVal != TTS_ERROR_NONE)
173     {
174       LogErrorCode(static_cast<tts_error_e>(retVal));
175     }
176     else
177     {
178       // Start synthesizing voice from text in the queue and play synthesized audio data
179       retVal = tts_play(mTtsHandle);
180       if(retVal != TTS_ERROR_NONE)
181       {
182         LogErrorCode(static_cast<tts_error_e>(retVal));
183       }
184     }
185   }
186   else
187   {
188     mUnplayedString = text;
189   }
190 }
191
192 void TtsPlayer::Stop()
193 {
194   if(mInitialized)
195   {
196     // Check the current TTS state
197     tts_state_e state;
198     int retVal = tts_get_state(mTtsHandle, &state);
199     if(retVal != TTS_ERROR_NONE)
200     {
201       LogErrorCode(static_cast<tts_error_e>(retVal));
202     }
203     else if(state == TTS_STATE_PLAYING || state == TTS_STATE_PAUSED)
204     {
205       // If it is playing or paused, stop playing and clear the queue
206       retVal = tts_stop(mTtsHandle);
207       if( retVal != TTS_ERROR_NONE )
208       {
209         LogErrorCode(static_cast<tts_error_e>(retVal));
210       }
211     }
212   }
213 }
214
215 void TtsPlayer::Pause()
216 {
217   if(mInitialized)
218   {
219     // Check the current TTS state
220     tts_state_e state;
221     int retVal = tts_get_state(mTtsHandle, &state);
222     if(retVal != TTS_ERROR_NONE)
223     {
224       LogErrorCode(static_cast<tts_error_e>(retVal));
225     }
226     else if(state == TTS_STATE_PLAYING)
227     {
228       // If the player is playing, pause it.
229       retVal = tts_pause(mTtsHandle);
230       if( retVal != TTS_ERROR_NONE )
231       {
232         LogErrorCode(static_cast<tts_error_e>(retVal));
233       }
234     }
235   }
236 }
237
238 void TtsPlayer::Resume()
239 {
240   if(mInitialized)
241   {
242     // Check the current TTS state
243     tts_state_e state;
244     int retVal = tts_get_state(mTtsHandle, &state);
245     if(retVal != TTS_ERROR_NONE)
246     {
247       LogErrorCode(static_cast<tts_error_e>(retVal));
248     }
249     else if(state == TTS_STATE_PAUSED)
250     {
251       // If the player is paused, resume it.
252       retVal = tts_play(mTtsHandle);
253       if( retVal != TTS_ERROR_NONE )
254       {
255         LogErrorCode(static_cast<tts_error_e>(retVal));
256       }
257     }
258   }
259 }
260
261 Dali::TtsPlayer::State TtsPlayer::GetState()
262 {
263   Dali::TtsPlayer::State ttsState = Dali::TtsPlayer::UNAVAILABLE;
264
265   if(mInitialized)
266   {
267     // Check the current TTS state
268     tts_state_e state;
269     int retVal = tts_get_state(mTtsHandle, &state);
270     if(retVal != TTS_ERROR_NONE)
271     {
272       LogErrorCode(static_cast<tts_error_e>(retVal));
273     }
274     else
275     {
276       ttsState = InternalToExternalState( state );
277     }
278   }
279
280   return ttsState;
281 }
282
283 Dali::TtsPlayer::StateChangedSignalType& TtsPlayer::StateChangedSignal()
284 {
285   return mStateChangedSignal;
286 }
287
288 void TtsPlayer::EmitStateChangedSignal( tts_state_e previous, tts_state_e current )
289 {
290   // Convert the previous and current states to external states and emit them as a signal.
291   if( !mStateChangedSignal.Empty() )
292   {
293     mStateChangedSignal.Emit( InternalToExternalState( previous ), InternalToExternalState( current ) );
294   }
295 }
296
297 void TtsPlayer::StateChangedCallback(tts_h tts, tts_state_e previous, tts_state_e current, void *userData)
298 {
299   // Get the implementation (this is a static function).
300   TtsPlayer* obj = static_cast<TtsPlayer*>(userData);
301
302   // Emit the signal.
303   obj->EmitStateChangedSignal( previous, current );
304
305   if(!obj->mInitialized && current == TTS_STATE_READY)
306   {
307     obj->mInitialized = true;
308
309     // if there is queued text before initialization, play it
310     if(obj->mUnplayedString != "")
311     {
312       obj->Play(obj->mUnplayedString);
313       obj->mUnplayedString = "";
314     }
315   }
316 }
317
318 void TtsPlayer::LogErrorCode(tts_error_e reason)
319 {
320   std::string error_string;
321
322   switch (reason)
323   {
324     case TTS_ERROR_NONE:
325     {
326       break;
327     }
328     case TTS_ERROR_OUT_OF_MEMORY:
329     {
330       error_string = "TTS: Out of Memory\n";
331       break;
332     }
333     case TTS_ERROR_IO_ERROR:
334     {
335       error_string = "TTS: I/O error\n";
336       break;
337     }
338     case TTS_ERROR_INVALID_PARAMETER:
339     {
340       error_string = "TTS: Invalid parameter\n";
341       break;
342     }
343     case TTS_ERROR_OUT_OF_NETWORK:
344     {
345       error_string = "TTS: Out of network\n";
346       break;
347     }
348     case TTS_ERROR_INVALID_STATE:
349     {
350       error_string = "TTS: Invalid state\n";
351       break;
352     }
353     case TTS_ERROR_INVALID_VOICE:
354     {
355       error_string = "TTS: Invalid voice\n";
356       break;
357     }
358     case TTS_ERROR_ENGINE_NOT_FOUND:
359     {
360       error_string = "TTS: No available engine\n";
361       break;
362     }
363     case TTS_ERROR_TIMED_OUT:
364     {
365       error_string = "TTS: No answer from the daemon\n";
366       break;
367     }
368     case TTS_ERROR_OPERATION_FAILED:
369     {
370       error_string = "TTS: Operation failed\n";
371       break;
372     }
373     default:
374     {
375       error_string = "Invalid TTS error code\n";
376       break;
377     }
378   }
379
380   if(reason != TTS_ERROR_NONE)
381   {
382     DALI_LOG_WARNING("[%s:%d] tts error : %s\n", __FUNCTION__, __LINE__, error_string.c_str());
383   }
384 }
385
386 } // namespace Adaptor
387
388 } // namespace Internal
389
390 } // namespace Dali