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