From 2d2a4804f7790f41a8b9af373c5274ff73e7c84c Mon Sep 17 00:00:00 2001 From: Gabriel Calero Date: Thu, 6 Sep 2018 17:49:52 -0300 Subject: [PATCH 01/12] Add android settings screen. Add AEC setting --- android/app/src/main/AndroidManifest.xml | 10 +++ android/app/src/main/cpp/native.cpp | 46 ++++++++++++++ .../hifiinterface/InterfaceActivity.java | 7 +++ .../hifiinterface/MainActivity.java | 23 +++++++ .../fragment/SettingsFragment.java | 63 +++++++++++++++++++ .../receiver/HeadsetStateReceiver.java | 20 ++++++ .../app/src/main/res/menu/menu_navigation.xml | 5 ++ android/app/src/main/res/values/strings.xml | 5 ++ android/app/src/main/res/xml/settings.xml | 11 ++++ interface/src/AndroidHelper.cpp | 17 +++++ interface/src/AndroidHelper.h | 1 + libraries/audio-client/src/AudioClient.cpp | 6 +- libraries/audio-client/src/AudioClient.h | 8 +++ 13 files changed, 220 insertions(+), 2 deletions(-) create mode 100644 android/app/src/main/java/io/highfidelity/hifiinterface/fragment/SettingsFragment.java create mode 100644 android/app/src/main/java/io/highfidelity/hifiinterface/receiver/HeadsetStateReceiver.java create mode 100644 android/app/src/main/res/xml/settings.xml diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 7255e1f295..b216819ed0 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -9,6 +9,7 @@ + @@ -75,6 +76,15 @@ android:enabled="true" android:exported="false" android:process=":breakpad_uploader"/> + + + + + + diff --git a/android/app/src/main/cpp/native.cpp b/android/app/src/main/cpp/native.cpp index ce5af01f29..6b44b2dc7a 100644 --- a/android/app/src/main/cpp/native.cpp +++ b/android/app/src/main/cpp/native.cpp @@ -355,5 +355,51 @@ JNIEXPORT void Java_io_highfidelity_hifiinterface_WebViewActivity_nativeProcessU AndroidHelper::instance().processURL(QString::fromUtf8(nativeString)); } +JNIEXPORT void JNICALL +Java_io_highfidelity_hifiinterface_fragment_SettingsFragment_updateHifiSetting(JNIEnv *env, + jobject instance, + jstring group_, + jstring key_, + jboolean value_) { + const char *c_group = env->GetStringUTFChars(group_, 0); + const char *c_key = env->GetStringUTFChars(key_, 0); + + const QString group = QString::fromUtf8(c_group); + const QString key = QString::fromUtf8(c_key); + + env->ReleaseStringUTFChars(group_, c_group); + env->ReleaseStringUTFChars(key_, c_key); + + bool value = value_; + + Setting::Handle setting { QStringList() << group << key , !value }; + setting.set(value); +} + +JNIEXPORT jboolean JNICALL +Java_io_highfidelity_hifiinterface_fragment_SettingsFragment_getHifiSettingBoolean(JNIEnv *env, + jobject instance, + jstring group_, + jstring key_, + jboolean defaultValue) { + const char *c_group = env->GetStringUTFChars(group_, 0); + const char *c_key = env->GetStringUTFChars(key_, 0); + + const QString group = QString::fromUtf8(c_group); + const QString key = QString::fromUtf8(c_key); + + env->ReleaseStringUTFChars(group_, c_group); + env->ReleaseStringUTFChars(key_, c_key); + + Setting::Handle setting { QStringList() << group << key , defaultValue}; + return setting.get(); +} + +JNIEXPORT void JNICALL +Java_io_highfidelity_hifiinterface_receiver_HeadsetStateReceiver_notifyHeadsetOn(JNIEnv *env, + jobject instance, + jboolean pluggedIn) { + AndroidHelper::instance().notifyHeadsetOn(pluggedIn); +} } diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java index f161783d6a..08e66a2f42 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/InterfaceActivity.java @@ -13,6 +13,7 @@ package io.highfidelity.hifiinterface; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; @@ -40,6 +41,7 @@ import java.util.HashMap; import java.util.List; import io.highfidelity.hifiinterface.fragment.WebViewFragment; +import io.highfidelity.hifiinterface.receiver.HeadsetStateReceiver; /*import com.google.vr.cardboard.DisplaySynchronizer; import com.google.vr.cardboard.DisplayUtils; @@ -55,6 +57,7 @@ public class InterfaceActivity extends QtActivity implements WebViewFragment.OnW private static final int NORMAL_DPI = 160; private Vibrator mVibrator; + private HeadsetStateReceiver headsetStateReceiver; //public static native void handleHifiURL(String hifiURLString); private native long nativeOnCreate(InterfaceActivity instance, AssetManager assetManager); @@ -151,6 +154,8 @@ public class InterfaceActivity extends QtActivity implements WebViewFragment.OnW layoutParams.resolveLayoutDirection(View.LAYOUT_DIRECTION_RTL); qtLayout.addView(webSlidingDrawer, layoutParams); webSlidingDrawer.setVisibility(View.GONE); + + headsetStateReceiver = new HeadsetStateReceiver(); } @Override @@ -161,6 +166,7 @@ public class InterfaceActivity extends QtActivity implements WebViewFragment.OnW } else { nativeEnterBackground(); } + unregisterReceiver(headsetStateReceiver); //gvrApi.pauseTracking(); } @@ -183,6 +189,7 @@ public class InterfaceActivity extends QtActivity implements WebViewFragment.OnW nativeEnterForeground(); surfacesWorkaround(); keepInterfaceRunning = false; + registerReceiver(headsetStateReceiver, new IntentFilter(Intent.ACTION_HEADSET_PLUG)); //gvrApi.resumeTracking(); } diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/MainActivity.java b/android/app/src/main/java/io/highfidelity/hifiinterface/MainActivity.java index db6f0fca24..4c6d05a3e8 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/MainActivity.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/MainActivity.java @@ -33,6 +33,7 @@ import io.highfidelity.hifiinterface.fragment.FriendsFragment; import io.highfidelity.hifiinterface.fragment.HomeFragment; import io.highfidelity.hifiinterface.fragment.LoginFragment; import io.highfidelity.hifiinterface.fragment.PolicyFragment; +import io.highfidelity.hifiinterface.fragment.SettingsFragment; import io.highfidelity.hifiinterface.task.DownloadProfileImageTask; public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, @@ -80,6 +81,8 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On mPeopleMenuItem = mNavigationView.getMenu().findItem(R.id.action_people); + updateDebugMenu(mNavigationView.getMenu()); + Toolbar toolbar = findViewById(R.id.toolbar); toolbar.setTitleTextAppearance(this, R.style.HomeActionBarTitleStyle); setSupportActionBar(toolbar); @@ -108,6 +111,16 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On } } + private void updateDebugMenu(Menu menu) { + if (BuildConfig.DEBUG) { + for (int i=0; i < menu.size(); i++) { + if (menu.getItem(i).getItemId() == R.id.action_debug_settings) { + menu.getItem(i).setVisible(true); + } + } + } + } + private void loadFragment(String fragment) { switch (fragment) { case "Login": @@ -151,6 +164,13 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On loadFragment(fragment, getString(R.string.people), getString(R.string.tagFragmentPeople), true); } + private void loadSettingsFragment() { + SettingsFragment fragment = SettingsFragment.newInstance(); + + loadFragment(fragment, getString(R.string.settings), getString(R.string.tagSettings), true); + } + + private void loadFragment(Fragment fragment, String title, String tag, boolean addToBackStack) { FragmentManager fragmentManager = getFragmentManager(); @@ -241,6 +261,9 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On case R.id.action_people: loadPeopleFragment(); return true; + case R.id.action_debug_settings: + loadSettingsFragment(); + return true; } return false; } diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/fragment/SettingsFragment.java b/android/app/src/main/java/io/highfidelity/hifiinterface/fragment/SettingsFragment.java new file mode 100644 index 0000000000..cc23665e72 --- /dev/null +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/fragment/SettingsFragment.java @@ -0,0 +1,63 @@ +package io.highfidelity.hifiinterface.fragment; + +import android.content.SharedPreferences; +import android.media.audiofx.AcousticEchoCanceler; +import android.os.Bundle; +import android.preference.Preference; +import android.preference.PreferenceFragment; +import android.support.annotation.Nullable; + +import io.highfidelity.hifiinterface.R; + +public class SettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener { + + public native void updateHifiSetting(String group, String key, boolean value); + public native boolean getHifiSettingBoolean(String group, String key, boolean defaultValue); + + private final String HIFI_SETTINGS_ANDROID_GROUP = "Android"; + private final String HIFI_SETTINGS_AEC_KEY = "aec"; + private final String PREFERENCE_KEY_AEC = "aec"; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.settings); + + if (!AcousticEchoCanceler.isAvailable()) { + getPreferenceScreen().getPreferenceManager().findPreference("aec").setEnabled(false); + } + + getPreferenceScreen().getSharedPreferences().edit().putBoolean(PREFERENCE_KEY_AEC, + getHifiSettingBoolean(HIFI_SETTINGS_ANDROID_GROUP, HIFI_SETTINGS_AEC_KEY, false)); + } + + public static SettingsFragment newInstance() { + SettingsFragment fragment = new SettingsFragment(); + return fragment; + } + + @Override + public void onResume() { + super.onResume(); + getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); + } + + @Override + public void onPause() { + super.onPause(); + getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this); + + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + Preference pref = findPreference(key); + switch (key) { + case "aec": + updateHifiSetting(HIFI_SETTINGS_ANDROID_GROUP, HIFI_SETTINGS_AEC_KEY, sharedPreferences.getBoolean(key, false)); + break; + default: + break; + } + } +} diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/receiver/HeadsetStateReceiver.java b/android/app/src/main/java/io/highfidelity/hifiinterface/receiver/HeadsetStateReceiver.java new file mode 100644 index 0000000000..29bc1c49f2 --- /dev/null +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/receiver/HeadsetStateReceiver.java @@ -0,0 +1,20 @@ +package io.highfidelity.hifiinterface.receiver; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.media.AudioManager; +import android.util.Log; + +public class HeadsetStateReceiver extends BroadcastReceiver { + + private native void notifyHeadsetOn(boolean pluggedIn); + + @Override + public void onReceive(Context context, Intent intent) { + AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + + Log.d("[HEADSET] " , "BR - Wired headset on:" + audioManager.isWiredHeadsetOn()); + notifyHeadsetOn(audioManager.isWiredHeadsetOn()); + } +} diff --git a/android/app/src/main/res/menu/menu_navigation.xml b/android/app/src/main/res/menu/menu_navigation.xml index 3cce64f9f5..142af5d146 100644 --- a/android/app/src/main/res/menu/menu_navigation.xml +++ b/android/app/src/main/res/menu/menu_navigation.xml @@ -9,4 +9,9 @@ android:id="@+id/action_people" android:title="@string/people" /> + diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index b158aba59d..abde15f484 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -29,4 +29,9 @@ tagFragmentLogin tagFragmentPolicy tagFragmentPeople + tagSettings + Settings + AEC + Acoustic Echo Cancellation + Developer diff --git a/android/app/src/main/res/xml/settings.xml b/android/app/src/main/res/xml/settings.xml new file mode 100644 index 0000000000..5ec47b1aff --- /dev/null +++ b/android/app/src/main/res/xml/settings.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/interface/src/AndroidHelper.cpp b/interface/src/AndroidHelper.cpp index 419382f2cb..35bf094591 100644 --- a/interface/src/AndroidHelper.cpp +++ b/interface/src/AndroidHelper.cpp @@ -10,6 +10,7 @@ // #include "AndroidHelper.h" #include +#include #include "Application.h" #if defined(qApp) @@ -18,6 +19,7 @@ #define qApp (static_cast(QCoreApplication::instance())) AndroidHelper::AndroidHelper() { + qRegisterMetaType("QAudio::Mode"); } AndroidHelper::~AndroidHelper() { @@ -56,3 +58,18 @@ void AndroidHelper::processURL(const QString &url) { qApp->acceptURL(url); } } + +void AndroidHelper::notifyHeadsetOn(bool pluggedIn) { +#if defined (Q_OS_ANDROID) + auto audioClient = DependencyManager::get(); + if (audioClient) { + QAudioDeviceInfo activeDev = audioClient->getActiveAudioDevice(QAudio::AudioInput); + Setting::Handle enableAEC(QStringList() << ANDROID_SETTINGS_GROUP << SETTING_AEC_KEY, false); + if ((pluggedIn || !enableAEC.get()) && !activeDev.isNull() && activeDev.deviceName() != VOICE_RECOGNITION) { + QMetaObject::invokeMethod(audioClient.get(), "switchAudioDevice", Q_ARG(QAudio::Mode, QAudio::AudioInput), Q_ARG(QString, VOICE_RECOGNITION)); + } else if ( (!pluggedIn && enableAEC.get()) && !activeDev.isNull() && activeDev.deviceName() != VOICE_COMMUNICATION) { + QMetaObject::invokeMethod(audioClient.get(), "switchAudioDevice", Q_ARG(QAudio::Mode, QAudio::AudioInput), Q_ARG(QString, VOICE_COMMUNICATION)); + } + } +#endif +} diff --git a/interface/src/AndroidHelper.h b/interface/src/AndroidHelper.h index 03d92f91d9..11b84e4025 100644 --- a/interface/src/AndroidHelper.h +++ b/interface/src/AndroidHelper.h @@ -29,6 +29,7 @@ public: void performHapticFeedback(int duration); void processURL(const QString &url); + void notifyHeadsetOn(bool pluggedIn); AndroidHelper(AndroidHelper const&) = delete; void operator=(AndroidHelper const&) = delete; diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 6a9363f309..e23b8ac3cd 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -53,7 +53,6 @@ #include "AudioHelpers.h" #if defined(Q_OS_ANDROID) -#define VOICE_RECOGNITION "voicerecognition" #include #endif @@ -451,9 +450,12 @@ QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) { #if defined (Q_OS_ANDROID) if (mode == QAudio::AudioInput) { + Setting::Handle enableAEC(QStringList() << ANDROID_SETTINGS_GROUP << SETTING_AEC_KEY, false); + bool aecEnabled = enableAEC.get(); auto inputDevices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput); for (auto inputDevice : inputDevices) { - if (inputDevice.deviceName() == VOICE_RECOGNITION) { + if ((aecEnabled && inputDevice.deviceName() == VOICE_COMMUNICATION) || + (!aecEnabled && inputDevice.deviceName() == VOICE_RECOGNITION)) { return inputDevice; } } diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index 8599c990a3..fa7ac40a16 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -64,6 +64,14 @@ #pragma warning( pop ) #endif +#if defined (Q_OS_ANDROID) +#define VOICE_RECOGNITION "voicerecognition" +#define VOICE_COMMUNICATION "voicecommunication" + +#define ANDROID_SETTINGS_GROUP "Android" +#define SETTING_AEC_KEY "aec" +#endif + class QAudioInput; class QAudioOutput; class QIODevice; From 2943502c9b5d0d9630c97b76793ffa5b3c205561 Mon Sep 17 00:00:00 2001 From: Gabriel Calero Date: Wed, 12 Sep 2018 16:36:04 -0300 Subject: [PATCH 02/12] Headset plug/unplug detection --- .../receiver/HeadsetStateReceiver.java | 2 -- interface/src/AndroidHelper.cpp | 8 +---- libraries/audio-client/src/AudioClient.cpp | 32 +++++++++++++++++-- libraries/audio-client/src/AudioClient.h | 11 +++++-- 4 files changed, 39 insertions(+), 14 deletions(-) diff --git a/android/app/src/main/java/io/highfidelity/hifiinterface/receiver/HeadsetStateReceiver.java b/android/app/src/main/java/io/highfidelity/hifiinterface/receiver/HeadsetStateReceiver.java index 29bc1c49f2..5645912d73 100644 --- a/android/app/src/main/java/io/highfidelity/hifiinterface/receiver/HeadsetStateReceiver.java +++ b/android/app/src/main/java/io/highfidelity/hifiinterface/receiver/HeadsetStateReceiver.java @@ -13,8 +13,6 @@ public class HeadsetStateReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); - - Log.d("[HEADSET] " , "BR - Wired headset on:" + audioManager.isWiredHeadsetOn()); notifyHeadsetOn(audioManager.isWiredHeadsetOn()); } } diff --git a/interface/src/AndroidHelper.cpp b/interface/src/AndroidHelper.cpp index 35bf094591..400085a62a 100644 --- a/interface/src/AndroidHelper.cpp +++ b/interface/src/AndroidHelper.cpp @@ -63,13 +63,7 @@ void AndroidHelper::notifyHeadsetOn(bool pluggedIn) { #if defined (Q_OS_ANDROID) auto audioClient = DependencyManager::get(); if (audioClient) { - QAudioDeviceInfo activeDev = audioClient->getActiveAudioDevice(QAudio::AudioInput); - Setting::Handle enableAEC(QStringList() << ANDROID_SETTINGS_GROUP << SETTING_AEC_KEY, false); - if ((pluggedIn || !enableAEC.get()) && !activeDev.isNull() && activeDev.deviceName() != VOICE_RECOGNITION) { - QMetaObject::invokeMethod(audioClient.get(), "switchAudioDevice", Q_ARG(QAudio::Mode, QAudio::AudioInput), Q_ARG(QString, VOICE_RECOGNITION)); - } else if ( (!pluggedIn && enableAEC.get()) && !activeDev.isNull() && activeDev.deviceName() != VOICE_COMMUNICATION) { - QMetaObject::invokeMethod(audioClient.get(), "switchAudioDevice", Q_ARG(QAudio::Mode, QAudio::AudioInput), Q_ARG(QString, VOICE_COMMUNICATION)); - } + QMetaObject::invokeMethod(audioClient.data(), "setHeadsetPluggedIn", Q_ARG(bool, pluggedIn)); } #endif } diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index e23b8ac3cd..f0ba0307cc 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -209,6 +209,7 @@ AudioClient::AudioClient() : _positionGetter(DEFAULT_POSITION_GETTER), #if defined(Q_OS_ANDROID) _checkInputTimer(this), + _isHeadsetPluggedIn(false), #endif _orientationGetter(DEFAULT_ORIENTATION_GETTER) { // avoid putting a lock in the device callback @@ -450,12 +451,14 @@ QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) { #if defined (Q_OS_ANDROID) if (mode == QAudio::AudioInput) { - Setting::Handle enableAEC(QStringList() << ANDROID_SETTINGS_GROUP << SETTING_AEC_KEY, false); + Setting::Handle enableAEC(SETTING_AEC_KEY, false); bool aecEnabled = enableAEC.get(); + auto audioClient = DependencyManager::get(); + bool headsetOn = audioClient? audioClient->isHeadsetPluggedIn() : false ; auto inputDevices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput); for (auto inputDevice : inputDevices) { - if ((aecEnabled && inputDevice.deviceName() == VOICE_COMMUNICATION) || - (!aecEnabled && inputDevice.deviceName() == VOICE_RECOGNITION)) { + if (((headsetOn || !aecEnabled) && inputDevice.deviceName() == VOICE_RECOGNITION) || + ((!headsetOn && aecEnabled) && inputDevice.deviceName() == VOICE_COMMUNICATION)) { return inputDevice; } } @@ -1632,6 +1635,29 @@ void AudioClient::checkInputTimeout() { #endif } +void AudioClient::setHeadsetPluggedIn(bool pluggedIn) { +#if defined(Q_OS_ANDROID) + if (pluggedIn == !_isHeadsetPluggedIn && !_inputDeviceInfo.isNull()) { + QAndroidJniObject brand = QAndroidJniObject::getStaticObjectField("android/os/Build", "BRAND"); + // some samsung phones needs more time to shutdown the previous input device + if (brand.toString().contains("samsung", Qt::CaseInsensitive)) { + switchInputToAudioDevice(QAudioDeviceInfo(), true); + QThread::msleep(200); + } + + Setting::Handle enableAEC(SETTING_AEC_KEY, false); + bool aecEnabled = enableAEC.get(); + + if ((pluggedIn || !aecEnabled) && _inputDeviceInfo.deviceName() != VOICE_RECOGNITION) { + switchAudioDevice(QAudio::AudioInput, VOICE_RECOGNITION); + } else if (!pluggedIn && aecEnabled && _inputDeviceInfo.deviceName() != VOICE_COMMUNICATION) { + switchAudioDevice(QAudio::AudioInput, VOICE_COMMUNICATION); + } + } + _isHeadsetPluggedIn = pluggedIn; +#endif +} + void AudioClient::outputNotify() { int recentUnfulfilled = _audioOutputIODevice.getRecentUnfulfilledReads(); if (recentUnfulfilled > 0) { diff --git a/libraries/audio-client/src/AudioClient.h b/libraries/audio-client/src/AudioClient.h index fa7ac40a16..b1ccb496b6 100644 --- a/libraries/audio-client/src/AudioClient.h +++ b/libraries/audio-client/src/AudioClient.h @@ -68,8 +68,7 @@ #define VOICE_RECOGNITION "voicerecognition" #define VOICE_COMMUNICATION "voicecommunication" -#define ANDROID_SETTINGS_GROUP "Android" -#define SETTING_AEC_KEY "aec" +#define SETTING_AEC_KEY "Android/aec" #endif class QAudioInput; @@ -176,6 +175,10 @@ public: static QString getWinDeviceName(wchar_t* guid); #endif +#if defined(Q_OS_ANDROID) + bool isHeadsetPluggedIn() { return _isHeadsetPluggedIn; } +#endif + public slots: void start(); void stop(); @@ -224,6 +227,9 @@ public slots: bool switchAudioDevice(QAudio::Mode mode, const QAudioDeviceInfo& deviceInfo = QAudioDeviceInfo()); bool switchAudioDevice(QAudio::Mode mode, const QString& deviceName); + // Qt opensles plugin is not able to detect when the headset is plugged in + void setHeadsetPluggedIn(bool pluggedIn); + float getInputVolume() const { return (_audioInput) ? (float)_audioInput->volume() : 0.0f; } void setInputVolume(float volume, bool emitSignal = true); void setReverb(bool reverb); @@ -285,6 +291,7 @@ private: #ifdef Q_OS_ANDROID QTimer _checkInputTimer; long _inputReadsSinceLastCheck = 0l; + bool _isHeadsetPluggedIn; #endif class Gate { From 27c7592d986af1424c4e85a7df5d44e2a50b2d7f Mon Sep 17 00:00:00 2001 From: Gabriel Calero Date: Thu, 13 Sep 2018 14:30:42 -0300 Subject: [PATCH 03/12] Patch qt 5.11.1 to support voice_communication opensl es preset --- android/build.gradle | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index a6de0d469c..a5d40b9b43 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -73,16 +73,16 @@ def baseUrl = 'https://hifi-public.s3.amazonaws.com/dependencies/android/' def breakpadDumpSymsDir = new File("${appDir}/build/tmp/breakpadDumpSyms") def qtFile='qt-5.11.1_linux_armv8-libcpp_openssl.tgz' -def qtChecksum='f312c47cd8b8dbca824c32af4eec5e66' -def qtVersionId='nyCGcb91S4QbYeJhUkawO5x1lrLdSNB_' +def qtChecksum='bf9e734d9c4e77c4807a38c93515e25c' +def qtVersionId='Qt3rvI0O7l5gLkacia2vA6KAchTgFkFf' if (Os.isFamily(Os.FAMILY_MAC)) { - qtFile = 'qt-5.11.1_osx_armv8-libcpp_openssl.tgz' - qtChecksum='a0c8b394aec5b0fcd46714ca3a53278a' - qtVersionId='QNa.lwNJaPc0eGuIL.xZ8ebeTuLL7rh8' + qtFile = 'qt-5.11.1_osx_armv8-libcpp_openssl_patched.tgz' + qtChecksum='5f12fd4fb25efe648c2fd161fd44998a' + qtVersionId='XXJ7ii1.xYzgFdWPnU.8mXnCj.q6y0Q5' } else if (Os.isFamily(Os.FAMILY_WINDOWS)) { - qtFile = 'qt-5.11.1_win_armv8-libcpp_openssl.tgz' - qtChecksum='d80aed4233ce9e222aae8376e7a94bf9' - qtVersionId='iDVXu0i3WEXRFIxQCtzcJ2XuKrE8RIqB' + qtFile = 'qt-5.11.1_win_armv8-libcpp_openssl_patched.tgz' + qtChecksum='0582191cc55431aa4f660848a542883e' + qtVersionId='JfWM0P_Mz5Qp0LwpzhrsRwN3fqlLSFeT' } def packages = [ From ec2c0226a5aadcf0ab762d463b10a30bc10c05ca Mon Sep 17 00:00:00 2001 From: Gabriel Calero Date: Thu, 13 Sep 2018 16:42:12 -0300 Subject: [PATCH 04/12] Replace qt build version (osx) --- android/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index a5d40b9b43..8a3f4d75b9 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -77,8 +77,8 @@ def qtChecksum='bf9e734d9c4e77c4807a38c93515e25c' def qtVersionId='Qt3rvI0O7l5gLkacia2vA6KAchTgFkFf' if (Os.isFamily(Os.FAMILY_MAC)) { qtFile = 'qt-5.11.1_osx_armv8-libcpp_openssl_patched.tgz' - qtChecksum='5f12fd4fb25efe648c2fd161fd44998a' - qtVersionId='XXJ7ii1.xYzgFdWPnU.8mXnCj.q6y0Q5' + qtChecksum='c83cc477c08a892e00c71764dca051a0' + qtVersionId='QNa.lwNJaPc0eGuIL.xZ8ebeTuLL7rh8' } else if (Os.isFamily(Os.FAMILY_WINDOWS)) { qtFile = 'qt-5.11.1_win_armv8-libcpp_openssl_patched.tgz' qtChecksum='0582191cc55431aa4f660848a542883e' From 1215ddbe88a6669173c7a635be0f0b8514e36fce Mon Sep 17 00:00:00 2001 From: Gabriel Calero Date: Thu, 13 Sep 2018 18:50:46 -0300 Subject: [PATCH 05/12] Remove debug files from linux qt build. Remove extra space --- android/build.gradle | 6 +++--- libraries/audio-client/src/AudioClient.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 8a3f4d75b9..14f0779e29 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -72,9 +72,9 @@ def jniFolder = new File(appDir, 'src/main/jniLibs/arm64-v8a') def baseUrl = 'https://hifi-public.s3.amazonaws.com/dependencies/android/' def breakpadDumpSymsDir = new File("${appDir}/build/tmp/breakpadDumpSyms") -def qtFile='qt-5.11.1_linux_armv8-libcpp_openssl.tgz' -def qtChecksum='bf9e734d9c4e77c4807a38c93515e25c' -def qtVersionId='Qt3rvI0O7l5gLkacia2vA6KAchTgFkFf' +def qtFile='qt-5.11.1_linux_armv8-libcpp_openssl_patched.tgz' +def qtChecksum='aa449d4bfa963f3bc9a9dfe558ba29df' +def qtVersionId='3S97HBM5G5Xw9EfE52sikmgdN3t6C2MN' if (Os.isFamily(Os.FAMILY_MAC)) { qtFile = 'qt-5.11.1_osx_armv8-libcpp_openssl_patched.tgz' qtChecksum='c83cc477c08a892e00c71764dca051a0' diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index f0ba0307cc..814cbf87e4 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -454,7 +454,7 @@ QAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) { Setting::Handle enableAEC(SETTING_AEC_KEY, false); bool aecEnabled = enableAEC.get(); auto audioClient = DependencyManager::get(); - bool headsetOn = audioClient? audioClient->isHeadsetPluggedIn() : false ; + bool headsetOn = audioClient? audioClient->isHeadsetPluggedIn() : false; auto inputDevices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput); for (auto inputDevice : inputDevices) { if (((headsetOn || !aecEnabled) && inputDevice.deviceName() == VOICE_RECOGNITION) || From 5795ef3c6323c9dbfd5782b486d3687d3016e322 Mon Sep 17 00:00:00 2001 From: Gabriel Calero Date: Thu, 13 Sep 2018 19:43:28 -0300 Subject: [PATCH 06/12] Fix qt build (osx) file version --- android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/build.gradle b/android/build.gradle index 14f0779e29..aa7aa399b2 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -78,7 +78,7 @@ def qtVersionId='3S97HBM5G5Xw9EfE52sikmgdN3t6C2MN' if (Os.isFamily(Os.FAMILY_MAC)) { qtFile = 'qt-5.11.1_osx_armv8-libcpp_openssl_patched.tgz' qtChecksum='c83cc477c08a892e00c71764dca051a0' - qtVersionId='QNa.lwNJaPc0eGuIL.xZ8ebeTuLL7rh8' + qtVersionId='OxBD7iKINv1HbyOXmAmDrBb8AF3N.Kup' } else if (Os.isFamily(Os.FAMILY_WINDOWS)) { qtFile = 'qt-5.11.1_win_armv8-libcpp_openssl_patched.tgz' qtChecksum='0582191cc55431aa4f660848a542883e' From b0cde2afcc40c94e10ef1b683af320fec6994947 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Fri, 14 Sep 2018 15:05:17 -0700 Subject: [PATCH 07/12] Small addition to Anim Stats * During a state machine interp the previous state now shows up in AlphaValues panel, with parentheses around the name. * Added 3 new fields * Position - in world coordinate frame. * Heading - the facing angle in the world corrdinate frame. * Local Vel - the velocity of the character in the local coordinate frame. (left, forward, up). --- interface/resources/qml/AnimStats.qml | 11 ++++++++-- interface/src/ui/AnimStats.cpp | 23 ++++++++++++++++++++ interface/src/ui/AnimStats.h | 20 ++++++++++++++--- libraries/animation/src/AnimStateMachine.cpp | 4 ++++ libraries/animation/src/AnimVariant.cpp | 9 ++++++++ 5 files changed, 62 insertions(+), 5 deletions(-) diff --git a/interface/resources/qml/AnimStats.qml b/interface/resources/qml/AnimStats.qml index 35ed3799a6..d000f3d9be 100644 --- a/interface/resources/qml/AnimStats.qml +++ b/interface/resources/qml/AnimStats.qml @@ -47,6 +47,9 @@ Item { id: firstCol spacing: 4; x: 4; y: 4; + StatText { + text: root.positionText + } StatText { text: "State Machines:---------------------------------------------------------------------------" } @@ -73,10 +76,12 @@ Item { id: secondCol spacing: 4; x: 4; y: 4; + StatText { + text: root.rotationText + } StatText { text: "Anim Vars:--------------------------------------------------------------------------------" } - ListView { width: secondCol.width height: root.animVars.length * 15 @@ -113,10 +118,12 @@ Item { id: thirdCol spacing: 4; x: 4; y: 4; + StatText { + text: root.velocityText + } StatText { text: "Alpha Values:--------------------------------------------------------------------------" } - ListView { width: thirdCol.width height: root.animAlphaValues.length * 15 diff --git a/interface/src/ui/AnimStats.cpp b/interface/src/ui/AnimStats.cpp index 7b4778e365..e3579fa2dc 100644 --- a/interface/src/ui/AnimStats.cpp +++ b/interface/src/ui/AnimStats.cpp @@ -42,6 +42,29 @@ void AnimStats::updateStats(bool force) { auto myAvatar = avatarManager->getMyAvatar(); auto debugAlphaMap = myAvatar->getSkeletonModel()->getRig().getDebugAlphaMap(); + glm::vec3 position = myAvatar->getWorldPosition(); + glm::quat rotation = myAvatar->getWorldOrientation(); + glm::vec3 velocity = myAvatar->getWorldVelocity(); + + _positionText = QString("Position: (%1, %2, %3)"). + arg(QString::number(position.x, 'f', 2)). + arg(QString::number(position.y, 'f', 2)). + arg(QString::number(position.z, 'f', 2)); + emit positionTextChanged(); + + glm::vec3 eulerRotation = safeEulerAngles(rotation); + _rotationText = QString("Heading: %1"). + arg(QString::number(glm::degrees(eulerRotation.y), 'f', 2)); + emit rotationTextChanged(); + + // transform velocity into rig coordinate frame. z forward. + glm::vec3 localVelocity = Quaternions::Y_180 * glm::inverse(rotation) * velocity; + _velocityText = QString("Local Vel: (%1, %2, %3)"). + arg(QString::number(localVelocity.x, 'f', 2)). + arg(QString::number(localVelocity.y, 'f', 2)). + arg(QString::number(localVelocity.z, 'f', 2)); + emit velocityTextChanged(); + // update animation debug alpha values QStringList newAnimAlphaValues; qint64 now = usecTimestampNow(); diff --git a/interface/src/ui/AnimStats.h b/interface/src/ui/AnimStats.h index 1a6795b498..7b6aaf7b54 100644 --- a/interface/src/ui/AnimStats.h +++ b/interface/src/ui/AnimStats.h @@ -19,6 +19,9 @@ class AnimStats : public QQuickItem { Q_PROPERTY(QStringList animAlphaValues READ animAlphaValues NOTIFY animAlphaValuesChanged) Q_PROPERTY(QStringList animVars READ animVars NOTIFY animVarsChanged) Q_PROPERTY(QStringList animStateMachines READ animStateMachines NOTIFY animStateMachinesChanged) + Q_PROPERTY(QString positionText READ positionText NOTIFY positionTextChanged) + Q_PROPERTY(QString rotationText READ rotationText NOTIFY rotationTextChanged) + Q_PROPERTY(QString velocityText READ velocityText NOTIFY velocityTextChanged) public: static AnimStats* getInstance(); @@ -27,9 +30,13 @@ public: void updateStats(bool force = false); - QStringList animAlphaValues() { return _animAlphaValues; } - QStringList animVars() { return _animVarsList; } - QStringList animStateMachines() { return _animStateMachines; } + QStringList animAlphaValues() const { return _animAlphaValues; } + QStringList animVars() const { return _animVarsList; } + QStringList animStateMachines() const { return _animStateMachines; } + + QString positionText() const { return _positionText; } + QString rotationText() const { return _rotationText; } + QString velocityText() const { return _velocityText; } public slots: void forceUpdateStats() { updateStats(true); } @@ -39,6 +46,9 @@ signals: void animAlphaValuesChanged(); void animVarsChanged(); void animStateMachinesChanged(); + void positionTextChanged(); + void rotationTextChanged(); + void velocityTextChanged(); private: QStringList _animAlphaValues; @@ -50,6 +60,10 @@ private: std::map _animVarChangedTimers; // last time animVar value has changed. QStringList _animStateMachines; + + QString _positionText; + QString _rotationText; + QString _velocityText; }; #endif // hifi_AnimStats_h diff --git a/libraries/animation/src/AnimStateMachine.cpp b/libraries/animation/src/AnimStateMachine.cpp index 7f46cd614a..fb13b8e71c 100644 --- a/libraries/animation/src/AnimStateMachine.cpp +++ b/libraries/animation/src/AnimStateMachine.cpp @@ -88,6 +88,10 @@ const AnimPoseVec& AnimStateMachine::evaluate(const AnimVariantMap& animVars, co processOutputJoints(triggersOut); context.addStateMachineInfo(_id, _currentState->getID(), _previousState->getID(), _duringInterp, _alpha); + if (_duringInterp) { + // hack: add previoius state to debug alpha map, with parens around it's name. + context.setDebugAlpha(QString("(%1)").arg(_previousState->getID()), 1.0f - _alpha, AnimNodeType::Clip); + } return _poses; } diff --git a/libraries/animation/src/AnimVariant.cpp b/libraries/animation/src/AnimVariant.cpp index 509462984a..21fe234f7b 100644 --- a/libraries/animation/src/AnimVariant.cpp +++ b/libraries/animation/src/AnimVariant.cpp @@ -140,14 +140,19 @@ std::map AnimVariantMap::toDebugMap() const { result[pair.first] = QString::number(pair.second.getFloat(), 'f', 3); break; case AnimVariant::Type::Vec3: { + // To prevent filling up debug stats, don't show vec3 values + /* glm::vec3 value = pair.second.getVec3(); result[pair.first] = QString("(%1, %2, %3)"). arg(QString::number(value.x, 'f', 3)). arg(QString::number(value.y, 'f', 3)). arg(QString::number(value.z, 'f', 3)); + */ break; } case AnimVariant::Type::Quat: { + // To prevent filling up the anim stats, don't show quat values + /* glm::quat value = pair.second.getQuat(); result[pair.first] = QString("(%1, %2, %3, %4)"). arg(QString::number(value.x, 'f', 3)). @@ -155,10 +160,14 @@ std::map AnimVariantMap::toDebugMap() const { arg(QString::number(value.z, 'f', 3)). arg(QString::number(value.w, 'f', 3)); break; + */ } case AnimVariant::Type::String: + // To prevent filling up anim stats, don't show string values + /* result[pair.first] = pair.second.getString(); break; + */ default: assert(("invalid AnimVariant::Type", false)); } From 11fe657c0588943a4d275f66923cf78c6237fbd2 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Mon, 17 Sep 2018 10:33:04 -0700 Subject: [PATCH 08/12] Swaped AnimVar and StatMachine panels --- interface/resources/qml/AnimStats.qml | 59 ++++++++++++++------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/interface/resources/qml/AnimStats.qml b/interface/resources/qml/AnimStats.qml index d000f3d9be..91ed0eb69b 100644 --- a/interface/resources/qml/AnimStats.qml +++ b/interface/resources/qml/AnimStats.qml @@ -50,35 +50,6 @@ Item { StatText { text: root.positionText } - StatText { - text: "State Machines:---------------------------------------------------------------------------" - } - ListView { - width: firstCol.width - height: root.animStateMachines.length * 15 - visible: root.animStateMchines.length > 0; - model: root.animStateMachines - delegate: StatText { - text: { - return modelData; - } - } - } - } - } - - Rectangle { - width: secondCol.width + 8 - height: secondCol.height + 8 - color: root.bgColor; - - Column { - id: secondCol - spacing: 4; x: 4; y: 4; - - StatText { - text: root.rotationText - } StatText { text: "Anim Vars:--------------------------------------------------------------------------------" } @@ -109,6 +80,36 @@ Item { } } + Rectangle { + width: secondCol.width + 8 + height: secondCol.height + 8 + color: root.bgColor; + + Column { + id: secondCol + spacing: 4; x: 4; y: 4; + + StatText { + text: root.rotationText + } + StatText { + text: "State Machines:---------------------------------------------------------------------------" + } + ListView { + width: firstCol.width + height: root.animStateMachines.length * 15 + visible: root.animStateMchines.length > 0; + model: root.animStateMachines + delegate: StatText { + text: { + return modelData; + } + } + } + + } + } + Rectangle { width: thirdCol.width + 8 height: thirdCol.height + 8 From 8229c14c4486c57e963f470dd9f0c54a56950d41 Mon Sep 17 00:00:00 2001 From: Anthony Thibault Date: Mon, 17 Sep 2018 15:17:43 -0700 Subject: [PATCH 09/12] Fix for type in AnimStats.qml --- interface/resources/qml/AnimStats.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/AnimStats.qml b/interface/resources/qml/AnimStats.qml index 91ed0eb69b..b1900cf0a7 100644 --- a/interface/resources/qml/AnimStats.qml +++ b/interface/resources/qml/AnimStats.qml @@ -98,7 +98,7 @@ Item { ListView { width: firstCol.width height: root.animStateMachines.length * 15 - visible: root.animStateMchines.length > 0; + visible: root.animStateMachines.length > 0; model: root.animStateMachines delegate: StatText { text: { From 8805ce49e3e1349c4a123cca909c00aaf915e934 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 19 Sep 2018 15:06:58 -0700 Subject: [PATCH 10/12] Remove verbose logging of keyboard messages in edit.js and gridTool.js --- scripts/system/edit.js | 4 +--- scripts/system/libraries/gridTool.js | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 88ae2852be..b1f01e1ea9 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -2134,9 +2134,7 @@ var PropertiesTool = function (opts) { var onWebEventReceived = function(data) { try { data = JSON.parse(data); - } - catch(e) { - print('Edit.js received web event that was not valid json.'); + } catch(e) { return; } var i, properties, dY, diff, newPosition; diff --git a/scripts/system/libraries/gridTool.js b/scripts/system/libraries/gridTool.js index 3a114f23c7..6f62742e8f 100644 --- a/scripts/system/libraries/gridTool.js +++ b/scripts/system/libraries/gridTool.js @@ -267,7 +267,6 @@ GridTool = function(opts) { try { data = JSON.parse(data); } catch (e) { - print("gridTool.js: Error parsing JSON: " + e.name + " data " + data); return; } From 72adfb7ff09ea4f708ff1edae0f3062e85882f4a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 18 Sep 2018 11:08:40 -0700 Subject: [PATCH 11/12] Fix entity list selection failing when selecting entities not in list --- scripts/system/html/js/entityList.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/scripts/system/html/js/entityList.js b/scripts/system/html/js/entityList.js index 9cfdf6df22..0e025ef4c4 100644 --- a/scripts/system/html/js/entityList.js +++ b/scripts/system/html/js/entityList.js @@ -161,7 +161,10 @@ function loaded() { selectedEntities.forEach(function(entityID) { if (selection.indexOf(entityID) === -1) { - entitiesByID[entityID].el.className = ''; + let entity = entitiesByID[entityID]; + if (entity !== undefined) { + entity.el.className = ''; + } } }); @@ -385,15 +388,18 @@ function loaded() { let notFound = false; selectedEntities.forEach(function(id) { - entitiesByID[id].el.className = ''; + let entity = entitiesByID[id]; + if (entity !== undefined) { + entity.el.className = ''; + } }); selectedEntities = []; for (let i = 0; i < selectedIDs.length; i++) { let id = selectedIDs[i]; selectedEntities.push(id); - if (id in entitiesByID) { - let entity = entitiesByID[id]; + let entity = entitiesByID[id]; + if (entity !== undefined) { entity.el.className = 'selected'; } else { notFound = true; From d772cdb34a1491196381752b682dcffbabdb7a1f Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 24 Sep 2018 10:16:35 -0700 Subject: [PATCH 12/12] please --- libraries/render-utils/src/Model.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index b9ed43c339..ab6507b29c 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1553,14 +1553,13 @@ void Model::setBlendedVertices(int blendNumber, const QVector& vertic for (int i = 0; i < fbxGeometry.meshes.size(); i++) { const FBXMesh& mesh = fbxGeometry.meshes.at(i); auto meshNormalsAndTangents = _normalsAndTangents.find(i); - if (mesh.blendshapes.isEmpty() || meshNormalsAndTangents == _normalsAndTangents.end()) { + const auto& buffer = _blendedVertexBuffers.find(i); + if (mesh.blendshapes.isEmpty() || meshNormalsAndTangents == _normalsAndTangents.end() || buffer == _blendedVertexBuffers.end()) { continue; } const auto vertexCount = mesh.vertices.size(); const auto verticesSize = vertexCount * sizeof(glm::vec3); - const auto& buffer = _blendedVertexBuffers.find(i); - assert(buffer != _blendedVertexBuffers.end()); buffer->second->resize(mesh.vertices.size() * sizeof(glm::vec3) + meshNormalsAndTangents->second.size() * sizeof(NormalType)); buffer->second->setSubData(0, verticesSize, (gpu::Byte*) vertices.constData() + index * sizeof(glm::vec3)); buffer->second->setSubData(verticesSize, meshNormalsAndTangents->second.size() * sizeof(NormalType), (const gpu::Byte*) normalsAndTangents.data() + normalAndTangentIndex * sizeof(NormalType));