2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0/
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
18 #include <FBaseColArrayList.h>
19 #include <FBaseString.h>
20 #include <FBaseSysLog.h>
21 #include <FBaseUtilStringTokenizer.h>
22 #include <FLclLocale.h>
23 #include <FBase_StringConverter.h>
24 #include "FUi_AccessibilityTtsPlayer.h"
25 #include "FUi_AccessibilityManager.h"
27 using namespace Tizen::Base;
28 using namespace Tizen::Base::Collection;
29 using namespace Tizen::Locales;
31 namespace Tizen { namespace Ui {
33 _AccessibilityTtsPlayer::_AccessibilityTtsPlayer(_AccessibilityManager& manager)
34 : __initialized(false)
38 , __speed(TTS_SPEED_AUTO)
39 , __status(ACCESSIBILITY_SCREEN_READER_STATUS_ERROR)
41 , __pCurrentLocale(null)
42 , __pSupportedLocaleList(null)
43 , __pManager(&manager)
47 _AccessibilityTtsPlayer::~_AccessibilityTtsPlayer(void)
50 delete __pCurrentLocale;
52 if (__pSupportedLocaleList != null)
54 __pSupportedLocaleList->RemoveAll(true);
55 delete __pSupportedLocaleList;
60 _AccessibilityTtsPlayer::Construct(void)
62 Locale *pLocale = new (std::nothrow) Locale(LANGUAGE_INVALID, COUNTRY_INVALID);
63 SysTryReturnResult(NID_UI, pLocale != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
65 ArrayList* pLocaleList = new (std::nothrow) ArrayList();
66 SysTryReturnResult(NID_UI, pLocaleList != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
68 result r = pLocaleList->Construct();
69 SysTryReturnResult(NID_UI, r == E_SUCCESS, E_OUT_OF_MEMORY, "The memory is insufficient.");
71 __pCurrentLocale = pLocale;
72 __pSupportedLocaleList = pLocaleList;
78 _AccessibilityTtsPlayer::Activate(void)
82 SysLog(NID_UI, "TTS player was already activated.");
86 int ttsError = tts_create(&__ttsHandle);
87 SysTryReturnResult(NID_UI, ttsError == TTS_ERROR_NONE, E_SYSTEM, "Failed to create.");
89 ttsError = tts_set_error_cb(__ttsHandle, TtsErrorReceiver, (void*)(this));
90 SysTryReturnResult(NID_UI, ttsError == TTS_ERROR_NONE, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
92 ttsError = tts_set_state_changed_cb(__ttsHandle, TtsStateChangedReceiver, (void*)(this));
93 SysTryReturnResult(NID_UI, ttsError == TTS_ERROR_NONE, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
95 ttsError = tts_set_utterance_started_cb(__ttsHandle, TtsStartedReceiver, (void*)(this));
96 SysTryReturnResult(NID_UI, ttsError == TTS_ERROR_NONE, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
98 ttsError = tts_set_utterance_completed_cb(__ttsHandle, TtsCompletedReceiver, (void*)(this));
99 SysTryReturnResult(NID_UI, ttsError == TTS_ERROR_NONE, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
101 tts_set_mode(__ttsHandle, TTS_MODE_SCREEN_READER);
103 ttsError = tts_prepare(__ttsHandle);
104 SysTryReturnResult(NID_UI, ttsError == TTS_ERROR_NONE, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
111 _AccessibilityTtsPlayer::GetEngineStateMessage(const tts_state_e state)
115 case TTS_STATE_CREATED:
118 case TTS_STATE_READY:
121 case TTS_STATE_PLAYING:
124 case TTS_STATE_PAUSED:
133 _AccessibilityTtsPlayer::GetEngineErrorMessage(const int errorType)
138 return "TTS_ERROR_NONE";
140 case TTS_ERROR_OUT_OF_MEMORY:
141 return "TTS_ERROR_OUT_OF_MEMORY";
143 case TTS_ERROR_IO_ERROR:
144 return "TTS_ERROR_IO_ERROR";
146 case TTS_ERROR_INVALID_PARAMETER:
147 return "TTS_ERROR_INVALID_PARAMETER";
149 case TTS_ERROR_INVALID_STATE:
150 return "TTS_ERROR_INVALID_STATE";
152 case TTS_ERROR_INVALID_VOICE:
153 return "TTS_ERROR_INVALID_VOICE";
155 case TTS_ERROR_ENGINE_NOT_FOUND:
156 return "TTS_ERROR_ENGINE_NOT_FOUND";
158 case TTS_ERROR_TIMED_OUT:
159 return "TTS_ERROR_TIMED_OUT";
161 case TTS_ERROR_OPERATION_FAILED:
162 return "TTS_ERROR_OPERATION_FAILED";
165 return "TTS_ERROR_UNKNOWN_ERROR";
170 _AccessibilityTtsPlayer::TtsStateChangedReceiver(tts_h ttsHandle, tts_state_e previousState, tts_state_e currentState, void* pTtsInstance)
172 SysLog(NID_UI, "[Accessibility TTS] [%s] ---> [%s]", GetEngineStateMessage(previousState), GetEngineStateMessage(currentState));
174 if ((previousState == TTS_STATE_CREATED) && (currentState == TTS_STATE_READY))
176 char *pDefaultLang = null;
177 tts_voice_type_e defaultVoiceType;
179 int ttsError = tts_get_default_voice(ttsHandle, &pDefaultLang, &defaultVoiceType);
180 if (ttsError == TTS_ERROR_NONE)
182 SysLog(NID_UI, "Default language[%s] and voice[%d]", pDefaultLang, defaultVoiceType);
183 const Locale* pDefaultLocale = ConvertEngineLocaleToNativeN(pDefaultLang);
186 delete static_cast<_AccessibilityTtsPlayer*>(pTtsInstance)->__pCurrentLocale;
187 static_cast<_AccessibilityTtsPlayer*>(pTtsInstance)->__pCurrentLocale = const_cast<Locale*>(pDefaultLocale);
192 ttsError = tts_foreach_supported_voices(ttsHandle, TtsSupportedLocaleListGetter, (void*)(static_cast<_AccessibilityTtsPlayer*>(pTtsInstance)->__pSupportedLocaleList));
193 SysTryLog(NID_UI, ttsError == TTS_ERROR_NONE, "[%s] Failed to get supported voices", GetEngineErrorMessage(ttsError));
195 static_cast<_AccessibilityTtsPlayer*>(pTtsInstance)->__initialized = true;
196 static_cast<_AccessibilityTtsPlayer*>(pTtsInstance)->OnStatusChanged(ACCESSIBILITY_SCREEN_READER_STATUS_READY);
198 else if ((previousState == TTS_STATE_READY || previousState == TTS_STATE_PAUSED) && (currentState == TTS_STATE_PLAYING))
200 static_cast<_AccessibilityTtsPlayer*>(pTtsInstance)->OnStatusChanged(ACCESSIBILITY_SCREEN_READER_STATUS_PLAYING);
202 else if ((previousState == TTS_STATE_PLAYING) && (currentState == TTS_STATE_PAUSED))
204 static_cast<_AccessibilityTtsPlayer*>(pTtsInstance)->OnStatusChanged(ACCESSIBILITY_SCREEN_READER_STATUS_PAUSE);
206 else if ((previousState == TTS_STATE_PLAYING || previousState == TTS_STATE_PAUSED) && (currentState == TTS_STATE_READY))
208 static_cast<_AccessibilityTtsPlayer*>(pTtsInstance)->OnStatusChanged(ACCESSIBILITY_SCREEN_READER_STATUS_READY);
212 SysLog(NID_UI, "[CB] Unknown state. / [%s] ---> [%s]",
213 GetEngineStateMessage(previousState), GetEngineStateMessage(currentState));
217 _AccessibilityTtsPlayer::TtsStartedReceiver(tts_h ttsHandle, int utteranceId, void* pListener)
219 SysLog(NID_UI, "Accessibility TTS reader is started", utteranceId);
222 _AccessibilityTtsPlayer::TtsCompletedReceiver(tts_h ttsHandle, int utteranceId, void* pTtsInstance)
224 int ttsError = tts_stop(ttsHandle);
225 SysTryReturnVoidResult(NID_UI, ttsError == TTS_ERROR_NONE, E_SYSTEM,
226 "[CB] Failed to stop, error[%s]", GetEngineErrorMessage(ttsError));
227 _AccessibilityTtsPlayer* pPlayer = static_cast<_AccessibilityTtsPlayer*>(pTtsInstance);
228 pPlayer->SetStatus(ACCESSIBILITY_SCREEN_READER_STATUS_READY);
229 pPlayer->__pManager->OnFinishReading(pPlayer->__grammar);
232 _AccessibilityTtsPlayer::TtsErrorReceiver(tts_h ttsHandle, int ttsUtteranceId, tts_error_e error, void* pTtsInstance)
234 Tizen::Base::String errorMessage =L"";
237 case TTS_ERROR_OUT_OF_MEMORY:
238 errorMessage = L"TEXT_TO_SPEECH_ERROR_OUT_OF_MEMORY";
240 case TTS_ERROR_IO_ERROR:
241 errorMessage = L"TEXT_TO_SPEECH_ERROR_IO_ERROR";
243 case TTS_ERROR_OUT_OF_NETWORK:
244 errorMessage = L"TEXT_TO_SPEECH_ERROR_NETWORK_ERROR";
246 case TTS_ERROR_ENGINE_NOT_FOUND:
247 errorMessage = L"TEXT_TO_SPEECH_ERROR_UNSUPPORTED_SERVICE";
249 case TTS_ERROR_TIMED_OUT:
250 errorMessage = L"TEXT_TO_SPEECH_ERROR_TIME_OUT";
253 errorMessage = L"TEXT_TO_SPEECH_ERROR_SYSTEM_ERROR";
256 static_cast<_AccessibilityTtsPlayer*>(pTtsInstance)->OnErrorOccurred(errorMessage);
259 _AccessibilityTtsPlayer::TtsSupportedLocaleListGetter(tts_h ttsHandle, const char* pLanguage, tts_voice_type_e voiceType, void* pLocaleList)
261 const Locale* pLocale = ConvertEngineLocaleToNativeN(String(pLanguage));
264 static_cast <ArrayList*>(pLocaleList)->RemoveAll(true);
268 if (pLocale->GetLanguageCode() == LANGUAGE_INVALID)
270 SysLog(NID_UI, "[CB] Not support language[%s]", pLanguage);
275 result r = static_cast<ArrayList*>(pLocaleList)->Add(*pLocale);
278 static_cast<ArrayList*>(pLocaleList)->RemoveAll(true);
285 _AccessibilityTtsPlayer::ConvertTizenLocaleToEngineN(const Tizen::Locales::Locale& locale)
287 String strLanguageCode = Locale::LanguageCodeToTwoLetterLanguageCodeString(locale.GetLanguageCode());
288 String strCountryCode = Locale::CountryCodeToString(locale.GetCountryCode());
289 String strLanguage = strLanguageCode + L"_" + strCountryCode;
291 return _StringConverter::CopyToCharArrayN(strLanguage);
293 const Tizen::Locales::Locale*
294 _AccessibilityTtsPlayer::ConvertEngineLocaleToNativeN(const Tizen::Base::String& strSource)
296 String strDelim(L"_");
297 String strLanguageCode;
298 String strCountryCode;
300 LanguageCode languageCode = LANGUAGE_INVALID;
301 CountryCode countryCode = COUNTRY_INVALID;
303 Utility::StringTokenizer toknizer(strSource, strDelim);
304 if (toknizer.GetTokenCount() == 2)
306 toknizer.GetNextToken(strLanguageCode);
307 toknizer.GetNextToken(strCountryCode);
309 languageCode = Locale::TwoLetterLanguageCodeStringToLanguageCode(strLanguageCode);
310 countryCode = Locale::StringToCountryCode(strCountryCode);
313 return new (std::nothrow) Locale(languageCode, countryCode);
317 _AccessibilityTtsPlayer::Speak(const String& text)
319 SysTryReturnResult(NID_UI, __initialized , E_INVALID_STATE,
320 "Not yet initialized! This method should be called after initialized.");
322 result r = E_SUCCESS;
323 tts_state_e ttsState = TTS_STATE_READY;
325 int ttsError = tts_get_state(__ttsHandle, &ttsState);
326 SysTryReturnResult(NID_UI, ttsError == TTS_ERROR_NONE, E_SYSTEM, "Failed to get the current state.");
329 const char* pTextN = _StringConverter::CopyToCharArrayN(text);
330 int ttsUtteranceId = 0;
332 ttsError = tts_add_text(__ttsHandle, pTextN, null, TTS_VOICE_TYPE_AUTO, __speed, &ttsUtteranceId);
333 SysTryCatch(NID_UI, ttsError == TTS_ERROR_NONE, r = E_OUT_OF_MEMORY, E_SYSTEM, "[E_SYSTEM] Failed to add a text.");
334 ttsError = tts_play(__ttsHandle);
335 SysTryCatch(NID_UI, ttsError == TTS_ERROR_NONE, r = E_SYSTEM, E_SYSTEM, "[%s] Failed to play.", GetEngineErrorMessage(ttsError));
337 OnStatusChanged(ACCESSIBILITY_SCREEN_READER_STATUS_PLAYING);
346 _AccessibilityTtsPlayer::Stop(void)
348 SysTryReturnResult(NID_UI, __initialized , E_INVALID_STATE,
349 "Not yet initialized! This method should be called after initialized.");
351 tts_state_e ttsState = TTS_STATE_READY;
353 int ttsError = tts_get_state(__ttsHandle, &ttsState);
354 SysTryReturnResult(NID_UI, ttsError == TTS_ERROR_NONE, E_SYSTEM, "Failed to get the current state.");
355 ttsError = tts_stop(__ttsHandle);
356 SysTryReturnResult(NID_UI, ttsError == TTS_ERROR_NONE, E_SYSTEM, "Failed to stop.");
362 _AccessibilityTtsPlayer::Pause(void)
364 SysTryReturnResult(NID_UI, __initialized , E_INVALID_STATE,
365 "Not yet initialized! This method should be called after initialized.");
367 tts_state_e ttsState = TTS_STATE_READY;
369 int ttsError = tts_get_state(__ttsHandle, &ttsState);
370 SysTryReturnResult(NID_UI, ttsError == TTS_ERROR_NONE, E_SYSTEM, "Failed to get the current state.");
371 SysTryReturnResult(NID_UI, ttsState == TTS_STATE_PLAYING, E_INVALID_OPERATION, "The TTS state should be TTS_STATUS_PLAYING.");
373 ttsError = tts_pause(__ttsHandle);
374 SysTryReturnResult(NID_UI, ttsError == TTS_ERROR_NONE, E_SYSTEM, "Failed to pause.");
380 _AccessibilityTtsPlayer::Resume(void)
382 SysTryReturnResult(NID_UI, __initialized , E_INVALID_STATE,
383 "Not yet initialized! This method should be called after initialized.");
385 tts_state_e ttsState = TTS_STATE_READY;
387 int ttsError = tts_get_state(__ttsHandle, &ttsState);
388 SysTryReturnResult(NID_UI, ttsError == TTS_ERROR_NONE, E_SYSTEM, "Failed to get the current state.");
389 SysTryReturnResult(NID_UI, ttsState == TTS_STATE_PAUSED, E_INVALID_OPERATION, "The TTS state should be TTS_STATUS_PAUSED.");
391 ttsError = tts_play(__ttsHandle);
392 SysTryReturnResult(NID_UI, ttsError == TTS_ERROR_NONE, E_SYSTEM, "Failed to resume.");
398 _AccessibilityTtsPlayer::SetLocale(const Locale& locale)
400 SysTryReturnResult(NID_UI, __initialized , E_INVALID_STATE,
401 "Not yet initialized! This method should be called after initialized.");
402 SysTryReturnResult(NID_UI, __pSupportedLocaleList->Contains(locale), E_UNSUPPORTED_LOCALE, "This locale is not supported.");
404 *__pCurrentLocale = locale;
408 Tizen::Locales::Locale
409 _AccessibilityTtsPlayer::GetLocale(void) const
411 SysTryReturn(NID_UI, __initialized, Locale(LANGUAGE_INVALID, COUNTRY_INVALID), E_INVALID_STATE,
412 "[E_INVALID_STATE] Not yet initialized! This method should be called after initialized.");
414 SetLastResult(E_SUCCESS);
415 return *__pCurrentLocale;
418 const Tizen::Base::Collection::IList*
419 _AccessibilityTtsPlayer::GetSupportedLocales(void) const
421 SysTryReturnResult(NID_UI, __initialized , null,
422 "Not yet initialized! This method should be called after initialized.");
424 SetLastResult(E_SUCCESS);
425 return __pSupportedLocaleList->GetCount() > 0 ? __pSupportedLocaleList : null;
429 _AccessibilityTtsPlayer::IsLocaleSupported(const Tizen::Locales::Locale& locale) const
431 SysTryReturnResult(NID_UI, __initialized , E_INVALID_STATE,
432 "Not yet initialized! This method should be called after initialized.");
434 SetLastResult(E_SUCCESS);
435 return __pSupportedLocaleList->Contains(locale);
439 _AccessibilityTtsPlayer::SetSpeechRate(tts_speed_e speechRate)
441 SysTryReturnResult(NID_UI, __initialized , E_INVALID_STATE,
442 "Not yet initialized! This method should be called after initialized.");
444 __speed = speechRate;
450 _AccessibilityTtsPlayer::ReadGrammar(const Tizen::Base::String& grammar, bool init)
452 if(grammar.GetLength() == 0)
456 if(init && GetStatus() == ACCESSIBILITY_SCREEN_READER_STATUS_PLAYING)
460 SetStatus(ACCESSIBILITY_SCREEN_READER_STATUS_PLAYING);
466 _AccessibilityTtsPlayer::StopReading(void)
471 AccessibilityScreenReaderStatus
472 _AccessibilityTtsPlayer::GetStatus(void)
477 _AccessibilityTtsPlayer::GetCurrentGrammar(void)
483 _AccessibilityTtsPlayer::Deactivate(void)
485 __initialized = false;
486 tts_state_e ttsState = TTS_STATE_READY;
488 int ttsError = tts_get_state(__ttsHandle, &ttsState);
489 SysTryLog(NID_UI, ttsError == TTS_ERROR_NONE, "[%s] Failed to get the current state.", GetEngineErrorMessage(ttsError));
491 if (ttsState == TTS_STATE_PLAYING || ttsState == TTS_STATE_PAUSED)
493 ttsError = tts_stop(__ttsHandle);
494 SysTryLog(NID_UI, ttsError == TTS_ERROR_NONE, "[%s] Failed to stop.", GetEngineErrorMessage(ttsError));
498 ttsError = tts_unprepare(__ttsHandle);
499 SysTryLog(NID_UI, ttsError == TTS_ERROR_NONE, "[%s] Failed to unprepare.", GetEngineErrorMessage(ttsError));
501 ttsError = tts_unset_utterance_completed_cb(__ttsHandle);
502 SysTryLog(NID_UI, ttsError == TTS_ERROR_NONE, "[%s] Failed to unset the utterance completed callback.", GetEngineErrorMessage(ttsError));
504 ttsError = tts_unset_utterance_started_cb(__ttsHandle);
505 SysTryLog(NID_UI, ttsError == TTS_ERROR_NONE, "[%s] Failed to unset the utterance started callback.", GetEngineErrorMessage(ttsError));
507 ttsError = tts_unset_state_changed_cb(__ttsHandle);
508 SysTryLog(NID_UI, ttsError == TTS_ERROR_NONE, "[%s] Failed to unset the state changed callback.", GetEngineErrorMessage(ttsError));
510 ttsError = tts_unset_error_cb(__ttsHandle);
511 SysTryLog(NID_UI, ttsError == TTS_ERROR_NONE, "[%s] Failed to unset the error callback.", GetEngineErrorMessage(ttsError));
513 ttsError = tts_destroy(__ttsHandle);
514 SysTryLog(NID_UI, ttsError == TTS_ERROR_NONE, "[%s] Failed to destroy.", GetEngineErrorMessage(ttsError));
522 _AccessibilityTtsPlayer::OnErrorOccurred(Tizen::Base::String& errorString)
526 _AccessibilityTtsPlayer::OnStatusChanged(AccessibilityScreenReaderStatus status)
530 case ACCESSIBILITY_SCREEN_READER_STATUS_PLAYING:
531 __pManager->OnStartReading(__grammar);
540 _AccessibilityTtsPlayer::SetStatus(AccessibilityScreenReaderStatus status)