Merge pull request #26273 from 78andyp/blurayfixes2
[xbmc.git] / xbmc / platform / android / speech / SpeechRecognitionAndroid.cpp
blob7a2377b9e4c90a55f30b7b4bdc8f53cd171d43cd
1 /*
2 * Copyright (C) 2012-2022 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "SpeechRecognitionAndroid.h"
11 #include "speech/ISpeechRecognitionListener.h"
12 #include "speech/SpeechRecognitionErrors.h"
13 #include "utils/log.h"
15 #include "platform/android/activity/JNIMainActivity.h"
16 #include "platform/android/activity/XBMCApp.h"
17 #include "platform/android/speech/SpeechRecognitionListenerAndroid.h"
19 #include <mutex>
21 #include <androidjni/Context.h>
22 #include <androidjni/Intent.h>
23 #include <androidjni/IntentFilter.h>
24 #include <androidjni/PackageManager.h>
25 #include <androidjni/RecognizerIntent.h>
26 #include <androidjni/SpeechRecognizer.h>
27 #include <jni.h>
29 std::shared_ptr<speech::ISpeechRecognition> speech::ISpeechRecognition::CreateInstance()
31 return std::make_shared<CSpeechRecognitionAndroid>(CXBMCApp::Get());
34 CSpeechRecognitionAndroid::CSpeechRecognitionAndroid(const CJNIContext& context)
35 : m_context(context)
39 CSpeechRecognitionAndroid::~CSpeechRecognitionAndroid()
43 void CSpeechRecognitionAndroid::StartSpeechRecognition(
44 const std::shared_ptr<speech::ISpeechRecognitionListener>& listener)
46 if (CJNISpeechRecognizer::isRecognitionAvailable(m_context))
48 if (CJNIContext::checkCallingOrSelfPermission("android.permission.RECORD_AUDIO") ==
49 CJNIPackageManager::PERMISSION_GRANTED)
51 std::unique_lock<CCriticalSection> lock(m_speechRecognitionListenersMutex);
52 m_speechRecognitionListeners.emplace_back(
53 std::make_unique<CSpeechRecognitionListenerAndroid>(listener, *this));
54 lock.unlock();
56 // speech recognizer init must be called from the main thread:
57 // https://developer.android.com/reference/android/speech/SpeechRecognizer
58 jni::CJNIMainActivity::runNativeOnUiThread(RegisterSpeechRecognitionListener, this);
60 else
62 CLog::LogF(LOGERROR, "Permission RECORD_AUDIO is not granted");
63 listener->OnError(speech::RecognitionError::INSUFFICIENT_PERMISSIONS);
66 else
68 CLog::LogF(LOGERROR, "Speech recognition service is not available");
69 listener->OnError(speech::RecognitionError::SERVICE_NOT_AVAILABLE);
73 void CSpeechRecognitionAndroid::RegisterSpeechRecognitionListener(void* thiz)
75 CSpeechRecognitionAndroid* sra = static_cast<CSpeechRecognitionAndroid*>(thiz);
77 CJNISpeechRecognizer speechRecognizer =
78 CJNISpeechRecognizer::createSpeechRecognizer(sra->m_context);
80 std::unique_lock<CCriticalSection> lock(sra->m_speechRecognitionListenersMutex);
81 speechRecognizer.setRecognitionListener(*(sra->m_speechRecognitionListeners.back()));
82 lock.unlock();
84 CJNIIntent intent = CJNIIntent(CJNIRecognizerIntent::ACTION_RECOGNIZE_SPEECH);
85 intent.putExtra(CJNIRecognizerIntent::EXTRA_LANGUAGE_MODEL,
86 CJNIRecognizerIntent::LANGUAGE_MODEL_FREE_FORM);
88 speechRecognizer.startListening(intent);
91 void CSpeechRecognitionAndroid::SpeechRecognitionDone(
92 jni::CJNIXBMCSpeechRecognitionListener* listener)
94 std::unique_lock<CCriticalSection> lock(m_speechRecognitionListenersMutex);
95 for (auto it = m_speechRecognitionListeners.begin(); it != m_speechRecognitionListeners.end();
96 ++it)
98 if ((*it).get() == listener)
100 m_speechRecognitionListeners.erase(it);
101 break;