Merge branch 'devel/master' into tizen
[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   mUtteranceId(0),
87   mTtsMode(mode)
88 {
89   Initialize();
90 }
91
92 TtsPlayer::~TtsPlayer()
93 {
94   // If it is playing, stop it
95   Stop();
96
97   // Unset the callback funtion for TTS state change
98   int retVal = tts_unset_state_changed_cb(mTtsHandle);
99   if( retVal != TTS_ERROR_NONE )
100   {
101     LogErrorCode(static_cast<tts_error_e>(retVal));
102   }
103
104   // Destroy the TTS handle and disconnects the daemon
105   retVal = tts_destroy(mTtsHandle);
106   if( retVal != TTS_ERROR_NONE )
107   {
108     LogErrorCode(static_cast<tts_error_e>(retVal));
109   }
110 }
111
112 void TtsPlayer::Initialize()
113 {
114   // Create the TTS handle
115   int retVal = tts_create(&mTtsHandle);
116
117   if( retVal != TTS_ERROR_NONE )
118   {
119     LogErrorCode(static_cast<tts_error_e>(retVal));
120   }
121   else
122   {
123     // Set the callback funtion for TTS state change
124     retVal = tts_set_state_changed_cb(mTtsHandle, &StateChangedCallback, this);
125     if( retVal != TTS_ERROR_NONE )
126     {
127       LogErrorCode(static_cast<tts_error_e>(retVal));
128     }
129
130     // Check tts mode
131     tts_mode_e ttsMode = TTS_MODE_DEFAULT;
132     switch (mTtsMode)
133     {
134       case Dali::TtsPlayer::DEFAULT:
135         ttsMode = TTS_MODE_DEFAULT;
136       break;
137       case Dali::TtsPlayer::NOTIFICATION:
138         ttsMode = TTS_MODE_NOTIFICATION;
139       break;
140       case Dali::TtsPlayer::SCREEN_READER:
141         ttsMode = TTS_MODE_SCREEN_READER;
142       break;
143       default:
144       break;
145     }
146
147     // Set mode
148     retVal = tts_set_mode(mTtsHandle, ttsMode);
149     if(retVal != TTS_ERROR_NONE)
150     {
151       LogErrorCode(static_cast<tts_error_e>(retVal));
152     }
153
154     // Connect the TTS daemon asynchronously
155     retVal = tts_prepare(mTtsHandle);
156     if(retVal != TTS_ERROR_NONE)
157     {
158       LogErrorCode(static_cast<tts_error_e>(retVal));
159     }
160   }
161 }
162
163 void TtsPlayer::Play(const std::string& text)
164 {
165   if(mInitialized)
166   {
167     Stop();
168
169     // Add text to the queue, and use normal speed, default language and default voice set by the user
170     int retVal = tts_add_text(mTtsHandle, text.c_str(), NULL, TTS_VOICE_TYPE_AUTO, TTS_SPEED_AUTO, &mUtteranceId);
171     if(retVal != TTS_ERROR_NONE)
172     {
173       LogErrorCode(static_cast<tts_error_e>(retVal));
174     }
175     else
176     {
177       // Start synthesizing voice from text in the queue and play synthesized audio data
178       retVal = tts_play(mTtsHandle);
179       if(retVal != TTS_ERROR_NONE)
180       {
181         LogErrorCode(static_cast<tts_error_e>(retVal));
182       }
183     }
184   }
185   else
186   {
187     mUnplayedString = text;
188   }
189 }
190
191 void TtsPlayer::Stop()
192 {
193   if(mInitialized)
194   {
195     // Check the current TTS state
196     tts_state_e state;
197     int retVal = tts_get_state(mTtsHandle, &state);
198     if(retVal != TTS_ERROR_NONE)
199     {
200       LogErrorCode(static_cast<tts_error_e>(retVal));
201     }
202     else if(state == TTS_STATE_PLAYING || state == TTS_STATE_PAUSED)
203     {
204       // If it is playing or paused, stop playing and clear the queue
205       retVal = tts_stop(mTtsHandle);
206       if( retVal != TTS_ERROR_NONE )
207       {
208         LogErrorCode(static_cast<tts_error_e>(retVal));
209       }
210     }
211   }
212 }
213
214 void TtsPlayer::Pause()
215 {
216   if(mInitialized)
217   {
218     // Check the current TTS state
219     tts_state_e state;
220     int retVal = tts_get_state(mTtsHandle, &state);
221     if(retVal != TTS_ERROR_NONE)
222     {
223       LogErrorCode(static_cast<tts_error_e>(retVal));
224     }
225     else if(state == TTS_STATE_PLAYING)
226     {
227       // If the player is playing, pause it.
228       retVal = tts_pause(mTtsHandle);
229       if( retVal != TTS_ERROR_NONE )
230       {
231         LogErrorCode(static_cast<tts_error_e>(retVal));
232       }
233     }
234   }
235 }
236
237 void TtsPlayer::Resume()
238 {
239   if(mInitialized)
240   {
241     // Check the current TTS state
242     tts_state_e state;
243     int retVal = tts_get_state(mTtsHandle, &state);
244     if(retVal != TTS_ERROR_NONE)
245     {
246       LogErrorCode(static_cast<tts_error_e>(retVal));
247     }
248     else if(state == TTS_STATE_PAUSED)
249     {
250       // If the player is paused, resume it.
251       retVal = tts_play(mTtsHandle);
252       if( retVal != TTS_ERROR_NONE )
253       {
254         LogErrorCode(static_cast<tts_error_e>(retVal));
255       }
256     }
257   }
258 }
259
260 Dali::TtsPlayer::State TtsPlayer::GetState()
261 {
262   Dali::TtsPlayer::State ttsState = Dali::TtsPlayer::UNAVAILABLE;
263
264   if(mInitialized)
265   {
266     // Check the current TTS state
267     tts_state_e state;
268     int retVal = tts_get_state(mTtsHandle, &state);
269     if(retVal != TTS_ERROR_NONE)
270     {
271       LogErrorCode(static_cast<tts_error_e>(retVal));
272     }
273     else
274     {
275       ttsState = InternalToExternalState( state );
276     }
277   }
278
279   return ttsState;
280 }
281
282 Dali::TtsPlayer::StateChangedSignalType& TtsPlayer::StateChangedSignal()
283 {
284   return mStateChangedSignal;
285 }
286
287 void TtsPlayer::EmitStateChangedSignal( tts_state_e previous, tts_state_e current )
288 {
289   // Convert the previous and current states to external states and emit them as a signal.
290   if( !mStateChangedSignal.Empty() )
291   {
292     mStateChangedSignal.Emit( InternalToExternalState( previous ), InternalToExternalState( current ) );
293   }
294 }
295
296 void TtsPlayer::StateChangedCallback(tts_h tts, tts_state_e previous, tts_state_e current, void *userData)
297 {
298   // Get the implementation (this is a static function).
299   TtsPlayer* obj = static_cast<TtsPlayer*>(userData);
300
301   // Emit the signal.
302   obj->EmitStateChangedSignal( previous, current );
303
304   if(!obj->mInitialized && current == TTS_STATE_READY)
305   {
306     obj->mInitialized = true;
307
308     // if there is queued text before initialization, play it
309     if(obj->mUnplayedString != "")
310     {
311       obj->Play(obj->mUnplayedString);
312       obj->mUnplayedString = "";
313     }
314   }
315 }
316
317 void TtsPlayer::LogErrorCode(tts_error_e reason)
318 {
319   std::string error_string;
320
321   switch (reason)
322   {
323     case TTS_ERROR_NONE:
324     {
325       break;
326     }
327     case TTS_ERROR_OUT_OF_MEMORY:
328     {
329       error_string = "TTS: Out of Memory\n";
330       break;
331     }
332     case TTS_ERROR_IO_ERROR:
333     {
334       error_string = "TTS: I/O error\n";
335       break;
336     }
337     case TTS_ERROR_INVALID_PARAMETER:
338     {
339       error_string = "TTS: Invalid parameter\n";
340       break;
341     }
342     case TTS_ERROR_OUT_OF_NETWORK:
343     {
344       error_string = "TTS: Out of network\n";
345       break;
346     }
347     case TTS_ERROR_INVALID_STATE:
348     {
349       error_string = "TTS: Invalid state\n";
350       break;
351     }
352     case TTS_ERROR_INVALID_VOICE:
353     {
354       error_string = "TTS: Invalid voice\n";
355       break;
356     }
357     case TTS_ERROR_ENGINE_NOT_FOUND:
358     {
359       error_string = "TTS: No available engine\n";
360       break;
361     }
362     case TTS_ERROR_TIMED_OUT:
363     {
364       error_string = "TTS: No answer from the daemon\n";
365       break;
366     }
367     case TTS_ERROR_OPERATION_FAILED:
368     {
369       error_string = "TTS: Operation failed\n";
370       break;
371     }
372     default:
373     {
374       error_string = "Invalid TTS error code\n";
375       break;
376     }
377   }
378
379   if(reason != TTS_ERROR_NONE)
380   {
381     DALI_LOG_WARNING("[%s:%d] tts error : %s\n", __FUNCTION__, __LINE__, error_string.c_str());
382   }
383 }
384
385 } // namespace Adaptor
386
387 } // namespace Internal
388
389 } // namespace Dali