| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/speech/tts_chromeos.h" |
| |
| #include <algorithm> |
| #include <utility> |
| |
| #include "base/strings/string_number_conversions.h" |
| #include "components/arc/arc_service_manager.h" |
| #include "components/arc/mojom/tts.mojom.h" |
| #include "components/arc/session/arc_bridge_service.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/tts_platform.h" |
| |
| void TtsPlatformImplChromeOs::SetVoices( |
| std::vector<content::VoiceData> voices) { |
| std::sort(voices.begin(), voices.end(), [](const auto& v1, const auto& v2) { |
| return !v1.remote && v2.remote; |
| }); |
| voices_ = std::move(voices); |
| received_word_event_ = false; |
| } |
| |
| void TtsPlatformImplChromeOs::ReceivedWordEvent() { |
| if (received_word_event_) |
| return; |
| |
| received_word_event_ = true; |
| for (auto& voice : voices_) |
| voice.events.insert(content::TTS_EVENT_WORD); |
| |
| content::TtsController::GetInstance()->VoicesChanged(); |
| } |
| |
| TtsPlatformImplChromeOs::TtsPlatformImplChromeOs() = default; |
| TtsPlatformImplChromeOs::~TtsPlatformImplChromeOs() = default; |
| |
| bool TtsPlatformImplChromeOs::PlatformImplSupported() { |
| // TODO(1133813): Chrome OS Platform should support background initialisation. |
| return arc::ArcServiceManager::Get() && arc::ArcServiceManager::Get() |
| ->arc_bridge_service() |
| ->tts() |
| ->IsConnected(); |
| } |
| |
| bool TtsPlatformImplChromeOs::PlatformImplInitialized() { |
| // On Chrome OS, the extension-based voices are really the platform level |
| // voices. ARC++ takes a while to load, so do not block TtsController from |
| // processing and speaking utterances here. |
| return true; |
| } |
| |
| void TtsPlatformImplChromeOs::LoadBuiltInTtsEngine( |
| content::BrowserContext* browser_context) { |
| content::TtsEngineDelegate* tts_engine_delegate = |
| content::TtsController::GetInstance()->GetTtsEngineDelegate(); |
| if (tts_engine_delegate) |
| tts_engine_delegate->LoadBuiltInTtsEngine(browser_context); |
| } |
| |
| void TtsPlatformImplChromeOs::Speak( |
| int utterance_id, |
| const std::string& utterance, |
| const std::string& lang, |
| const content::VoiceData& voice, |
| const content::UtteranceContinuousParameters& params, |
| base::OnceCallback<void(bool)> on_speak_finished) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| |
| // Parse SSML and process speech. |
| content::TtsController::GetInstance()->StripSSML( |
| utterance, base::BindOnce(&TtsPlatformImplChromeOs::ProcessSpeech, |
| base::Unretained(this), utterance_id, lang, |
| voice, params, std::move(on_speak_finished))); |
| } |
| |
| void TtsPlatformImplChromeOs::ProcessSpeech( |
| int utterance_id, |
| const std::string& lang, |
| const content::VoiceData& voice, |
| const content::UtteranceContinuousParameters& params, |
| base::OnceCallback<void(bool)> on_speak_finished, |
| const std::string& parsed_utterance) { |
| auto* const arc_service_manager = arc::ArcServiceManager::Get(); |
| if (!arc_service_manager) { |
| std::move(on_speak_finished).Run(false); |
| return; |
| } |
| arc::mojom::TtsInstance* tts = ARC_GET_INSTANCE_FOR_METHOD( |
| arc_service_manager->arc_bridge_service()->tts(), Speak); |
| if (!tts) { |
| std::move(on_speak_finished).Run(false); |
| return; |
| } |
| |
| arc::mojom::TtsUtterancePtr arc_utterance = arc::mojom::TtsUtterance::New(); |
| arc_utterance->utteranceId = utterance_id; |
| arc_utterance->text = parsed_utterance; |
| arc_utterance->rate = params.rate; |
| arc_utterance->pitch = params.pitch; |
| int voice_id = 0; |
| if (!voice.native_voice_identifier.empty() && |
| base::StringToInt(voice.native_voice_identifier, &voice_id)) { |
| arc_utterance->voice_id = voice_id; |
| } |
| |
| tts->Speak(std::move(arc_utterance)); |
| std::move(on_speak_finished).Run(true); |
| } |
| |
| bool TtsPlatformImplChromeOs::StopSpeaking() { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| auto* const arc_service_manager = arc::ArcServiceManager::Get(); |
| if (!arc_service_manager) |
| return false; |
| arc::mojom::TtsInstance* tts = ARC_GET_INSTANCE_FOR_METHOD( |
| arc_service_manager->arc_bridge_service()->tts(), Stop); |
| if (!tts) |
| return false; |
| |
| tts->Stop(); |
| return true; |
| } |
| |
| void TtsPlatformImplChromeOs::GetVoices( |
| std::vector<content::VoiceData>* out_voices) { |
| for (const auto& voice : voices_) |
| out_voices->push_back(voice); |
| } |
| |
| std::string TtsPlatformImplChromeOs::GetError() { |
| return error_; |
| } |
| |
| void TtsPlatformImplChromeOs::ClearError() { |
| error_ = std::string(); |
| } |
| |
| void TtsPlatformImplChromeOs::SetError(const std::string& error) { |
| error_ = error; |
| } |
| |
| bool TtsPlatformImplChromeOs::IsSpeaking() { |
| return false; |
| } |
| |
| // static |
| TtsPlatformImplChromeOs* |
| TtsPlatformImplChromeOs::GetInstance() { |
| static base::NoDestructor<TtsPlatformImplChromeOs> tts_platform; |
| return tts_platform.get(); |
| } |