diff options
author | Roman Birg <roman@cyngn.com> | 2015-07-08 17:21:04 -0700 |
---|---|---|
committer | Roman Birg <roman@cyngn.com> | 2015-07-10 17:28:47 -0700 |
commit | 37c4a3107cd0bff3489d2ee49682f00d2025db49 (patch) | |
tree | e22b0beddd90a81cada8bf51c1744ab7378617a2 | |
parent | d281ad758d9b10a3a50c1ad44541457a63ec4ff8 (diff) | |
download | android_packages_apps_AudioFX-37c4a3107cd0bff3489d2ee49682f00d2025db49.tar.gz android_packages_apps_AudioFX-37c4a3107cd0bff3489d2ee49682f00d2025db49.tar.bz2 android_packages_apps_AudioFX-37c4a3107cd0bff3489d2ee49682f00d2025db49.zip |
AudioFX: DTS
REF: SAMBAR-165
Change-Id: Ia7d1450fb973279c3b4589ae6de74860444a739a
Signed-off-by: Roman Birg <roman@cyngn.com>
27 files changed, 2179 insertions, 1042 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index fc5a38d..148d052 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -17,8 +17,8 @@ xmlns:android="http://schemas.android.com/apk/res/android" package="com.cyngn.audiofx" android:installLocation="auto" - android:versionName="1.7" - android:versionCode="10700"> + android:versionName="1.8" + android:versionCode="10800"> <uses-sdk android:minSdkVersion="22"/> diff --git a/res/drawable/logo_dts_1c.xml b/res/drawable/logo_dts_1c.xml new file mode 100644 index 0000000..ed81042 --- /dev/null +++ b/res/drawable/logo_dts_1c.xml @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2015 The CyanogenMod Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="60dp" + android:height="24dp" + android:viewportWidth="60" + android:viewportHeight="24"> + + <group> + <path + android:fillColor="#FFFFFF" + android:pathData="M4.5,6.3c0,0-0.1-0.1-0.1-0.1C5.5,4.8,9,3.7,13.2,3.6c5.1-0.1,9.2,1.3,9.4,3.2 +c0,0,0,0.4,0,1.2l0,0c-0.4-1.7-4.3-3.3-9.1-3.6C9.3,4.2,5.7,5,4.5,6.3L4.5,6.3z +M5.6,7.2c1.7-0.8,4.6-1.3,7.9-1.1 +c4.8,0.3,8.7,1.8,9.1,3.6l0,0c0-0.7,0-1.2,0-1.2c-0.1-1.8-4.3-3.3-9.4-3.2C9.9,5.3,7,6,5.3,7C5.3,7,5.5,7.1,5.6,7.2L5.6,7.2z +M7.8,8.1c1.6-0.4,3.6-0.5,5.8-0.4c4.8,0.3,8.7,1.8,9.1,3.6v0c0-0.7,0-1.2,0-1.2c-0.1-1.8-4.3-3.3-9.4-3.2c-2.4,0-4.5,0.4-6.1,0.9 +C7.1,7.8,7.4,8,7.8,8.1L7.8,8.1z +M4,5.2c0.6-1.5,4.6-2.7,9.5-2.4c4.8,0.3,8.7,1.8,9.1,3.6l0-0.1c0-1-0.1-1.3-0.1-1.3 +c0-0.2-0.1-0.3-0.1-0.3c-0.7-1.6-4.5-2.8-9.2-2.7C8.4,2.1,4.4,3.5,4,5.2L4,5.2z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M22.2,10.5c-1.1,1.4-4.7,2.5-8.9,2.5C8.2,13.1,4.1,11.7,4,9.9c0,0,0-0.4,0-1.2l0,0 +c0.4,1.7,4.3,3.3,9.1,3.6c4.2,0.3,7.8-0.5,9.1-1.9C22.1,10.4,22.2,10.5,22.2,10.5L22.2,10.5z +M21.2,9.7C21.1,9.6,21,9.5,21,9.5 +c-1.7,0.8-4.6,1.3-7.9,1.1C8.2,10.3,4.4,8.8,4,7.1l0,0c0,0.7,0,1.2,0,1.2c0.1,1.8,4.3,3.3,9.4,3.2C16.7,11.4,19.6,10.7,21.2,9.7 +L21.2,9.7z +M19.4,8.8c-0.4-0.1-0.7-0.2-0.7-0.2C17.2,9,15.2,9.1,13,9C8.2,8.7,4.4,7.1,4,5.4l0,0c0,0.7,0,1.2,0,1.2 +c0.1,1.8,4.3,3.3,9.4,3.2C15.7,9.7,17.8,9.4,19.4,8.8L19.4,8.8z +M22.5,11.5C22,13,17.9,14.2,13,13.9c-4.8-0.3-8.7-1.8-9.1-3.6 +l0,0.1c0,1,0.1,1.3,0.1,1.3c0,0.2,0.1,0.3,0.1,0.3c0.7,1.6,4.5,2.8,9.2,2.7C18.2,14.6,22.1,13.2,22.5,11.5L22.5,11.5z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M37.6,14.5c-2.4,0-4.3,0-4.3,0c-2.3,0.1-3.5,0-3.5,0c-2.5,0-4.5-1.7-4.6-3.9 +c-0.1-2.1,1.7-3.9,4.3-4c0,0,1.2-0.1,3.2,0.2l0-0.2l0-4.3l5,0l0,4.6H40V5.3l4.8-2.1l0,3.6l1.7,0l0,1.3c-0.9,0-1.7,0-1.7,0v2.4 +c0,0.1,0,1.2,0,1.5c0,0,0.1,0.7,0.6,1.1c0,0,0.3,0.3,1,0.3c0,0,0.2,0,0.6,0h1.1l0,0c0.9,0,1.1-0.2,1.1-0.2c0.4-0.2,0.6-0.5,0.6-0.9 +c0-0.3-0.1-0.6-0.3-0.8l0,0l-1.3-1.2C48,10,47.8,9.7,47.7,9.6l0,0c-0.2-0.3-0.2-0.6-0.2-0.9c0-0.6,0.4-1.2,0.9-1.5l0,0 +C48.8,6.9,51.2,6,55.6,7l0,1.1l-0.1,0c0,0-1.2-0.1-1.6,0l0,0c-0.4,0.1-0.6,0.3-0.6,0.7c0,0.2,0.1,0.4,0.2,0.5l0,0l1.7,1.7l0,0 +c0.4,0.4,0.6,0.8,0.6,1.4c0,0.9-0.6,1.6-1.4,1.9c0,0-0.5,0.2-1.3,0.2c0,0-0.4,0-1.5,0h-0.1c-3.9,0-8,0-8,0l-0.1,0 +c-2.6-0.1-3.1-2-3.1-2c-0.1-0.4-0.2-1.3-0.2-1.3l0-3.2l-2.4,0L37.6,14.5 +M29.8,10.7c0,1.3,0.6,2,0.6,2c0.4,0.5,1.2,0.6,1.2,0.6 +c0.4,0.1,1,0,1,0l0-5.3c0,0-0.6-0.1-1,0c0,0-0.7,0-1.2,0.7c0,0-0.6,0.7-0.6,2V10.7z +M27.4,22c-1.1,0-1.5-0.5-1.5-1.5v-0.1h0.6v0.1 +c0,0.6,0.1,1,0.8,1c0.6,0,0.8-0.3,0.8-0.9c0-0.7-0.4-0.9-0.9-1.1c-0.7-0.4-1.3-0.7-1.3-1.7c0-0.9,0.6-1.3,1.4-1.3 +c0.9,0,1.4,0.4,1.4,1.3V18h-0.6v-0.1c0-0.5-0.1-0.8-0.8-0.8c-0.5,0-0.8,0.3-0.8,0.8c0,0.7,0.5,0.9,1.1,1.2c0.6,0.4,1.1,0.6,1.1,1.6 +C28.8,21.5,28.3,22,27.4,22z +M33.9,22c-1.2,0-1.3-0.8-1.3-1.9c0-1.1,0.1-2,1.3-2c1.2,0,1.2,0.8,1.2,1.9C35.2,21.3,35.1,22,33.9,22z +M34.6,19.9c0-0.6,0-1.3-0.7-1.3c-0.7,0-0.7,0.8-0.7,1.3v0.5c0,0.5,0,1.1,0.7,1.1c0.6,0,0.7-0.6,0.7-1.1V19.9z +M41.2,21.9l0-0.5 +C41,21.8,40.7,22,40.3,22c-0.7,0-1-0.5-1-1.1v-2.6h0.6v2.4c0,0.4,0,1,0.6,1c0.6,0,0.7-0.6,0.7-1.1v-2.2h0.6v2.9c0,0.3,0,0.5,0,0.8 +H41.2z +M47.8,22v-2.4c0-0.4,0-1-0.6-1c-0.5,0-0.7,0.6-0.7,1.1V22h-0.6v-2.9c0-0.3,0-0.5,0-0.8h0.6v0.5c0.2-0.3,0.5-0.6,1-0.6 +c0.7,0,1,0.5,1,1.1V22H47.8z +M54.4,21.9l0-0.4C54.2,21.8,54,22,53.6,22c-1.1,0-1.1-1.1-1.1-2c0-0.9,0.1-1.9,1.1-1.9 +c0.4,0,0.7,0.1,0.8,0.4v-2H55v4.6c0,0.2,0,0.5,0,0.7H54.4z +M53.7,18.6c-0.7,0-0.7,0.8-0.7,1.5c0,0.8,0.1,1.5,0.7,1.5 +c0.7,0,0.7-0.8,0.7-1.4C54.4,19.3,54.4,18.6,53.7,18.6z +M55.1,2.1c0.2,0,0.3,0,0.5,0.1c0.1,0.1,0.3,0.2,0.3,0.3 +C56,2.8,56,2.9,56,3.1c0,0.2,0,0.3-0.1,0.5c-0.1,0.1-0.2,0.3-0.3,0.3C55.4,4,55.3,4,55.1,4c-0.2,0-0.3,0-0.5-0.1 +c-0.1-0.1-0.3-0.2-0.3-0.3c-0.1-0.1-0.1-0.3-0.1-0.5c0-0.2,0-0.3,0.1-0.5c0.1-0.1,0.2-0.3,0.3-0.3C54.8,2.2,55,2.1,55.1,2.1z +M55.1,2.3c-0.1,0-0.3,0-0.4,0.1c-0.1,0.1-0.2,0.2-0.3,0.3c-0.1,0.1-0.1,0.3-0.1,0.4c0,0.1,0,0.3,0.1,0.4c0.1,0.1,0.2,0.2,0.3,0.3 +c0.1,0.1,0.3,0.1,0.4,0.1c0.1,0,0.3,0,0.4-0.1c0.1-0.1,0.2-0.2,0.3-0.3c0.1-0.1,0.1-0.3,0.1-0.4c0-0.1,0-0.3-0.1-0.4 +c-0.1-0.1-0.2-0.2-0.3-0.3C55.4,2.3,55.2,2.3,55.1,2.3z +M54.7,3.6v-1H55c0.1,0,0.2,0,0.3,0c0.1,0,0.1,0.1,0.1,0.1c0,0,0,0.1,0,0.1 +c0,0.1,0,0.1-0.1,0.2c-0.1,0.1-0.1,0.1-0.2,0.1c0,0,0.1,0,0.1,0.1c0,0,0.1,0.1,0.1,0.2l0.1,0.2h-0.2l-0.1-0.2 +c-0.1-0.1-0.1-0.2-0.2-0.2c0,0-0.1,0-0.1,0h-0.1v0.4H54.7z +M54.9,3h0.2c0.1,0,0.2,0,0.2,0c0,0,0.1-0.1,0.1-0.1c0,0,0-0.1,0-0.1 +c0,0,0,0-0.1-0.1c0,0-0.1,0-0.2,0h-0.2V3z" /> + </group> +</vector>
\ No newline at end of file diff --git a/res/drawable/logo_dts_fc.xml b/res/drawable/logo_dts_fc.xml new file mode 100644 index 0000000..ea9bbed --- /dev/null +++ b/res/drawable/logo_dts_fc.xml @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (c) 2015 The CyanogenMod Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="60dp" + android:height="24dp" + android:viewportWidth="60" + android:viewportHeight="24"> + + <group> + <path + android:fillColor="#FDB813" + android:pathData="M4.5,6.3c0,0-0.1-0.1-0.1-0.1C5.5,4.8,9,3.7,13.2,3.6c5.1-0.1,9.2,1.3,9.4,3.2 +c0,0,0,0.4,0,1.2l0,0c-0.4-1.7-4.3-3.3-9.1-3.6C9.3,4.2,5.7,5,4.5,6.3L4.5,6.3z +M5.6,7.2c1.7-0.8,4.6-1.3,7.9-1.1 +c4.8,0.3,8.7,1.8,9.1,3.6l0,0c0-0.7,0-1.2,0-1.2c-0.1-1.8-4.3-3.3-9.4-3.2C9.9,5.3,7,6,5.3,7C5.3,7,5.5,7.1,5.6,7.2L5.6,7.2z +M7.8,8.1c1.6-0.4,3.6-0.5,5.8-0.4c4.8,0.3,8.7,1.8,9.1,3.6v0c0-0.7,0-1.2,0-1.2c-0.1-1.8-4.3-3.3-9.4-3.2c-2.4,0-4.5,0.4-6.1,0.9 +C7.1,7.8,7.4,8,7.8,8.1L7.8,8.1z +M4,5.2c0.6-1.5,4.6-2.7,9.5-2.4c4.8,0.3,8.7,1.8,9.1,3.6l0-0.1c0-1-0.1-1.3-0.1-1.3 +c0-0.2-0.1-0.3-0.1-0.3c-0.7-1.6-4.5-2.8-9.2-2.7C8.4,2.1,4.4,3.5,4,5.2L4,5.2z" /> + <path + android:fillColor="#F16521" + android:pathData="M22.2,10.5c-1.1,1.4-4.7,2.5-8.9,2.5C8.2,13.1,4.1,11.7,4,9.9c0,0,0-0.4,0-1.2l0,0 +c0.4,1.7,4.3,3.3,9.1,3.6c4.2,0.3,7.8-0.5,9.1-1.9C22.1,10.4,22.2,10.5,22.2,10.5L22.2,10.5z +M21.2,9.7C21.1,9.6,21,9.5,21,9.5 +c-1.7,0.8-4.6,1.3-7.9,1.1C8.2,10.3,4.4,8.8,4,7.1l0,0c0,0.7,0,1.2,0,1.2c0.1,1.8,4.3,3.3,9.4,3.2C16.7,11.4,19.6,10.7,21.2,9.7 +L21.2,9.7z +M19.4,8.8c-0.4-0.1-0.7-0.2-0.7-0.2C17.2,9,15.2,9.1,13,9C8.2,8.7,4.4,7.1,4,5.4l0,0c0,0.7,0,1.2,0,1.2 +c0.1,1.8,4.3,3.3,9.4,3.2C15.7,9.7,17.8,9.4,19.4,8.8L19.4,8.8z +M22.5,11.5C22,13,17.9,14.2,13,13.9c-4.8-0.3-8.7-1.8-9.1-3.6 +l0,0.1c0,1,0.1,1.3,0.1,1.3c0,0.2,0.1,0.3,0.1,0.3c0.7,1.6,4.5,2.8,9.2,2.7C18.2,14.6,22.1,13.2,22.5,11.5L22.5,11.5z" /> + <path + android:fillColor="#FFFFFF" + android:pathData="M37.6,14.5c-2.4,0-4.3,0-4.3,0c-2.3,0.1-3.5,0-3.5,0c-2.5,0-4.5-1.7-4.6-3.9 +c-0.1-2.1,1.7-3.9,4.3-4c0,0,1.2-0.1,3.2,0.2l0-0.2l0-4.3l5,0l0,4.6H40V5.3l4.8-2.1l0,3.6l1.7,0l0,1.3c-0.9,0-1.7,0-1.7,0v2.4 +c0,0.1,0,1.2,0,1.5c0,0,0.1,0.7,0.6,1.1c0,0,0.3,0.3,1,0.3c0,0,0.2,0,0.6,0h1.1l0,0c0.9,0,1.1-0.2,1.1-0.2c0.4-0.2,0.6-0.5,0.6-0.9 +c0-0.3-0.1-0.6-0.3-0.8l0,0l-1.3-1.2C48,10,47.8,9.7,47.7,9.6l0,0c-0.2-0.3-0.2-0.6-0.2-0.9c0-0.6,0.4-1.2,0.9-1.5l0,0 +C48.8,6.9,51.2,6,55.6,7l0,1.1l-0.1,0c0,0-1.2-0.1-1.6,0l0,0c-0.4,0.1-0.6,0.3-0.6,0.7c0,0.2,0.1,0.4,0.2,0.5l0,0l1.7,1.7l0,0 +c0.4,0.4,0.6,0.8,0.6,1.4c0,0.9-0.6,1.6-1.4,1.9c0,0-0.5,0.2-1.3,0.2c0,0-0.4,0-1.5,0h-0.1c-3.9,0-8,0-8,0l-0.1,0 +c-2.6-0.1-3.1-2-3.1-2c-0.1-0.4-0.2-1.3-0.2-1.3l0-3.2l-2.4,0L37.6,14.5 +M29.8,10.7c0,1.3,0.6,2,0.6,2c0.4,0.5,1.2,0.6,1.2,0.6 +c0.4,0.1,1,0,1,0l0-5.3c0,0-0.6-0.1-1,0c0,0-0.7,0-1.2,0.7c0,0-0.6,0.7-0.6,2V10.7z +M27.4,22c-1.1,0-1.5-0.5-1.5-1.5v-0.1h0.6v0.1 +c0,0.6,0.1,1,0.8,1c0.6,0,0.8-0.3,0.8-0.9c0-0.7-0.4-0.9-0.9-1.1c-0.7-0.4-1.3-0.7-1.3-1.7c0-0.9,0.6-1.3,1.4-1.3 +c0.9,0,1.4,0.4,1.4,1.3V18h-0.6v-0.1c0-0.5-0.1-0.8-0.8-0.8c-0.5,0-0.8,0.3-0.8,0.8c0,0.7,0.5,0.9,1.1,1.2c0.6,0.4,1.1,0.6,1.1,1.6 +C28.8,21.5,28.3,22,27.4,22z +M33.9,22c-1.2,0-1.3-0.8-1.3-1.9c0-1.1,0.1-2,1.3-2c1.2,0,1.2,0.8,1.2,1.9C35.2,21.3,35.1,22,33.9,22z +M34.6,19.9c0-0.6,0-1.3-0.7-1.3c-0.7,0-0.7,0.8-0.7,1.3v0.5c0,0.5,0,1.1,0.7,1.1c0.6,0,0.7-0.6,0.7-1.1V19.9z +M41.2,21.9l0-0.5 +C41,21.8,40.7,22,40.3,22c-0.7,0-1-0.5-1-1.1v-2.6h0.6v2.4c0,0.4,0,1,0.6,1c0.6,0,0.7-0.6,0.7-1.1v-2.2h0.6v2.9c0,0.3,0,0.5,0,0.8 +H41.2z +M47.8,22v-2.4c0-0.4,0-1-0.6-1c-0.5,0-0.7,0.6-0.7,1.1V22h-0.6v-2.9c0-0.3,0-0.5,0-0.8h0.6v0.5c0.2-0.3,0.5-0.6,1-0.6 +c0.7,0,1,0.5,1,1.1V22H47.8z +M54.4,21.9l0-0.4C54.2,21.8,54,22,53.6,22c-1.1,0-1.1-1.1-1.1-2c0-0.9,0.1-1.9,1.1-1.9 +c0.4,0,0.7,0.1,0.8,0.4v-2H55v4.6c0,0.2,0,0.5,0,0.7H54.4z +M53.7,18.6c-0.7,0-0.7,0.8-0.7,1.5c0,0.8,0.1,1.5,0.7,1.5 +c0.7,0,0.7-0.8,0.7-1.4C54.4,19.3,54.4,18.6,53.7,18.6z +M55.1,2.1c0.2,0,0.3,0,0.5,0.1c0.1,0.1,0.3,0.2,0.3,0.3 +C56,2.8,56,2.9,56,3.1c0,0.2,0,0.3-0.1,0.5c-0.1,0.1-0.2,0.3-0.3,0.3C55.4,4,55.3,4,55.1,4c-0.2,0-0.3,0-0.5-0.1 +c-0.1-0.1-0.3-0.2-0.3-0.3c-0.1-0.1-0.1-0.3-0.1-0.5c0-0.2,0-0.3,0.1-0.5c0.1-0.1,0.2-0.3,0.3-0.3C54.8,2.2,55,2.1,55.1,2.1z +M55.1,2.3c-0.1,0-0.3,0-0.4,0.1c-0.1,0.1-0.2,0.2-0.3,0.3c-0.1,0.1-0.1,0.3-0.1,0.4c0,0.1,0,0.3,0.1,0.4c0.1,0.1,0.2,0.2,0.3,0.3 +c0.1,0.1,0.3,0.1,0.4,0.1c0.1,0,0.3,0,0.4-0.1c0.1-0.1,0.2-0.2,0.3-0.3c0.1-0.1,0.1-0.3,0.1-0.4c0-0.1,0-0.3-0.1-0.4 +c-0.1-0.1-0.2-0.2-0.3-0.3C55.4,2.3,55.2,2.3,55.1,2.3z +M54.7,3.6v-1H55c0.1,0,0.2,0,0.3,0c0.1,0,0.1,0.1,0.1,0.1c0,0,0,0.1,0,0.1 +c0,0.1,0,0.1-0.1,0.2c-0.1,0.1-0.1,0.1-0.2,0.1c0,0,0.1,0,0.1,0.1c0,0,0.1,0.1,0.1,0.2l0.1,0.2h-0.2l-0.1-0.2 +c-0.1-0.1-0.1-0.2-0.2-0.2c0,0-0.1,0-0.1,0h-0.1v0.4H54.7z +M54.9,3h0.2c0.1,0,0.2,0,0.2,0c0,0,0.1-0.1,0.1-0.1c0,0,0-0.1,0-0.1 +c0,0,0,0-0.1-0.1c0,0-0.1,0-0.2,0h-0.2V3z" /> + </group> +</vector>
\ No newline at end of file diff --git a/res/layout/action_bar.xml b/res/layout/action_bar.xml new file mode 100644 index 0000000..6477951 --- /dev/null +++ b/res/layout/action_bar.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <Spinner xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/spinner" + android:layout_weight="0" + android:dropDownWidth="wrap_content" + android:layout_width="wrap_content" + android:layout_height="wrap_content"/> + + <Space android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1"/> + + <CheckBox + android:layout_weight="0" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:id="@+id/device_toggle"/> + +</LinearLayout> diff --git a/res/layout/action_bar_spinner.xml b/res/layout/action_bar_spinner.xml new file mode 100644 index 0000000..67b81d1 --- /dev/null +++ b/res/layout/action_bar_spinner.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:padding="8dp"> + + <TextView android:id="@android:id/summary" + android:textSize="14sp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + android:gravity="center_vertical"/> + + <TextView android:id="@android:id/title" + android:textSize="18sp" + android:textStyle="bold" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentTop="true" + android:layout_above="@android:id/summary" + android:layout_alignWithParentIfMissing="true" + android:gravity="center_vertical"/> + +</RelativeLayout> + diff --git a/res/layout/action_bar_spinner_row.xml b/res/layout/action_bar_spinner_row.xml new file mode 100644 index 0000000..d081618 --- /dev/null +++ b/res/layout/action_bar_spinner_row.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<RelativeLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="64dp" + android:padding="8dp"> + + <TextView android:id="@android:id/summary" + android:textSize="14sp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + android:gravity="center_vertical"/> + + <TextView android:id="@android:id/title" + android:textSize="18sp" + android:textStyle="bold" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentTop="true" + android:layout_above="@android:id/summary" + android:layout_alignWithParentIfMissing="true" + android:gravity="center_vertical"/> + +</RelativeLayout> diff --git a/res/layout/activity_main.xml b/res/layout/activity_main.xml new file mode 100644 index 0000000..84c5337 --- /dev/null +++ b/res/layout/activity_main.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> + +<FrameLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:custom="http://schemas.android.com/apk/res/com.cyngn.audiofx" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <FrameLayout + android:id="@+id/main_fragment" + android:layout_width="match_parent" + android:layout_height="match_parent"/> + +</FrameLayout> diff --git a/res/layout/activity_main_generic.xml b/res/layout/activity_main_generic.xml deleted file mode 100644 index c33f544..0000000 --- a/res/layout/activity_main_generic.xml +++ /dev/null @@ -1,74 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> - -<com.cyngn.audiofx.widget.InterceptableLinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:custom="http://schemas.android.com/apk/res/com.cyngn.audiofx" - android:id="@+id/interceptable_layout" - android:orientation="vertical" - android:layout_width="match_parent" - android:layout_height="match_parent"> - - <com.cyngn.audiofx.eq.EqSwipeController - android:id="@+id/swipe_interceptor" - android:orientation="vertical" - android:layout_weight="1" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - <include - layout="@layout/eq_container" - android:layout_weight="1" - android:layout_width="match_parent" - android:layout_height="0dp"/> - - <LinearLayout - android:orientation="vertical" - android:id="@+id/preset_container" - android:layout_weight="0" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - - <com.cyngn.audiofx.preset.InfiniteViewPager - android:id="@+id/pager" - android:layout_width="match_parent" - android:layout_height="40dp" - /> - - <com.viewpagerindicator.CirclePageIndicator - android:id="@+id/indicator" - android:padding="10dip" - android:layout_weight="1" - android:layout_height="wrap_content" - android:layout_width="match_parent" - /> - - <android.support.v4.view.ViewPager - android:layout_height="0dp" - android:layout_width="0dp" - android:visibility="gone" - android:id="@+id/fake_pager" - /> - - </LinearLayout> - </com.cyngn.audiofx.eq.EqSwipeController> - - <LinearLayout - android:background="@color/knob_container_background" - android:orientation="vertical" - android:layout_width="match_parent" - android:layout_height="160dp" - android:elevation="8dp" - android:padding="4dp"> - - <com.cyngn.audiofx.knobs.KnobContainer - android:id="@+id/knob_container" - android:layout_width="match_parent" - android:layout_height="0dp" - android:gravity="top|center_horizontal" - android:orientation="horizontal" - android:animateLayoutChanges="true" - android:layout_weight="1"> - - </com.cyngn.audiofx.knobs.KnobContainer> - - </LinearLayout> -</com.cyngn.audiofx.widget.InterceptableLinearLayout> diff --git a/res/layout/activity_main_maxx_audio.xml b/res/layout/activity_main_maxx_audio.xml deleted file mode 100644 index 082f82b..0000000 --- a/res/layout/activity_main_maxx_audio.xml +++ /dev/null @@ -1,207 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> - -<com.cyngn.audiofx.widget.InterceptableLinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:custom="http://schemas.android.com/apk/res/com.cyngn.audiofx" - android:id="@+id/interceptable_layout" - android:orientation="vertical" - android:layout_width="match_parent" - android:layout_height="match_parent"> - - <com.cyngn.audiofx.eq.EqSwipeController - android:id="@+id/swipe_interceptor" - android:orientation="vertical" - android:layout_weight="1" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - - <include - layout="@layout/eq_container" - android:layout_weight="1" - android:layout_width="match_parent" - android:layout_height="0dp"/> - - <LinearLayout - android:orientation="vertical" - android:id="@+id/preset_container" - android:layout_weight="0" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - - <com.cyngn.audiofx.preset.InfiniteViewPager - android:id="@+id/pager" - android:layout_width="match_parent" - android:layout_height="40dp" - /> - - <com.viewpagerindicator.CirclePageIndicator - android:id="@+id/indicator" - android:padding="10dip" - android:layout_weight="1" - android:layout_height="wrap_content" - android:layout_width="match_parent" - /> - - <android.support.v4.view.ViewPager - android:layout_height="0dp" - android:layout_width="0dp" - android:visibility="gone" - android:id="@+id/fake_pager" - /> - </LinearLayout> - - </com.cyngn.audiofx.eq.EqSwipeController> - - <LinearLayout - android:background="@color/knob_container_background" - android:orientation="vertical" - android:layout_width="match_parent" - android:layout_height="200dp" - android:elevation="8dp" - android:padding="4dp"> - - <LinearLayout - android:paddingLeft="30dp" - android:paddingRight="30dp" - android:orientation="horizontal" - android:layout_width="match_parent" - android:minHeight="?android:listPreferredItemHeightSmall" - android:layout_height="wrap_content" - android:gravity="center_horizontal"> - - <ImageView - android:layout_width="83dp" - android:layout_height="22dp" - android:layout_gravity="center_vertical" - android:src="@drawable/maxvolume_white" - android:scaleType="fitCenter" - /> - - <Space - android:layout_width="12dp" - android:layout_height="match_parent"/> - - <CheckBox - android:id="@+id/maxx_volume_switch" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:button="@drawable/toggle_check" - android:gravity="center_vertical" - android:layout_gravity="center_vertical"/> - - </LinearLayout> - - <com.cyngn.audiofx.knobs.KnobContainer - android:id="@+id/knob_container" - android:layout_width="match_parent" - android:layout_height="0dp" - android:gravity="top|center_horizontal" - android:orientation="horizontal" - android:animateLayoutChanges="true" - android:layout_weight="1"> - - <Space - android:layout_weight="0.1" - android:layout_width="0dp" - android:layout_height="match_parent"/> - - <FrameLayout - android:id="@+id/treble_knob_container" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_weight="0" - android:layout_gravity="center_horizontal" - android:paddingBottom="@dimen/knob_container_padding_bottom"> - - <com.cyngn.audiofx.knobs.RadialKnob - android:id="@+id/knob" - android:layout_width="@dimen/knob_width" - android:layout_gravity="top|center_horizontal" - android:layout_height="wrap_content" - android:layout_centerHorizontal="true" - custom:foreground="@drawable/knob" - /> - - <ImageView - android:id="@+id/label" - android:layout_gravity="bottom|center_horizontal" - android:layout_width="76dp" - android:layout_height="22dp" - android:src="@drawable/maxxreble_white" - android:scaleType="fitCenter"/> - - </FrameLayout> - - <Space - android:layout_weight="0.1" - android:layout_width="0dp" - android:layout_height="match_parent"/> - - <FrameLayout - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_gravity="center_horizontal" - android:layout_weight="0" - android:id="@+id/bass_knob_container" - android:paddingBottom="@dimen/knob_container_padding_bottom"> - - <com.cyngn.audiofx.knobs.RadialKnob - android:id="@+id/knob" - android:layout_gravity="top|center_horizontal" - android:layout_width="@dimen/knob_width" - android:layout_height="wrap_content" - android:layout_centerHorizontal="true" - custom:foreground="@drawable/knob"/> - - <ImageView - android:id="@+id/label" - android:layout_gravity="bottom|center_horizontal" - android:layout_width="68dp" - android:layout_height="22dp" - android:src="@drawable/maxxbass_white" - android:scaleType="fitCenter"/> - - </FrameLayout> - - <Space - android:layout_weight="0.1" - android:layout_width="0dp" - android:layout_height="match_parent"/> - - <FrameLayout - android:visibility="gone" - android:id="@+id/virtualizer_knob_container" - android:layout_width="wrap_content" - android:layout_weight="0" - android:layout_height="match_parent" - android:layout_gravity="center_horizontal" - android:paddingBottom="@dimen/knob_container_padding_bottom"> - - <com.cyngn.audiofx.knobs.RadialKnob - android:id="@+id/knob" - android:layout_gravity="top|center_horizontal" - android:layout_width="@dimen/knob_width" - android:layout_height="wrap_content" - custom:foreground="@drawable/knob"/> - - - <ImageView - android:id="@+id/label" - android:layout_gravity="bottom|center_horizontal" - android:layout_width="69dp" - android:layout_height="22dp" - android:src="@drawable/maxxspace_white" - android:scaleType="fitCenter" - /> - </FrameLayout> - - <Space - android:visibility="gone" - android:layout_weight="0.1" - android:layout_width="0dp" - android:layout_height="match_parent"/> - - </com.cyngn.audiofx.knobs.KnobContainer> - - </LinearLayout> -</com.cyngn.audiofx.widget.InterceptableLinearLayout> diff --git a/res/layout/controls_generic.xml b/res/layout/controls_generic.xml new file mode 100644 index 0000000..44f6a7b --- /dev/null +++ b/res/layout/controls_generic.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:background="@color/knob_container_background" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="160dp" + android:elevation="8dp" + android:padding="4dp"> + + <com.cyngn.audiofx.knobs.KnobContainer + android:id="@+id/knob_container" + android:layout_width="match_parent" + android:layout_height="0dp" + android:gravity="top|center_horizontal" + android:orientation="horizontal" + android:animateLayoutChanges="true" + android:layout_weight="1"> + + </com.cyngn.audiofx.knobs.KnobContainer> + +</LinearLayout> diff --git a/res/layout/controls_maxx_audio.xml b/res/layout/controls_maxx_audio.xml new file mode 100644 index 0000000..410f1a3 --- /dev/null +++ b/res/layout/controls_maxx_audio.xml @@ -0,0 +1,152 @@ +<?xml version="1.0" encoding="utf-8"?> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:custom="http://schemas.android.com/apk/res/com.cyngn.audiofx" + android:background="@color/knob_container_background" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="200dp" + android:elevation="8dp" + android:padding="4dp"> + + <LinearLayout + android:paddingLeft="30dp" + android:paddingRight="30dp" + android:orientation="horizontal" + android:layout_width="match_parent" + android:minHeight="?android:listPreferredItemHeightSmall" + android:layout_height="wrap_content" + android:gravity="center_horizontal"> + + <ImageView + android:layout_width="83dp" + android:layout_height="22dp" + android:layout_gravity="center_vertical" + android:src="@drawable/maxvolume_white" + android:scaleType="fitCenter"/> + + <Space + android:layout_width="12dp" + android:layout_height="match_parent"/> + + <CheckBox + android:id="@+id/maxx_volume_switch" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:button="@drawable/toggle_check" + android:gravity="center_vertical" + android:layout_gravity="center_vertical"/> + + </LinearLayout> + + <com.cyngn.audiofx.knobs.KnobContainer + android:id="@+id/knob_container" + android:layout_width="match_parent" + android:layout_height="0dp" + android:gravity="top|center_horizontal" + android:orientation="horizontal" + android:animateLayoutChanges="true" + android:layout_weight="1"> + + <Space + android:layout_weight="0.1" + android:layout_width="0dp" + android:layout_height="match_parent"/> + + <FrameLayout + android:id="@+id/treble_knob_container" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_weight="0" + android:layout_gravity="center_horizontal" + android:paddingBottom="@dimen/knob_container_padding_bottom"> + + <com.cyngn.audiofx.knobs.RadialKnob + android:id="@+id/knob" + android:layout_width="@dimen/knob_width" + android:layout_gravity="top|center_horizontal" + android:layout_height="wrap_content" + android:layout_centerHorizontal="true" + custom:foreground="@drawable/knob"/> + + <ImageView + android:id="@+id/label" + android:layout_gravity="bottom|center_horizontal" + android:layout_width="76dp" + android:layout_height="22dp" + android:src="@drawable/maxxreble_white" + android:scaleType="fitCenter"/> + + </FrameLayout> + + <Space + android:layout_weight="0.1" + android:layout_width="0dp" + android:layout_height="match_parent"/> + + <FrameLayout + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_gravity="center_horizontal" + android:layout_weight="0" + android:id="@+id/bass_knob_container" + android:paddingBottom="@dimen/knob_container_padding_bottom"> + + <com.cyngn.audiofx.knobs.RadialKnob + android:id="@+id/knob" + android:layout_gravity="top|center_horizontal" + android:layout_width="@dimen/knob_width" + android:layout_height="wrap_content" + android:layout_centerHorizontal="true" + custom:foreground="@drawable/knob"/> + + <ImageView + android:id="@+id/label" + android:layout_gravity="bottom|center_horizontal" + android:layout_width="68dp" + android:layout_height="22dp" + android:src="@drawable/maxxbass_white" + android:scaleType="fitCenter"/> + + </FrameLayout> + + <Space + android:layout_weight="0.1" + android:layout_width="0dp" + android:layout_height="match_parent"/> + + <FrameLayout + android:visibility="gone" + android:id="@+id/virtualizer_knob_container" + android:layout_width="wrap_content" + android:layout_weight="0" + android:layout_height="match_parent" + android:layout_gravity="center_horizontal" + android:paddingBottom="@dimen/knob_container_padding_bottom"> + + <com.cyngn.audiofx.knobs.RadialKnob + android:id="@+id/knob" + android:layout_gravity="top|center_horizontal" + android:layout_width="@dimen/knob_width" + android:layout_height="wrap_content" + custom:foreground="@drawable/knob"/> + + + <ImageView + android:id="@+id/label" + android:layout_gravity="bottom|center_horizontal" + android:layout_width="69dp" + android:layout_height="22dp" + android:src="@drawable/maxxspace_white" + android:scaleType="fitCenter"/> + </FrameLayout> + + <Space + android:visibility="gone" + android:layout_weight="0.1" + android:layout_width="0dp" + android:layout_height="match_parent"/> + + </com.cyngn.audiofx.knobs.KnobContainer> + +</LinearLayout> diff --git a/res/layout/equalizer.xml b/res/layout/equalizer.xml index 2ebee34..883385d 100644 --- a/res/layout/equalizer.xml +++ b/res/layout/equalizer.xml @@ -1,16 +1,44 @@ <?xml version="1.0" encoding="utf-8"?> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="vertical" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_gravity="center" - android:background="#cc191919" - > +<com.cyngn.audiofx.eq.EqSwipeController + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/swipe_interceptor" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <include + layout="@layout/eq_container" + android:layout_weight="1" + android:layout_width="match_parent" + android:layout_height="0dp"/> - <org.cyanogenmod.audiofx.widget.EqualizerSurface - android:id="@+id/frequencyResponse" - android:layout_height="match_parent" - android:layout_width="match_parent" /> + <LinearLayout + android:orientation="vertical" + android:id="@+id/preset_container" + android:layout_weight="0" + android:layout_width="match_parent" + android:layout_height="wrap_content"> -</LinearLayout> + <com.cyngn.audiofx.preset.InfiniteViewPager + android:id="@+id/pager" + android:layout_width="match_parent" + android:layout_height="40dp" + /> + + <com.viewpagerindicator.CirclePageIndicator + android:id="@+id/indicator" + android:padding="10dip" + android:layout_weight="1" + android:layout_height="wrap_content" + android:layout_width="match_parent" + /> + + <android.support.v4.view.ViewPager + android:layout_height="0dp" + android:layout_width="0dp" + android:visibility="gone" + android:id="@+id/fake_pager" + /> + + </LinearLayout> +</com.cyngn.audiofx.eq.EqSwipeController> diff --git a/res/layout/fragment_audiofx.xml b/res/layout/fragment_audiofx.xml new file mode 100644 index 0000000..c4bb367 --- /dev/null +++ b/res/layout/fragment_audiofx.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> + +<com.cyngn.audiofx.widget.InterceptableLinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:custom="http://schemas.android.com/apk/res/com.cyngn.audiofx" + android:id="@+id/interceptable_layout" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <!-- equalizer layout --> + <FrameLayout class="com.cyngn.audiofx.fragment.EqualizerFragment" + android:id="@+id/equalizer" + android:layout_weight="1" + android:layout_width="match_parent" + android:layout_height="0dp"/> + + <!-- knobs --> + <FrameLayout class="com.cyngn.audiofx.fragment.ControlsFragment" + android:id="@+id/controls" + android:layout_weight="0" + android:layout_width="match_parent" + android:layout_height="160dp"/> + +</com.cyngn.audiofx.widget.InterceptableLinearLayout> diff --git a/res/layout/fragment_audiofx_maxxaudio.xml b/res/layout/fragment_audiofx_maxxaudio.xml new file mode 100644 index 0000000..3f5a022 --- /dev/null +++ b/res/layout/fragment_audiofx_maxxaudio.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> + +<com.cyngn.audiofx.widget.InterceptableLinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:custom="http://schemas.android.com/apk/res/com.cyngn.audiofx" + android:id="@+id/interceptable_layout" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <!-- equalizer layout --> + <FrameLayout class="com.cyngn.audiofx.fragment.EqualizerFragment" + android:id="@+id/equalizer" + android:layout_weight="1" + android:layout_width="match_parent" + android:layout_height="0dp"/> + + <!-- knobs --> + <FrameLayout class="com.cyngn.audiofx.fragment.ControlsFragment" + android:id="@+id/controls" + android:layout_weight="0" + android:layout_width="match_parent" + android:layout_height="200dp"/> + +</com.cyngn.audiofx.widget.InterceptableLinearLayout> diff --git a/res/layout/fragment_dts.xml b/res/layout/fragment_dts.xml new file mode 100644 index 0000000..785b996 --- /dev/null +++ b/res/layout/fragment_dts.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8"?> + +<RelativeLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <ImageView + android:id="@+id/logo" + android:layout_width="120dp" + android:layout_height="48dp" + android:layout_centerInParent="true" + android:src="@drawable/logo_dts_1c" + /> + +</RelativeLayout> diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml index 085a250..12fd26a 100644 --- a/res/values/cm_strings.xml +++ b/res/values/cm_strings.xml @@ -58,4 +58,7 @@ <string name="remove_custom_preset_warning_message">Are you sure you want to remove %1$s?</string> + <string name="mode_audiofx"></string> + <string name="mode_dts">with DTS Sound™</string> + </resources> diff --git a/res/values/dimens.xml b/res/values/dimens.xml index c778cf0..65b5fef 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -41,4 +41,8 @@ <dimen name="radial_rect_padding">8dp</dimen> <dimen name="radial_knob_stroke">22dp</dimen> + + <!-- 16 dp + 64 dp --> + <dimen name="action_bar_dts_switch_padding">48dp</dimen> + </resources> diff --git a/src/com/cyngn/audiofx/Constants.java b/src/com/cyngn/audiofx/Constants.java index 7399e8d..1545c23 100644 --- a/src/com/cyngn/audiofx/Constants.java +++ b/src/com/cyngn/audiofx/Constants.java @@ -15,15 +15,28 @@ */ package com.cyngn.audiofx; +import android.content.Context; +import android.content.SharedPreferences; + public class Constants { - // per-device settings + // global settings + public static final String AUDIOFX_GLOBAL_FILE = "global"; + + public static final String AUDIOFX_GLOBAL_USE_DTS = "audiofx.global.use_dts"; + public static final String AUDIOFX_GLOBAL_HAS_DTS = "audiofx.global.has_dts"; + public static final String AUDIOFX_GLOBAL_ENABLE_DTS = "audiofx.global.dts.enable"; + public static final String AUDIOFX_GLOBAL_HAS_MAXXAUDIO = "audiofx.global.hasmaxxaudio"; + public static final String AUDIOFX_GLOBAL_HAS_BASSBOOST = "audiofx.global.hasbassboost"; + public static final String AUDIOFX_GLOBAL_HAS_VIRTUALIZER = "audiofx.global.hasvirtualizer"; + // per-device settings public static final boolean DEVICE_DEFAULT_GLOBAL_ENABLE = false; + + /** + * not really global enable, but really the device global enable... + */ public static final String DEVICE_AUDIOFX_GLOBAL_ENABLE = "audiofx.global.enable"; - public static final String DEVICE_AUDIOFX_GLOBAL_HAS_MAXXAUDIO = "audiofx.global.hasmaxxaudio"; - public static final String DEVICE_AUDIOFX_GLOBAL_HAS_BASSBOOST = "audiofx.global.hasbassboost"; - public static final String DEVICE_AUDIOFX_GLOBAL_HAS_VIRTUALIZER = "audiofx.global.hasvirtualizer"; public static final String DEVICE_AUDIOFX_BASS_ENABLE = "audiofx.bass.enable"; public static final String DEVICE_AUDIOFX_BASS_STRENGTH = "audiofx.bass.strength"; public static final String DEVICE_AUDIOFX_REVERB_PRESET = "audiofx.reverb.preset"; @@ -35,4 +48,8 @@ public class Constants { public static final String DEVICE_AUDIOFX_EQ_PRESET = "audiofx.eq.preset"; public static final String DEVICE_AUDIOFX_EQ_PRESET_LEVELS = "audiofx.eq.preset.levels"; + + public static SharedPreferences getGlobalPrefs(Context context) { + return context.getSharedPreferences(AUDIOFX_GLOBAL_FILE, 0); + } } diff --git a/src/com/cyngn/audiofx/activity/ActivityMusic.java b/src/com/cyngn/audiofx/activity/ActivityMusic.java index cc7a375..d6d2ec9 100644 --- a/src/com/cyngn/audiofx/activity/ActivityMusic.java +++ b/src/com/cyngn/audiofx/activity/ActivityMusic.java @@ -1,850 +1,326 @@ package com.cyngn.audiofx.activity; -import android.animation.Animator; -import android.animation.ArgbEvaluator; -import android.animation.ValueAnimator; import android.app.ActionBar; import android.app.Activity; -import android.app.AlertDialog; -import android.content.DialogInterface; -import android.content.BroadcastReceiver; import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.hardware.usb.UsbManager; -import android.media.AudioManager; -import android.media.AudioService; +import android.content.res.Configuration; import android.os.Bundle; -import android.os.Handler; -import android.support.v4.view.ViewPager; -import android.util.ArrayMap; import android.util.Log; import android.view.Gravity; +import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; -import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; import android.widget.CheckBox; import android.widget.CompoundButton; -import android.widget.EditText; +import android.widget.Spinner; import android.widget.TextView; - -import com.cyngn.audiofx.knobs.KnobCommander; -import com.cyngn.audiofx.service.AudioFxService; -import com.cyngn.audiofx.service.OutputDevice; -import com.viewpagerindicator.CirclePageIndicator; -import com.viewpagerindicator.PageIndicator; +import com.cyngn.audiofx.Constants; import com.cyngn.audiofx.R; -import com.cyngn.audiofx.eq.EqContainerView; -import com.cyngn.audiofx.knobs.KnobContainer; -import com.cyngn.audiofx.preset.InfinitePagerAdapter; -import com.cyngn.audiofx.preset.InfiniteViewPager; -import com.cyngn.audiofx.preset.PresetPagerAdapter; -import com.cyngn.audiofx.widget.InterceptableLinearLayout; +import com.cyngn.audiofx.fragment.AudioFxFragment; +import com.cyngn.audiofx.fragment.DTSFragment; +import com.cyngn.audiofx.service.DtsControl; +import java.util.ArrayList; import java.util.List; -import java.util.Map; -public class ActivityMusic extends Activity implements MasterConfigControl.EqUpdatedCallback { +public class ActivityMusic extends Activity { private static final String TAG = ActivityMusic.class.getSimpleName(); private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); - private static final boolean DEBUG_VIEWPAGER = false; - private final ArgbEvaluator mArgbEval = new ArgbEvaluator(); - MasterConfigControl mConfig; - KnobCommander mKnobCommander; - Handler mHandler; - KnobContainer mKnobContainer; - EqContainerView mEqContainer; - ViewGroup mPresetContainer; - InfiniteViewPager mViewPager; - PageIndicator mPresetPageIndicator; - PresetPagerAdapter mDataAdapter; - InfinitePagerAdapter mInfiniteAdapter; - InterceptableLinearLayout mInterceptLayout; - CheckBox mMaxxVolumeSwitch; - int mCurrentBackgroundColor; - int mCurrentRealPage; - - // whether we are in the middle of animating while switching devices - boolean mDeviceChanging; - - private MenuItem mMenuDevices; - private ViewPager mFakePager; + + public static final int CURRENT_MODE_AUDIOFX = 1; + public static final int CURRENT_MODE_DTS = 2; + + public static final String TAG_AUDIOFX = "audiofx"; + public static final String TAG_DTS = "dts"; + + private int mCurrentMode = CURRENT_MODE_AUDIOFX; + private Spinner mSpinner; + DtsControl mDts; + private CheckBox mCurrentDeviceToggle; + MasterConfigControl mConfig; - private ValueAnimator mDeviceChangeAnimation; - private int mAnimatingToRealPageTarget = -1; + private List<ActivityStateListener> mGlobalToggleListeners = new ArrayList<>(); - /* - * this array can hold on to arrays which store preset levels, - * so modifying values in here should only be done with extreme care - */ - private float[] mSelectedPositionBands; + public interface ActivityStateListener { + public void onGlobalToggleChanged(final CompoundButton buttonView, boolean isChecked); - // current selected index - public int mSelectedPosition = 0; - private Map<Integer, OutputDevice> mBluetoothMap - = new ArrayMap<Integer, OutputDevice>(); - List<OutputDevice> mBluetoothDevices = null; - private boolean mResumeDeviceChanged; - private boolean mUsbDeviceConnected; + public void onModeChanged(int mode); + } - private BroadcastReceiver mDevicesChangedReceiver = new BroadcastReceiver() { + private CompoundButton.OnCheckedChangeListener mGlobalEnableToggleListener + = new CompoundButton.OnCheckedChangeListener() { @Override - public void onReceive(Context context, Intent intent) { - if (AudioFxService.ACTION_BLUETOOTH_DEVICES_UPDATED.equals(intent.getAction())) { - runOnUiThread(new Runnable() { - @Override - public void run() { - mBluetoothDevices = mConfig.getBluetoothDevices(); - invalidateOptionsMenu(); - } - }); - } else if (AudioFxService.ACTION_DEVICE_OUTPUT_CHANGED.equals(intent.getAction())) { - invalidateOptionsMenu(); - } else if (AudioManager.ACTION_DIGITAL_AUDIO_DOCK_PLUG.equals(intent.getAction()) - || AudioManager.ACTION_ANALOG_AUDIO_DOCK_PLUG.equals(intent.getAction()) - || AudioManager.ACTION_USB_AUDIO_DEVICE_PLUG.equals(intent.getAction())) { - boolean connected = intent.getIntExtra("state", 0) == 1; - mUsbDeviceConnected = connected; - invalidateOptionsMenu(); + public void onCheckedChanged(final CompoundButton buttonView, + final boolean isChecked) { + for (ActivityStateListener listener : mGlobalToggleListeners) { + listener.onGlobalToggleChanged(buttonView, isChecked); } } }; @Override public void onCreate(Bundle savedInstanceState) { + if (DEBUG) + Log.i(TAG, "onCreate() called with " + + "savedInstanceState = [" + savedInstanceState + "]"); super.onCreate(savedInstanceState); - if (DEBUG) Log.d(TAG, "onCreate() savedInstanceState=" + savedInstanceState); - mHandler = new Handler(); + mDts = new DtsControl(this); mConfig = MasterConfigControl.getInstance(this); - mKnobCommander = KnobCommander.getInstance(this); - - mSelectedPositionBands = mConfig.getPersistedPresetLevels(mConfig.getCurrentPresetIndex()); - if (mConfig.hasMaxxAudio()) { - setContentView(R.layout.activity_main_maxx_audio); - } else { - setContentView(R.layout.activity_main_generic); - } - - mInterceptLayout = (InterceptableLinearLayout) findViewById(R.id.interceptable_layout); - - mKnobContainer = (KnobContainer) findViewById(R.id.knob_container); - mMaxxVolumeSwitch = (CheckBox) findViewById(R.id.maxx_volume_switch); - mEqContainer = (EqContainerView) findViewById(R.id.eq_container); - mPresetContainer = (ViewGroup) findViewById(R.id.preset_container); - mViewPager = (InfiniteViewPager) findViewById(R.id.pager); - CirclePageIndicator indicator = (CirclePageIndicator) findViewById(R.id.indicator); - mPresetPageIndicator = indicator; - - if (mMaxxVolumeSwitch != null) { - mMaxxVolumeSwitch.setOnCheckedChangeListener(mMaxxVolumeListener); - } - - final PresetPagerAdapter adapter = new PresetPagerAdapter(this); - InfinitePagerAdapter infinitePagerAdapter = new InfinitePagerAdapter(adapter); - - mInfiniteAdapter = infinitePagerAdapter; - mDataAdapter = adapter; - - mViewPager.setAdapter(mInfiniteAdapter); - mFakePager = (ViewPager) findViewById(R.id.fake_pager); - - mViewPager.setOnPageChangeListener(mViewPageChangeListener); - - mViewPager.setCurrentItem(mSelectedPosition = mConfig.getCurrentPresetIndex()); - - mFakePager.setAdapter(adapter); - mEqContainer.findViewById(R.id.save).setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - - final int newidx = mConfig.addPresetFromCustom(); - mInfiniteAdapter.notifyDataSetChanged(); - mDataAdapter.notifyDataSetChanged(); - mPresetPageIndicator.notifyDataSetChanged(); - - jumpToPreset(newidx); - } - } - ); - mEqContainer.findViewById(R.id.rename).setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - if (mConfig.isUserPreset()) { - openRenameDialog(); - } - } - } - ); - mEqContainer.findViewById(R.id.remove).setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View v) { - removeCurrentCustomPreset(true); - } - } - ); - - indicator.setViewPager(mFakePager, mConfig.getCurrentPresetIndex()); - indicator.setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - // eat all events - return true; - } - }); - indicator.setSnap(true); - - mCurrentRealPage = mInfiniteAdapter.getRealCount() * 100; - - // setup actionbar on off switch - mCurrentDeviceToggle = new CheckBox(this); - final int padding = getResources().getDimensionPixelSize( - R.dimen.action_bar_switch_padding); - mCurrentDeviceToggle.setPaddingRelative(0, 0, padding, 0); - mCurrentDeviceToggle.setButtonDrawable(R.drawable.toggle_check); - mCurrentDeviceToggle.setOnCheckedChangeListener(mGlobalEnableToggleListener); - - final ActionBar.LayoutParams params = new ActionBar.LayoutParams( - ActionBar.LayoutParams.WRAP_CONTENT, - ActionBar.LayoutParams.WRAP_CONTENT, - Gravity.CENTER_VERTICAL | Gravity.END); ActionBar ab = getActionBar(); ab.setTitle(R.string.app_title); - if (mConfig.hasMaxxAudio()) { - ab.setSubtitle(R.string.app_subtitle); - } - ab.setCustomView(mCurrentDeviceToggle, params); - ab.setHomeButtonEnabled(true); - ab.setDisplayShowTitleEnabled(true); ab.setDisplayShowCustomEnabled(true); - mCurrentBackgroundColor = !mConfig.isCurrentDeviceEnabled() - ? getResources().getColor(R.color.disabled_eq) - : mConfig.getAssociatedPresetColorHex(mConfig.getCurrentPresetIndex()); - updateBackgroundColors(mCurrentBackgroundColor); - } + if (mDts.hasDts()) { + ab.setCustomView(R.layout.action_bar); - private void removeCurrentCustomPreset(boolean showWarning) { - if (showWarning) { - MasterConfigControl.Preset p = mConfig.getCurrentPreset(); - new AlertDialog.Builder(ActivityMusic.this) - .setMessage(String.format(getString( - R.string.remove_custom_preset_warning_message), p.mName)) - .setNegativeButton(android.R.string.no, null) - .setPositiveButton(android.R.string.yes, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - removeCurrentCustomPreset(false); - } - }) - .create() - .show(); - return; - } + mCurrentDeviceToggle = (CheckBox) findViewById(R.id.device_toggle); + final int padding = getResources().getDimensionPixelSize( + R.dimen.action_bar_switch_padding); + mCurrentDeviceToggle.setPaddingRelative(mCurrentDeviceToggle.getPaddingLeft(), + mCurrentDeviceToggle.getPaddingTop(), + padding, + mCurrentDeviceToggle.getPaddingBottom()); - final int currentIndexBeforeRemove = mConfig.getCurrentPresetIndex(); - if (mConfig.removePreset(currentIndexBeforeRemove)) { - mInfiniteAdapter.notifyDataSetChanged(); - mDataAdapter.notifyDataSetChanged(); - mPresetPageIndicator.notifyDataSetChanged(); + mCurrentDeviceToggle.setButtonDrawable(R.drawable.toggle_check); + mCurrentDeviceToggle.setOnCheckedChangeListener(mGlobalEnableToggleListener); - jumpToPreset(mSelectedPosition - 1); - } - } + ModeAdapter spinnerAdapter = new ModeAdapter(this); - private void openRenameDialog() { - AlertDialog.Builder renameDialog = new AlertDialog.Builder(this); - renameDialog.setTitle(R.string.rename); - final EditText newName = new EditText(this); - newName.setText(mConfig.getCurrentPreset().mName); - renameDialog.setView(newName); - renameDialog.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - - public void onClick(DialogInterface d, int which) { - mConfig.renameCurrentPreset(newName.getText().toString()); - final TextView viewWithTag = (TextView) mViewPager.findViewWithTag(mConfig.getCurrentPreset()); - viewWithTag.setText(newName.getText().toString()); - mDataAdapter.notifyDataSetChanged(); - mViewPager.invalidate(); - } - }); + mSpinner = (Spinner) findViewById(R.id.spinner); + mSpinner.setAdapter(spinnerAdapter); - renameDialog.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { - - public void onClick(DialogInterface d, int which) { + final boolean shouldUseDts = mDts.shouldUseDts(); + setCurrentMode(shouldUseDts ? CURRENT_MODE_DTS : CURRENT_MODE_AUDIOFX); + mSpinner.setSelection(shouldUseDts ? 1 : 0, false); + } else { + // manually populate action bar + if (mConfig.hasMaxxAudio()) { + ab.setDisplayShowTitleEnabled(true); + ab.setSubtitle(R.string.app_subtitle); } - }); - - renameDialog.show(); - } - - private void updateEnabledState() { - final OutputDevice device = mConfig.getCurrentDevice(); - boolean currentDeviceEnabled = mConfig.isCurrentDeviceEnabled(); - - if (DEBUG) { - Log.d(TAG, "updating with current device: " + device); - } - - if (mCurrentDeviceToggle != null) { - mCurrentDeviceToggle.setChecked(currentDeviceEnabled); - } - if (mInterceptLayout != null) { - mInterceptLayout.setInterception(!currentDeviceEnabled); + // setup actionbar on off switch + mCurrentDeviceToggle = new CheckBox(this); + final int padding = getResources().getDimensionPixelSize( + R.dimen.action_bar_switch_padding); + mCurrentDeviceToggle.setPaddingRelative(0, 0, padding, 0); + mCurrentDeviceToggle.setButtonDrawable(R.drawable.toggle_check); + mCurrentDeviceToggle.setOnCheckedChangeListener(mGlobalEnableToggleListener); + + final ActionBar.LayoutParams params = new ActionBar.LayoutParams( + ActionBar.LayoutParams.WRAP_CONTENT, + ActionBar.LayoutParams.WRAP_CONTENT, + Gravity.CENTER_VERTICAL | Gravity.END); + ab.setCustomView(mCurrentDeviceToggle, params); } - if (mMaxxVolumeSwitch != null) { - mMaxxVolumeSwitch.setChecked(mConfig.getMaxxVolumeEnabled()); - mMaxxVolumeSwitch.setEnabled(currentDeviceEnabled); - } - } - - private void updateActionBarDeviceIcon() { - if (mMenuDevices != null) { - int icon = 0; - switch (mConfig.getCurrentDevice().getDeviceType()) { - case OutputDevice.DEVICE_HEADSET: - icon = R.drawable.ic_action_dsp_icons_headphones; - break; - - case OutputDevice.DEVICE_SPEAKER: - icon = R.drawable.ic_action_dsp_icons_speaker; - break; - - case OutputDevice.DEVICE_USB: - icon = R.drawable.ic_action_dsp_icons_usb; - break; - - case OutputDevice.DEVICE_BLUETOOTH: - icon = R.drawable.ic_action_dsp_icons_bluetoof; - break; - - case OutputDevice.DEVICE_WIRELESS: - // TODO add wireless back - break; - - } - mMenuDevices.setIcon(icon); + setContentView(R.layout.activity_main); + + if (savedInstanceState == null && findViewById(R.id.main_fragment) != null) { + getFragmentManager() + .beginTransaction() + .add(R.id.main_fragment, + mCurrentMode == CURRENT_MODE_AUDIOFX + ? new AudioFxFragment() + : new DTSFragment(), + TAG_AUDIOFX) + .commit(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { - super.onCreateOptionsMenu(menu); - getMenuInflater().inflate(R.menu.devices, menu); - mMenuDevices = menu.findItem(R.id.devices); - - return true; + return super.onCreateOptionsMenu(menu); } @Override public boolean onPrepareOptionsMenu(Menu menu) { - super.onPrepareOptionsMenu(menu); - final OutputDevice currentDevice = mConfig.getCurrentDevice(); - updateActionBarDeviceIcon(); - - final MenuItem usb = menu.findItem(R.id.device_usb); - usb.setVisible(mUsbDeviceConnected); - - // select proper device - if (mConfig.isServiceBound()) { - MenuItem selectedItem = null; - - if (mBluetoothDevices != null) { - // remove previous bluetooth entries - for (Integer id : mBluetoothMap.keySet()) { - mMenuDevices.getSubMenu().removeItem(id); - } - mBluetoothMap.clear(); - - for (int i = 0; i < mBluetoothDevices.size(); i++) { - int viewId = View.generateViewId(); - mBluetoothMap.put(viewId, mBluetoothDevices.get(i)); - MenuItem item = mMenuDevices.getSubMenu().add(R.id.device_group, viewId, i, - mBluetoothDevices.get(i).getDisplayName()); - if (mBluetoothDevices.get(i).equals(currentDevice)) { - selectedItem = item; - } - item.setIcon(R.drawable.ic_action_dsp_icons_bluetoof); - } - } - mMenuDevices.getSubMenu().setGroupCheckable(R.id.device_group, true, true); - - switch (currentDevice.getDeviceType()) { - case OutputDevice.DEVICE_SPEAKER: - selectedItem = mMenuDevices.getSubMenu().findItem(R.id.device_speaker); - break; - case OutputDevice.DEVICE_USB: - selectedItem = mMenuDevices.getSubMenu().findItem(R.id.device_usb); - break; - case OutputDevice.DEVICE_HEADSET: - selectedItem = mMenuDevices.getSubMenu().findItem(R.id.device_headset); - break; - } - if (selectedItem != null) { - selectedItem.setChecked(true); - } + if (mDts.hasDts()) { + final boolean audioFX = mCurrentMode == CURRENT_MODE_AUDIOFX; + final int padding = getResources().getDimensionPixelSize( + audioFX ? R.dimen.action_bar_switch_padding + : R.dimen.action_bar_dts_switch_padding); + + mCurrentDeviceToggle.setPaddingRelative(mCurrentDeviceToggle.getPaddingLeft(), + mCurrentDeviceToggle.getPaddingTop(), + padding, + mCurrentDeviceToggle.getPaddingBottom()); } - - return true; + return super.onPrepareOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { - OutputDevice newDevice = null; - switch (item.getItemId()) { - case R.id.device_headset: - newDevice = new OutputDevice(OutputDevice.DEVICE_HEADSET); - break; - - case R.id.device_usb: - newDevice = new OutputDevice(OutputDevice.DEVICE_USB); - break; - - case R.id.device_speaker: - newDevice = new OutputDevice(OutputDevice.DEVICE_SPEAKER); - break; - - default: - newDevice = mBluetoothMap.get(item.getItemId()); - break; - - } - if (newDevice != null) { - mDeviceChanging = true; - if (item.isCheckable()) { - item.setChecked(!item.isChecked()); - } - final OutputDevice finalNewDevice = newDevice; - mHandler.postDelayed(new Runnable() { - @Override - public void run() { - mConfig.setCurrentDevice(finalNewDevice, true); - } - }, 100); - return true; - } return super.onOptionsItemSelected(item); } - private void updateBackgroundColors(int color) { - mEqContainer.setBackgroundColor(color); - mPresetContainer.setBackgroundColor(color); - mKnobContainer.updateKnobHighlights(color); - } - @Override protected void onResume() { + if (DEBUG) Log.i(TAG, "onResume() called with " + ""); super.onResume(); - mResumeDeviceChanged = true; - mConfig.bindService(); - - IntentFilter filter = new IntentFilter(); - filter.addAction(AudioFxService.ACTION_BLUETOOTH_DEVICES_UPDATED); - filter.addAction(AudioFxService.ACTION_DEVICE_OUTPUT_CHANGED); - filter.addAction(AudioManager.ACTION_DIGITAL_AUDIO_DOCK_PLUG); - filter.addAction(AudioManager.ACTION_ANALOG_AUDIO_DOCK_PLUG); - filter.addAction(AudioManager.ACTION_USB_AUDIO_DEVICE_PLUG); - registerReceiver(mDevicesChangedReceiver, filter); - mConfig.addEqStateChangeCallback(ActivityMusic.this); /** * Since the app is 'persisted', the user cannot clear the app's data because the app will * still be in memory after they try and force close it. Let's mimic clearing the data if we * detect this. */ - if (!getSharedPrefsFile("global").exists()) { + if (!getSharedPrefsFile(Constants.AUDIOFX_GLOBAL_FILE).exists()) { Log.w(TAG, "missing global configuration file, resetting state"); - mConfig.removeEqStateChangeCallback(ActivityMusic.this); - mConfig.resetState(); - mConfig.addEqStateChangeCallback(ActivityMusic.this); - - getSharedPreferences("global", 0).edit().commit(); - - mInfiniteAdapter.notifyDataSetChanged(); - mDataAdapter.notifyDataSetChanged(); - mPresetPageIndicator.notifyDataSetChanged(); - mViewPager.invalidate(); - - updateEnabledState(); - jumpToPreset(mConfig.getCurrentPresetIndex()); - } else { - // do all work in onDeviceChanged() callback after service attaches - } - } - - private void jumpToPreset(int index) { - // TODO always animate colors here so they're smooooth - // force instant color jump to preset index - updateBackgroundColors(mConfig.getAssociatedPresetColorHex(index)); - - int diff = index - (mCurrentRealPage % mDataAdapter.getCount()); - // double it, short (e.g. 1 hop) distances sometimes bug out?? - diff += mDataAdapter.getCount(); - int newPage = mCurrentRealPage + diff; - mViewPager.setCurrentItemAbsolute(newPage, false); - } - - @Override - protected void onPause() { - mConfig.unbindService(); - unregisterReceiver(mDevicesChangedReceiver); - mConfig.removeEqStateChangeCallback(this); - super.onPause(); - } - - @Override - public void onBandLevelChange(int band, float dB, boolean fromSystem) { - // call backs we get when bands are changing, check if the user is physically touching them - // and set the preset to "custom" and do proper animations. - if (!fromSystem) { // from user - if (!mConfig.isCustomPreset() // not on custom already - && !mConfig.isUserPreset() // or not on a user preset - && !mConfig.isAnimatingToCustom()) { // and animation hasn't started - if (DEBUG) Log.w(TAG, "met conditions to start an animation to custom trigger"); - // view pager is infinite, so we can't set the item to 0. find NEXT 0 - mConfig.setAnimatingToCustom(true); - - final int newIndex = mConfig.copyToCustom(); - - mInfiniteAdapter.notifyDataSetChanged(); - mDataAdapter.notifyDataSetChanged(); - mViewPager.getAdapter().notifyDataSetChanged(); - // do background transition manually as viewpager can't handle this bg change - final Integer colorFrom = mCurrentBackgroundColor; - final Integer colorTo = mConfig.getAssociatedPresetColorHex(newIndex); - ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo); - colorAnimation.setDuration(500); - colorAnimation.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - int diff = newIndex - (mCurrentRealPage % mDataAdapter.getCount()); - diff += mDataAdapter.getCount(); - int newPage = mCurrentRealPage + diff; - - mAnimatingToRealPageTarget = newPage; - mViewPager.setCurrentItemAbsolute(newPage); - } - - @Override - public void onAnimationEnd(Animator animation) { - mCurrentBackgroundColor = colorTo; - } - - @Override - public void onAnimationCancel(Animator animation) { - } - - @Override - public void onAnimationRepeat(Animator animation) { - } - }); - colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - - @Override - public void onAnimationUpdate(ValueAnimator animator) { - updateBackgroundColors((Integer) animator.getAnimatedValue()); - } - }); - colorAnimation.start(); - + AudioFxFragment frag = (AudioFxFragment) getFragmentManager() + .findFragmentByTag(TAG_AUDIOFX); + if (frag != null) { + frag.onFakeDataClear(); } - mSelectedPositionBands[band] = dB; } - } - @Override - public void onPresetChanged(int newPresetIndex) { - if (!mDeviceChanging) { - mSelectedPositionBands = mConfig.getPresetLevels(newPresetIndex); - } + // action bar controls need to live beyond all fragments + setupDtsActionBar(); } @Override - public void onPresetsChanged() { - mDataAdapter.notifyDataSetChanged(); + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + if (DEBUG) Log.i(TAG, "onConfigurationChanged() called with " + + "newConfig = [" + newConfig + "]"); + mCurrentDeviceToggle = null; } - @Override - public void onDeviceChanged(OutputDevice deviceId, boolean userChange) { - if (!isResumed()) { - return; - } - - invalidateOptionsMenu(); - updateEnabledState(); - - if (mResumeDeviceChanged) { - mBluetoothDevices = mConfig.getBluetoothDevices(); - mResumeDeviceChanged = false; - mEqContainer.resume(); - jumpToPreset(mConfig.getCurrentPresetIndex()); + private void setupDtsActionBar() { + if (!mDts.hasDts()) { return; } + mCurrentDeviceToggle = (CheckBox) findViewById(R.id.device_toggle); - int diff = mConfig.getCurrentPresetIndex() - mSelectedPosition; - final boolean samePage = diff == 0; - diff = mDataAdapter.getCount() + diff; - if (DEBUG) { - Log.d(TAG, "diff: " + diff); - } - - if (DEBUG) Log.d(TAG, "mCurrentRealPage Before: " + mCurrentRealPage); - final int newPage = mCurrentRealPage + diff; - if (DEBUG) Log.d(TAG, "mCurrentRealPage After: " + newPage); - - mSelectedPositionBands = mConfig.getPresetLevels(mSelectedPosition); - final float[] targetBandLevels = mConfig.getPresetLevels(mConfig.getCurrentPresetIndex()); - - if (mDeviceChangeAnimation != null) { - mDeviceChangeAnimation.cancel(); - } - - // do background transition manually as viewpager can't handle this bg change - final Integer colorFrom = mCurrentBackgroundColor; - final Integer colorTo = !mConfig.isCurrentDeviceEnabled() - ? getResources().getColor(R.color.disabled_eq) - : mConfig.getAssociatedPresetColorHex(mConfig.getCurrentPresetIndex()); - mDeviceChangeAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo); - mDeviceChangeAnimation.setDuration(500); - mDeviceChangeAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - - @Override - public void onAnimationUpdate(ValueAnimator animator) { - updateBackgroundColors((Integer) animator.getAnimatedValue()); - - final int N = mConfig.getNumBands(); - for (int i = 0; i < N; i++) { // animate bands - float delta = targetBandLevels[i] - mSelectedPositionBands[i]; - float newBandLevel = mSelectedPositionBands[i] + (delta * animator.getAnimatedFraction()); - //if (DEBUG_VIEWPAGER) Log.d(TAG, i + ", delta: " + delta + ", newBandLevel: " + newBandLevel); - mConfig.setLevel(i, newBandLevel, true); - } - } - }); - mDeviceChangeAnimation.addListener(new Animator.AnimatorListener() { + mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override - public void onAnimationStart(Animator animation) { - mConfig.setChangingPresets(true); - - mDeviceChanging = true; - - if (!samePage) { - mViewPager.setCurrentItemAbsolute(newPage); + public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { + int selectedMode = (Integer) parent.getItemAtPosition(position); + setCurrentMode(selectedMode); + + mDts.setShouldUseDts(mCurrentMode == CURRENT_MODE_DTS); + + if (mCurrentMode == CURRENT_MODE_AUDIOFX) { + mCurrentDeviceToggle.setChecked(mConfig.isCurrentDeviceEnabled()); + + // change to audio fx layout + getFragmentManager() + .beginTransaction() + .replace(R.id.main_fragment, new AudioFxFragment(), TAG_AUDIOFX) + .commit(); + + } else if (mCurrentMode == CURRENT_MODE_DTS) { + // change to dts layout + getFragmentManager() + .beginTransaction() + .replace(R.id.main_fragment, new DTSFragment(), TAG_DTS) + .commit(); } + mCurrentDeviceToggle = null; + setupDtsActionBar(); } @Override - public void onAnimationEnd(Animator animation) { - mCurrentBackgroundColor = colorTo; - mConfig.setChangingPresets(false); - - mSelectedPosition = mConfig.getCurrentPresetIndex(); - mSelectedPositionBands = mConfig.getPresetLevels(mSelectedPosition); + public void onNothingSelected(AdapterView<?> parent) { - mDeviceChanging = false; } + }); + } - @Override - public void onAnimationCancel(Animator animation) { + public void addToggleListener(ActivityStateListener listener) { + mGlobalToggleListeners.add(listener); + } - } + public void removeToggleListener(ActivityStateListener listener) { + mGlobalToggleListeners.remove(listener); + } - @Override - public void onAnimationRepeat(Animator animation) { + public void setGlobalToggleChecked(boolean checked) { + mCurrentDeviceToggle.setOnCheckedChangeListener(null); + mCurrentDeviceToggle.setChecked(checked); + mCurrentDeviceToggle.setOnCheckedChangeListener(mGlobalEnableToggleListener); + } + public void setCurrentMode(int currentMode) { + if (mCurrentMode != currentMode) { + mCurrentMode = currentMode; + for (ActivityStateListener listener : mGlobalToggleListeners) { + listener.onModeChanged(mCurrentMode); } - }); - mDeviceChangeAnimation.start(); + } } - private ViewPager.OnPageChangeListener mViewPageChangeListener = new ViewPager.OnPageChangeListener() { + public int getCurrentMode() { + return mCurrentMode; + } - int mState; - float mLastOffset; - boolean mJustGotToCustomAndSettling; + private static class ModeAdapter extends ArrayAdapter<Integer> { + private LayoutInflater mInflater; + public ModeAdapter(Context context) { + super(context, R.layout.action_bar_spinner_row, android.R.id.title, + new Integer[]{CURRENT_MODE_AUDIOFX, CURRENT_MODE_DTS} + ); + setDropDownViewResource(R.layout.action_bar_spinner_row); + mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + } @Override - public void onPageScrolled(int newPosition, float positionOffset, int positionOffsetPixels) { - if (DEBUG_VIEWPAGER) - Log.i(TAG, "onPageScrolled(" + newPosition + ", " + positionOffset + ", " + positionOffsetPixels + ")"); - Integer colorFrom; - Integer colorTo; - - if (newPosition == mAnimatingToRealPageTarget && mConfig.isAnimatingToCustom()) { - if (DEBUG_VIEWPAGER) Log.w(TAG, "settling var set to true"); - mJustGotToCustomAndSettling = true; - mAnimatingToRealPageTarget = -1; - } - - newPosition = newPosition % mDataAdapter.getCount(); + public View getDropDownView(int position, View convertView, ViewGroup parent) { + View view; + TextView text; + TextView subText; - - if (mConfig.isAnimatingToCustom() || mDeviceChanging) { - if (DEBUG_VIEWPAGER) - Log.i(TAG, "ignoring onPageScrolled because animating to custom or device is changing"); - return; - } - - int toPos; - if (mLastOffset - positionOffset > 0.8) { // this is needed for flings - //Log.e(TAG, "OFFSET DIFF > 0.8! Setting selected position from: " + mSelectedPosition + " to " + newPosition); - mSelectedPosition = newPosition; - // mSelectedPositionBands will be reset by setPreset() below calling back to onPresetChanged() - - mConfig.setPreset(mSelectedPosition); - } - - if (newPosition < mSelectedPosition || (newPosition == mDataAdapter.getCount() - 1) && mSelectedPosition == 0) { - // scrolling left <<<<< - positionOffset = (1 - positionOffset); - //Log.v(TAG, "<<<<<< positionOffset: " + positionOffset + " (last offset: " + mLastOffset + ")"); - toPos = newPosition; - colorTo = mConfig.getAssociatedPresetColorHex(toPos); + if (convertView == null) { + view = mInflater.inflate(R.layout.action_bar_spinner_row, parent, false); } else { - // scrolling right >>>>> - //Log.v(TAG, ">>>>>>> positionOffset: " + positionOffset + " (last offset: " + mLastOffset + ")"); - toPos = newPosition + 1 % mDataAdapter.getCount(); - if (toPos >= mDataAdapter.getCount()) { - toPos = 0; - } - - colorTo = mConfig.getAssociatedPresetColorHex(toPos); - } - - if (mConfig.isCurrentDeviceEnabled()) { - colorFrom = mConfig.getAssociatedPresetColorHex(mSelectedPosition); - updateBackgroundColors((Integer) mArgbEval.evaluate(positionOffset, colorFrom, colorTo)); + view = convertView; } + final Integer mode = getItem(position); - if (mSelectedPositionBands == null) { - mSelectedPositionBands = mConfig.getPresetLevels(mSelectedPosition); - } - // get current bands - float[] finalPresetLevels = mConfig.getPresetLevels(toPos); - - final int N = mConfig.getNumBands(); - for (int i = 0; i < N; i++) { // animate bands - float delta = finalPresetLevels[i] - mSelectedPositionBands[i]; - float newBandLevel = mSelectedPositionBands[i] + (delta * positionOffset); - //if (DEBUG_VIEWPAGER) Log.d(TAG, i + ", delta: " + delta + ", newBandLevel: " + newBandLevel); - mConfig.setLevel(i, newBandLevel, true); - } - mLastOffset = positionOffset; + text = (TextView) view.findViewById(android.R.id.title); + text.setText(R.string.app_name); + subText = (TextView) view.findViewById(android.R.id.summary); + subText.setText(getModeSubTitle(mode)); + subText.setVisibility(subText.length() == 0 ? View.GONE : View.VISIBLE); + return view; } @Override - public void onPageSelected(int position) { - if (DEBUG_VIEWPAGER) Log.i(TAG, "onPageSelected(" + position + ")"); - mCurrentRealPage = position; - position = position % mDataAdapter.getCount(); - if (DEBUG_VIEWPAGER) Log.e(TAG, "onPageSelected(" + position + ")"); - mFakePager.setCurrentItem(position); - mSelectedPosition = position; - if (!mDeviceChanging) { - mSelectedPositionBands = mConfig.getPresetLevels(mSelectedPosition); - mCurrentBackgroundColor = mConfig.getAssociatedPresetColorHex(mSelectedPosition); - } - } - + public View getView(int position, View convertView, ViewGroup parent) { + View view; + TextView text; + TextView subText; - @Override - public void onPageScrollStateChanged(int newState) { - mState = newState; - if (mDeviceChanging) { // avoid setting unwanted presets during custom animations - return; - } - if (DEBUG_VIEWPAGER) - Log.w(TAG, "onPageScrollStateChanged(" + stateToString(newState) + ")"); - - if (mJustGotToCustomAndSettling && mState == ViewPager.SCROLL_STATE_IDLE) { - if (DEBUG_VIEWPAGER) Log.w(TAG, "onPageScrollChanged() setting animating to custom = false"); - mJustGotToCustomAndSettling = false; - mConfig.setChangingPresets(false); - mConfig.setAnimatingToCustom(false); + if (convertView == null) { + view = mInflater.inflate(R.layout.action_bar_spinner, parent, false); } else { - if (mState == ViewPager.SCROLL_STATE_IDLE) { - mConfig.setChangingPresets(false); - mConfig.setPreset(mSelectedPosition); - } else { - // not idle - mConfig.setChangingPresets(true); - } + view = convertView; } - } - private String stateToString(int state) { - switch (state) { - case 0: - return "STATE_IDLE"; - case 1: - return "STATE_DRAGGING"; - case 2: - return "STATE_SETTLING"; - default: - return "STATE_WUT"; - } - } + final Integer mode = getItem(position); + text = (TextView) view.findViewById(android.R.id.title); + text.setText(R.string.app_name); - }; - - private CompoundButton.OnCheckedChangeListener mGlobalEnableToggleListener - = new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(final CompoundButton buttonView, - final boolean isChecked) { - final Integer colorFrom = mCurrentBackgroundColor; - final Integer colorTo = isChecked - ? mConfig.getAssociatedPresetColorHex(mConfig.getCurrentPresetIndex()) - : getResources().getColor(R.color.disabled_eq); - ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo); - colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animator) { - updateBackgroundColors((Integer) animator.getAnimatedValue()); - } - }); - colorAnimation.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - buttonView.setEnabled(false); - } - - @Override - public void onAnimationEnd(Animator animation) { - mCurrentBackgroundColor = colorTo; - mConfig.setCurrentDeviceEnabled(isChecked); - updateEnabledState(); - buttonView.setEnabled(true); - } - - @Override - public void onAnimationCancel(Animator animation) { - - } - - @Override - public void onAnimationRepeat(Animator animation) { - - } - }); - colorAnimation.start(); + subText = (TextView) view.findViewById(android.R.id.summary); + subText.setText(getModeSubTitle(mode)); + subText.setVisibility(subText.length() == 0 ? View.GONE : View.VISIBLE); + return view; } - }; - private CompoundButton.OnCheckedChangeListener mMaxxVolumeListener = new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - mConfig.setMaxxVolumeEnabled(isChecked); + public String getModeSubTitle(int mode) { + switch (mode) { + case CURRENT_MODE_DTS: + return getContext().getResources().getString(R.string.mode_dts); + case CURRENT_MODE_AUDIOFX: + default: + return null; + } } - }; + } } diff --git a/src/com/cyngn/audiofx/activity/MasterConfigControl.java b/src/com/cyngn/audiofx/activity/MasterConfigControl.java index 16fbe94..3cd2715 100644 --- a/src/com/cyngn/audiofx/activity/MasterConfigControl.java +++ b/src/com/cyngn/audiofx/activity/MasterConfigControl.java @@ -15,7 +15,6 @@ import com.cyngn.audiofx.Constants; import com.cyngn.audiofx.R; import com.cyngn.audiofx.eq.EqUtils; import com.cyngn.audiofx.knobs.KnobCommander; -import com.cyngn.audiofx.knobs.RadialKnob; import com.cyngn.audiofx.service.AudioFxService; import com.cyngn.audiofx.service.OutputDevice; @@ -85,8 +84,10 @@ public class MasterConfigControl { public void unbindService() { if (DEBUG) Log.i(TAG, "unbindService() called"); + if (mServiceConnection != null && isServiceBound()) { + mContext.unbindService(mServiceConnection); + } mService = null; - mContext.unbindService(mServiceConnection); } public boolean isServiceBound() { @@ -234,7 +235,7 @@ public class MasterConfigControl { setPreset(mCurrentPreset); mHasMaxxAudio = getGlobalPrefs() - .getBoolean(Constants.DEVICE_AUDIOFX_GLOBAL_HAS_MAXXAUDIO, false); + .getBoolean(Constants.AUDIOFX_GLOBAL_HAS_MAXXAUDIO, false); } public SharedPreferences getGlobalPrefs() { diff --git a/src/com/cyngn/audiofx/fragment/AudioFxBaseFragment.java b/src/com/cyngn/audiofx/fragment/AudioFxBaseFragment.java new file mode 100644 index 0000000..c49a6d6 --- /dev/null +++ b/src/com/cyngn/audiofx/fragment/AudioFxBaseFragment.java @@ -0,0 +1,70 @@ +package com.cyngn.audiofx.fragment; + +import android.animation.Animator; +import android.app.Fragment; +import android.os.Bundle; +import com.cyngn.audiofx.activity.ActivityMusic; +import com.cyngn.audiofx.activity.MasterConfigControl; + +public class AudioFxBaseFragment extends Fragment { + + MasterConfigControl mConfig; + + AudioFxFragment mFrag; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mFrag = (AudioFxFragment) getParentFragment(); + + mConfig = MasterConfigControl.getInstance(getActivity()); + } + + public int getDisabledColor() { + return mFrag.getDisabledColor(); + } + + public int getCurrentBackgroundColor() { + return mFrag.mCurrentBackgroundColor; + } + + public void animateBackgroundColorTo(Integer colorTo, Animator.AnimatorListener listener, + AudioFxFragment.ColorUpdateListener updateListener) { + if (mFrag != null) { + mFrag.animateBackgroundColorTo(colorTo, listener, updateListener); + } + } + + /** + * Call to change the color and propogate it up to the activity, which will call + * {@link #updateFragmentBackgroundColors(int)} + * + * @param color + */ + public void setBackgroundColor(int color, boolean cancelAnimated) { + if (mFrag != null) { + mFrag.updateBackgroundColors(color, cancelAnimated); + } + } + + /** + * For sub class fragments to override and apply the color + * + * @param color the new color to apply to any colored elements + */ + public void updateFragmentBackgroundColors(int color) { + } + + /** + * For sub class fragments to override when they might need to update their enabled states + */ + public void updateEnabledState() { + + } + + public void onFakeDataClear() { + + } + +} diff --git a/src/com/cyngn/audiofx/fragment/AudioFxFragment.java b/src/com/cyngn/audiofx/fragment/AudioFxFragment.java new file mode 100644 index 0000000..7efd0b2 --- /dev/null +++ b/src/com/cyngn/audiofx/fragment/AudioFxFragment.java @@ -0,0 +1,532 @@ +package com.cyngn.audiofx.fragment; + +import android.animation.Animator; +import android.animation.ArgbEvaluator; +import android.animation.ValueAnimator; +import android.annotation.Nullable; +import android.app.ActionBar; +import android.app.Activity; +import android.app.Fragment; +import android.app.FragmentTransaction; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.media.AudioManager; +import android.os.Bundle; +import android.os.Handler; +import android.util.ArrayMap; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.Spinner; +import android.widget.SpinnerAdapter; +import com.cyngn.audiofx.R; +import com.cyngn.audiofx.activity.ActivityMusic; +import com.cyngn.audiofx.activity.MasterConfigControl; +import com.cyngn.audiofx.service.AudioFxService; +import com.cyngn.audiofx.service.OutputDevice; +import com.cyngn.audiofx.widget.InterceptableLinearLayout; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class AudioFxFragment extends Fragment implements MasterConfigControl.EqUpdatedCallback, + ActivityMusic.ActivityStateListener { + + private static final String TAG = AudioFxFragment.class.getSimpleName(); + + public static final String TAG_EQUALIZER = "equalizer"; + public static final String TAG_CONTROLS = "controls"; + + Handler mHandler; + int mCurrentBackgroundColor; + + // whether we are in the middle of animating while switching devices + boolean mDeviceChanging; + + private MenuItem mMenuDevices; + + // current selected index + public int mSelectedPosition = 0; + private Map<Integer, OutputDevice> mBluetoothMap + = new ArrayMap<Integer, OutputDevice>(); + List<OutputDevice> mBluetoothDevices = null; + private boolean mResumeDeviceChanged; + private boolean mUsbDeviceConnected; + + EqualizerFragment mEqFragment; + ControlsFragment mControlFragment; + + InterceptableLinearLayout mInterceptLayout; + private ValueAnimator mColorChangeAnimator; + + private int mDisabledColor; + + MasterConfigControl mConfig; + + private int mCurrentMode; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mConfig = MasterConfigControl.getInstance(getActivity()); + mHandler = new Handler(); + mDisabledColor = getResources().getColor(R.color.disabled_eq); + + setHasOptionsMenu(true); + ((ActivityMusic) getActivity()).addToggleListener(this); + + mCurrentMode = ((ActivityMusic) getActivity()).getCurrentMode(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + ((ActivityMusic) getActivity()).removeToggleListener(this); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + mCurrentMode = ((ActivityMusic) getActivity()).getCurrentMode(); + } + + private boolean showFragments() { + boolean createNewFrags = true; + final FragmentTransaction fragmentTransaction = getChildFragmentManager() + .beginTransaction(); + if (mEqFragment == null) { + mEqFragment = (EqualizerFragment) getChildFragmentManager() + .findFragmentByTag(TAG_EQUALIZER); + + if (mEqFragment != null) { + fragmentTransaction.show(mEqFragment); + } + } + if (mControlFragment == null) { + mControlFragment = (ControlsFragment) getChildFragmentManager() + .findFragmentByTag(TAG_CONTROLS); + if (mControlFragment != null) { + fragmentTransaction.show(mControlFragment); + } + } + + if (mEqFragment != null && mControlFragment != null) { + createNewFrags = false; + } + + fragmentTransaction.commit(); + + return createNewFrags; + } + + @Override + public void onResume() { + super.onResume(); + mResumeDeviceChanged = true; + mConfig.bindService(); + + IntentFilter filter = new IntentFilter(); + filter.addAction(AudioFxService.ACTION_BLUETOOTH_DEVICES_UPDATED); + filter.addAction(AudioFxService.ACTION_DEVICE_OUTPUT_CHANGED); + filter.addAction(AudioManager.ACTION_DIGITAL_AUDIO_DOCK_PLUG); + filter.addAction(AudioManager.ACTION_ANALOG_AUDIO_DOCK_PLUG); + filter.addAction(AudioManager.ACTION_USB_AUDIO_DEVICE_PLUG); + getActivity().registerReceiver(mDevicesChangedReceiver, filter); + mConfig.addEqStateChangeCallback(this); + } + + @Override + public void onPause() { + super.onPause(); + getActivity().unregisterReceiver(mDevicesChangedReceiver); + mConfig.removeEqStateChangeCallback(this); + mConfig.unbindService(); + } + + public void onFakeDataClear() { + int colorTo = !mConfig.isCurrentDeviceEnabled() + ? mDisabledColor + : mConfig.getAssociatedPresetColorHex(mConfig.getCurrentPresetIndex()); + animateBackgroundColorTo(colorTo, null, null); + + updateEnabledState(); + + if (mEqFragment != null) { + mEqFragment.onFakeDataClear(); + } + if (mControlFragment != null) { + mControlFragment.onFakeDataClear(); + } + } + + public void updateBackgroundColors(Integer color, boolean cancelAnimated) { + if (cancelAnimated && mColorChangeAnimator != null) { + mColorChangeAnimator.cancel(); + } + mCurrentBackgroundColor = color; + if (mEqFragment != null) { + mEqFragment.updateFragmentBackgroundColors(color); + } + if (mControlFragment != null) { + mControlFragment.updateFragmentBackgroundColors(color); + } + } + + public void updateEnabledState() { + boolean currentDeviceEnabled = mConfig.isCurrentDeviceEnabled(); + if (mEqFragment != null) { + mEqFragment.updateEnabledState(); + } + if (mControlFragment != null) { + mControlFragment.updateEnabledState(); + } + + ((ActivityMusic) getActivity()).setGlobalToggleChecked(currentDeviceEnabled); + + if (mInterceptLayout != null) { + mInterceptLayout.setInterception(!currentDeviceEnabled); + } + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + super.onCreateOptionsMenu(menu, inflater); + inflater.inflate(R.menu.devices, menu); + mMenuDevices = menu.findItem(R.id.devices); + } + + @Override + public void onPrepareOptionsMenu(Menu menu) { + super.onPrepareOptionsMenu(menu); + final OutputDevice currentDevice = mConfig.getCurrentDevice(); + updateActionBarDeviceIcon(); + + final MenuItem usb = menu.findItem(R.id.device_usb); + usb.setVisible(mUsbDeviceConnected); + + // select proper device + if (mConfig.isServiceBound()) { + MenuItem selectedItem = null; + + if (mBluetoothDevices != null) { + // remove previous bluetooth entries + for (Integer id : mBluetoothMap.keySet()) { + mMenuDevices.getSubMenu().removeItem(id); + } + mBluetoothMap.clear(); + + for (int i = 0; i < mBluetoothDevices.size(); i++) { + int viewId = View.generateViewId(); + mBluetoothMap.put(viewId, mBluetoothDevices.get(i)); + MenuItem item = mMenuDevices.getSubMenu().add(R.id.device_group, viewId, i, + mBluetoothDevices.get(i).getDisplayName()); + if (mBluetoothDevices.get(i).equals(currentDevice)) { + selectedItem = item; + } + item.setIcon(R.drawable.ic_action_dsp_icons_bluetoof); + } + } + mMenuDevices.getSubMenu().setGroupCheckable(R.id.device_group, true, true); + + switch (currentDevice.getDeviceType()) { + case OutputDevice.DEVICE_SPEAKER: + selectedItem = mMenuDevices.getSubMenu().findItem(R.id.device_speaker); + break; + case OutputDevice.DEVICE_USB: + selectedItem = mMenuDevices.getSubMenu().findItem(R.id.device_usb); + break; + case OutputDevice.DEVICE_HEADSET: + selectedItem = mMenuDevices.getSubMenu().findItem(R.id.device_headset); + break; + } + if (selectedItem != null) { + selectedItem.setChecked(true); + } + } + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + OutputDevice newDevice = null; + + switch (item.getItemId()) { + case R.id.device_headset: + newDevice = new OutputDevice(OutputDevice.DEVICE_HEADSET); + break; + + case R.id.device_usb: + newDevice = new OutputDevice(OutputDevice.DEVICE_USB); + break; + + case R.id.device_speaker: + newDevice = new OutputDevice(OutputDevice.DEVICE_SPEAKER); + break; + + default: + newDevice = mBluetoothMap.get(item.getItemId()); + break; + + } + if (newDevice != null) { + mDeviceChanging = true; + if (item.isCheckable()) { + item.setChecked(!item.isChecked()); + } + final OutputDevice finalNewDevice = newDevice; + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + mConfig.setCurrentDevice(finalNewDevice, true); + } + }, 100); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + if (container == null) { + Log.w(TAG, "container is null."); + // no longer displaying this fragment + return null; + } + + View root = inflater.inflate(mConfig.hasMaxxAudio() + ? R.layout.fragment_audiofx_maxxaudio + : R.layout.fragment_audiofx, container, false); + + final FragmentTransaction fragmentTransaction = getChildFragmentManager() + .beginTransaction(); + + boolean createNewFrags = true; + + if (savedInstanceState != null) { + createNewFrags = showFragments(); + } + + if (createNewFrags) { + fragmentTransaction.add(R.id.equalizer, mEqFragment = new EqualizerFragment(), TAG_EQUALIZER); + fragmentTransaction.add(R.id.controls, mControlFragment = new ControlsFragment(), TAG_CONTROLS); + } + + fragmentTransaction.commit(); + + + return root; + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + + // view was destroyed + final FragmentTransaction fragmentTransaction = getChildFragmentManager() + .beginTransaction(); + + if (mEqFragment != null) { + fragmentTransaction.remove(mEqFragment); + mEqFragment = null; + } + if (mControlFragment != null) { + fragmentTransaction.remove(mControlFragment); + mControlFragment = null; + } + + fragmentTransaction.commit(); + + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + mInterceptLayout = (InterceptableLinearLayout) view.findViewById(R.id.interceptable_layout); + + mCurrentBackgroundColor = !mConfig.isCurrentDeviceEnabled() + ? mDisabledColor + : mConfig.getAssociatedPresetColorHex(mConfig.getCurrentPresetIndex()); + updateBackgroundColors(mCurrentBackgroundColor, false); + } + + public void animateBackgroundColorTo(int colorTo, Animator.AnimatorListener listener, + ColorUpdateListener updateListener) { + if (mColorChangeAnimator != null) { + mColorChangeAnimator.cancel(); + mColorChangeAnimator = null; + } + mColorChangeAnimator = ValueAnimator.ofObject(new ArgbEvaluator(), + mCurrentBackgroundColor, colorTo); + mColorChangeAnimator.setDuration(500); + mColorChangeAnimator.addUpdateListener(updateListener != null ? updateListener + : mColorUpdateListener); + if (listener != null) { + mColorChangeAnimator.addListener(listener); + } + mColorChangeAnimator.start(); + } + + private BroadcastReceiver mDevicesChangedReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (AudioFxService.ACTION_BLUETOOTH_DEVICES_UPDATED.equals(intent.getAction())) { + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + mBluetoothDevices = mConfig.getBluetoothDevices(); + getActivity().invalidateOptionsMenu(); + } + }); + } else if (AudioFxService.ACTION_DEVICE_OUTPUT_CHANGED.equals(intent.getAction())) { + getActivity().invalidateOptionsMenu(); + } else if (AudioManager.ACTION_DIGITAL_AUDIO_DOCK_PLUG.equals(intent.getAction()) + || AudioManager.ACTION_ANALOG_AUDIO_DOCK_PLUG.equals(intent.getAction()) + || AudioManager.ACTION_USB_AUDIO_DEVICE_PLUG.equals(intent.getAction())) { + boolean connected = intent.getIntExtra("state", 0) == 1; + mUsbDeviceConnected = connected; + getActivity().invalidateOptionsMenu(); + } + } + }; + + @Override + public void onBandLevelChange(int band, float dB, boolean fromSystem) { + + } + + @Override + public void onPresetChanged(int newPresetIndex) { + + } + + @Override + public void onPresetsChanged() { + + } + + @Override + public void onDeviceChanged(OutputDevice deviceId, boolean userChange) { + if (!isResumed()) { + ((ActivityMusic) getActivity()).setGlobalToggleChecked(mConfig.isCurrentDeviceEnabled()); + return; + } + + getActivity().invalidateOptionsMenu(); + updateEnabledState(); + + if (mResumeDeviceChanged) { + mBluetoothDevices = mConfig.getBluetoothDevices(); + if (mEqFragment != null) { + mEqFragment.mEqContainer.resume(); + mEqFragment.jumpToPreset(mConfig.getCurrentPresetIndex()); + } + mResumeDeviceChanged = false; + } + } + + private void updateActionBarDeviceIcon() { + if (mMenuDevices != null) { + int icon = 0; + switch (mConfig.getCurrentDevice().getDeviceType()) { + case OutputDevice.DEVICE_HEADSET: + icon = R.drawable.ic_action_dsp_icons_headphones; + break; + + case OutputDevice.DEVICE_SPEAKER: + icon = R.drawable.ic_action_dsp_icons_speaker; + break; + + case OutputDevice.DEVICE_USB: + icon = R.drawable.ic_action_dsp_icons_usb; + break; + + case OutputDevice.DEVICE_BLUETOOTH: + icon = R.drawable.ic_action_dsp_icons_bluetoof; + break; + + case OutputDevice.DEVICE_WIRELESS: + // TODO add wireless back + break; + + } + mMenuDevices.setIcon(icon); + } + } + + private ValueAnimator.AnimatorUpdateListener mColorUpdateListener + = new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + updateBackgroundColors((Integer) animation.getAnimatedValue(), false); + } + }; + + @Override + public void onGlobalToggleChanged(final CompoundButton buttonView, final boolean checked) { + if (mCurrentMode != ActivityMusic.CURRENT_MODE_AUDIOFX) { + return; + } + final Animator.AnimatorListener animatorListener = new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + buttonView.setEnabled(false); + mConfig.setCurrentDeviceEnabled(checked); + } + + @Override + public void onAnimationEnd(Animator animation) { + updateEnabledState(); + buttonView.setEnabled(true); + } + + @Override + public void onAnimationCancel(Animator animation) { + buttonView.setEnabled(true); + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + }; + final Integer colorTo = checked + ? mConfig.getAssociatedPresetColorHex(mConfig.getCurrentPresetIndex()) + : mDisabledColor; + animateBackgroundColorTo(colorTo, + animatorListener, null); + } + + @Override + public void onModeChanged(int mode) { + mCurrentMode = mode; + } + + public static class ColorUpdateListener implements ValueAnimator.AnimatorUpdateListener { + + final AudioFxBaseFragment mFrag; + + public ColorUpdateListener(AudioFxBaseFragment frag) { + this.mFrag = frag; + } + + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mFrag.setBackgroundColor((Integer) animation.getAnimatedValue(), false); + } + } + + public int getDisabledColor() { + return mDisabledColor; + } +} diff --git a/src/com/cyngn/audiofx/fragment/ControlsFragment.java b/src/com/cyngn/audiofx/fragment/ControlsFragment.java new file mode 100644 index 0000000..0d39e2a --- /dev/null +++ b/src/com/cyngn/audiofx/fragment/ControlsFragment.java @@ -0,0 +1,99 @@ +package com.cyngn.audiofx.fragment; + +import android.annotation.Nullable; +import android.os.Bundle; +import android.os.Handler; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import com.cyngn.audiofx.R; +import com.cyngn.audiofx.knobs.KnobCommander; +import com.cyngn.audiofx.knobs.KnobContainer; +import com.cyngn.audiofx.service.OutputDevice; + +public class ControlsFragment extends AudioFxBaseFragment { + + private static final String TAG = ControlsFragment.class.getSimpleName(); + private static final boolean DEBUG = false; + + KnobCommander mKnobCommander; + Handler mHandler; + KnobContainer mKnobContainer; + CheckBox mMaxxVolumeSwitch; + + private CompoundButton.OnCheckedChangeListener mMaxxVolumeListener + = new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + mConfig.setMaxxVolumeEnabled(isChecked); + } + }; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mHandler = new Handler(); + mKnobCommander = KnobCommander.getInstance(getActivity()); + + } + + @Override + public void onPause() { + super.onPause(); + } + + @Override + public void onResume() { + super.onResume(); + } + + @Override + public void updateFragmentBackgroundColors(int color) { + if (mKnobContainer != null) { + mKnobContainer.updateKnobHighlights(color); + } + } + + + public void updateEnabledState() { + final OutputDevice device = mConfig.getCurrentDevice(); + boolean currentDeviceEnabled = mConfig.isCurrentDeviceEnabled(); + + if (DEBUG) { + Log.d(TAG, "updating with current device: " + device); + } + + if (mMaxxVolumeSwitch != null) { + mMaxxVolumeSwitch.setChecked(mConfig.getMaxxVolumeEnabled()); + mMaxxVolumeSwitch.setEnabled(currentDeviceEnabled); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, + Bundle savedInstanceState) { + View root = inflater.inflate(mConfig.hasMaxxAudio() ? R.layout.controls_maxx_audio + : R.layout.controls_generic, container, false); + return root; + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + mKnobContainer = (KnobContainer) view.findViewById(R.id.knob_container); + mMaxxVolumeSwitch = (CheckBox) view.findViewById(R.id.maxx_volume_switch); + + updateFragmentBackgroundColors(getCurrentBackgroundColor()); + + if (mMaxxVolumeSwitch != null) { + mMaxxVolumeSwitch.setOnCheckedChangeListener(mMaxxVolumeListener); + } + } + + +} diff --git a/src/com/cyngn/audiofx/fragment/DTSFragment.java b/src/com/cyngn/audiofx/fragment/DTSFragment.java new file mode 100644 index 0000000..ac82036 --- /dev/null +++ b/src/com/cyngn/audiofx/fragment/DTSFragment.java @@ -0,0 +1,118 @@ +package com.cyngn.audiofx.fragment; + +import android.annotation.Nullable; +import android.app.Activity; +import android.app.Fragment; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CompoundButton; +import android.widget.ImageView; +import com.cyngn.audiofx.R; +import com.cyngn.audiofx.activity.ActivityMusic; +import com.cyngn.audiofx.service.AudioFxService; +import com.cyngn.audiofx.service.DtsControl; + +public class DTSFragment extends Fragment implements ActivityMusic.ActivityStateListener { + + private static final String TAG = DTSFragment.class.getSimpleName(); + private static final boolean DEBUG = false; + + private ImageView mLogo; + private boolean mGlobalToggleEnabled; + private DtsControl mDts; + private int mMode; + + @Override + public void onCreate(Bundle savedInstanceState) { + if (DEBUG) Log.i(TAG, "onCreate() called with " + + "savedInstanceState = [" + savedInstanceState + "]"); + super.onCreate(savedInstanceState); + mDts = new DtsControl(getActivity()); + ((ActivityMusic)getActivity()).addToggleListener(this); + + mMode = ((ActivityMusic) getActivity()).getCurrentMode(); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + mMode = ((ActivityMusic) getActivity()).getCurrentMode(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + ((ActivityMusic)getActivity()).removeToggleListener(this); + } + + @Override + public void onResume() { + super.onResume(); + + final boolean dtsEnabledByUser = mDts.getUserEnabled(); + ((ActivityMusic)getActivity()) + .setGlobalToggleChecked(mGlobalToggleEnabled = dtsEnabledByUser); + updateLogo(); + + final boolean dtsEnabled = mDts.isDtsEnabled(); + if (DEBUG) Log.i(TAG, "onResume() dtsEnabledByUser=" + dtsEnabledByUser + + ", dtsEnabled=" + dtsEnabled); + } + + @Override + public void onPause() { + if (DEBUG) Log.i(TAG, "onPause() called with " + ""); + super.onPause(); + } + + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, + Bundle savedInstanceState) { + View root = inflater.inflate(R.layout.fragment_dts, container, false); + + return root; + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + mLogo = (ImageView) view.findViewById(R.id.logo); + updateLogo(); + } + + private void updateLogo() { + if (mLogo != null) { + mLogo.setImageResource(mGlobalToggleEnabled + ? R.drawable.logo_dts_fc : R.drawable.logo_dts_1c); + mLogo.animate().cancel(); + mLogo.animate().alpha(mGlobalToggleEnabled ? 1 : .6f); + } + } + + @Override + public void onGlobalToggleChanged(CompoundButton compoundButton, boolean checked) { + if (DEBUG) Log.i(TAG, "onGlobalToggleChanged() called with " + + "checked = [" + checked + "]"); + if (mMode != ActivityMusic.CURRENT_MODE_DTS) { + Log.w(TAG, "not visible, ignoring toggle change"); + // not interested in this update + return; + } + + mGlobalToggleEnabled = checked; + updateLogo(); + + mDts.setUserEnabled(checked); + AudioFxService.updateService(getActivity()); + } + + @Override + public void onModeChanged(int mode) { + mMode = mode; + } + +} diff --git a/src/com/cyngn/audiofx/fragment/EqualizerFragment.java b/src/com/cyngn/audiofx/fragment/EqualizerFragment.java new file mode 100644 index 0000000..1cf5d13 --- /dev/null +++ b/src/com/cyngn/audiofx/fragment/EqualizerFragment.java @@ -0,0 +1,536 @@ +package com.cyngn.audiofx.fragment; + +import android.animation.Animator; +import android.animation.ArgbEvaluator; +import android.animation.ValueAnimator; +import android.annotation.Nullable; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.os.Handler; +import android.support.v4.view.ViewPager; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.EditText; +import android.widget.TextView; +import com.cyngn.audiofx.R; +import com.cyngn.audiofx.activity.ActivityMusic; +import com.cyngn.audiofx.activity.MasterConfigControl; +import com.cyngn.audiofx.eq.EqContainerView; +import com.cyngn.audiofx.preset.InfinitePagerAdapter; +import com.cyngn.audiofx.preset.InfiniteViewPager; +import com.cyngn.audiofx.preset.PresetPagerAdapter; +import com.cyngn.audiofx.service.OutputDevice; +import com.viewpagerindicator.CirclePageIndicator; +import com.viewpagerindicator.PageIndicator; + +public class EqualizerFragment extends AudioFxBaseFragment + implements MasterConfigControl.EqUpdatedCallback { + private static final String TAG = ControlsFragment.class.getSimpleName(); + private static final boolean DEBUG = false; + private static final boolean DEBUG_VIEWPAGER = false; + + private final ArgbEvaluator mArgbEval = new ArgbEvaluator(); + + Handler mHandler; + public EqContainerView mEqContainer; + ViewGroup mPresetContainer; + InfiniteViewPager mViewPager; + PageIndicator mPresetPageIndicator; + PresetPagerAdapter mDataAdapter; + InfinitePagerAdapter mInfiniteAdapter; + int mCurrentRealPage; + + // whether we are in the middle of animating while switching devices + boolean mDeviceChanging; + + private ViewPager mFakePager; + + private int mAnimatingToRealPageTarget = -1; + + /* + * this array can hold on to arrays which store preset levels, + * so modifying values in here should only be done with extreme care + */ + private float[] mSelectedPositionBands; + + // current selected index + public int mSelectedPosition = 0; + + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mHandler = new Handler(); + + mSelectedPositionBands = mConfig.getPersistedPresetLevels(mConfig.getCurrentPresetIndex()); + + } + + @Override + public void onPause() { + super.onPause(); + mConfig.removeEqStateChangeCallback(this); + } + + @Override + public void onResume() { + super.onResume(); + mConfig.addEqStateChangeCallback(this); + + final Integer colorTo = !mConfig.isCurrentDeviceEnabled() + ? getDisabledColor() + : mConfig.getAssociatedPresetColorHex(mConfig.getCurrentPresetIndex()); + animateBackgroundColorTo(colorTo, null, null); + } + + @Override + public void onFakeDataClear() { + super.onFakeDataClear(); + mInfiniteAdapter.notifyDataSetChanged(); + mDataAdapter.notifyDataSetChanged(); + mPresetPageIndicator.notifyDataSetChanged(); + mViewPager.invalidate(); + + jumpToPreset(mConfig.getCurrentPresetIndex()); + } + + @Override + public void updateFragmentBackgroundColors(int color) { + if (mEqContainer != null) { + mEqContainer.setBackgroundColor(color); + } + if (mPresetContainer != null) { + mPresetContainer.setBackgroundColor(color); + } + } + + + public void jumpToPreset(int index) { + int diff = index - (mCurrentRealPage % mDataAdapter.getCount()); + // double it, short (e.g. 1 hop) distances sometimes bug out?? + diff += mDataAdapter.getCount(); + int newPage = mCurrentRealPage + diff; + mViewPager.setCurrentItemAbsolute(newPage, false); + } + + private void removeCurrentCustomPreset(boolean showWarning) { + if (showWarning) { + MasterConfigControl.Preset p = mConfig.getCurrentPreset(); + new AlertDialog.Builder(getActivity()) + .setMessage(String.format(getString( + R.string.remove_custom_preset_warning_message), p.mName)) + .setNegativeButton(android.R.string.no, null) + .setPositiveButton(android.R.string.yes, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + removeCurrentCustomPreset(false); + } + }) + .create() + .show(); + return; + } + + final int currentIndexBeforeRemove = mConfig.getCurrentPresetIndex(); + if (mConfig.removePreset(currentIndexBeforeRemove)) { + mInfiniteAdapter.notifyDataSetChanged(); + mDataAdapter.notifyDataSetChanged(); + mPresetPageIndicator.notifyDataSetChanged(); + + jumpToPreset(mSelectedPosition - 1); + } + } + + private void openRenameDialog() { + AlertDialog.Builder renameDialog = new AlertDialog.Builder(getActivity()); + renameDialog.setTitle(R.string.rename); + final EditText newName = new EditText(getActivity()); + newName.setText(mConfig.getCurrentPreset().mName); + renameDialog.setView(newName); + renameDialog.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + + public void onClick(DialogInterface d, int which) { + mConfig.renameCurrentPreset(newName.getText().toString()); + final TextView viewWithTag = (TextView) mViewPager + .findViewWithTag(mConfig.getCurrentPreset()); + viewWithTag.setText(newName.getText().toString()); + mDataAdapter.notifyDataSetChanged(); + mViewPager.invalidate(); + } + }); + + renameDialog.setNegativeButton(android.R.string.cancel, + new DialogInterface.OnClickListener() { + + public void onClick(DialogInterface d, int which) { + } + }); + + renameDialog.show(); + } + + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, + Bundle savedInstanceState) { + View root = inflater.inflate(R.layout.equalizer, container, false); + return root; + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + mEqContainer = (EqContainerView) view.findViewById(R.id.eq_container); + mPresetContainer = (ViewGroup) view.findViewById(R.id.preset_container); + mViewPager = (InfiniteViewPager) view.findViewById(R.id.pager); + CirclePageIndicator indicator = (CirclePageIndicator) view.findViewById(R.id.indicator); + mPresetPageIndicator = indicator; + + final PresetPagerAdapter adapter = new PresetPagerAdapter(getActivity()); + + mInfiniteAdapter = new InfinitePagerAdapter(adapter); + mDataAdapter = adapter; + + mViewPager.setAdapter(mInfiniteAdapter); + mFakePager = (ViewPager) view.findViewById(R.id.fake_pager); + + mViewPager.setOnPageChangeListener(mViewPageChangeListener); + + mViewPager.setCurrentItem(mSelectedPosition = mConfig.getCurrentPresetIndex()); + + mFakePager.setAdapter(adapter); + mEqContainer.findViewById(R.id.save).setOnClickListener( + new View.OnClickListener() { + @Override + public void onClick(View v) { + + final int newidx = mConfig.addPresetFromCustom(); + mInfiniteAdapter.notifyDataSetChanged(); + mDataAdapter.notifyDataSetChanged(); + mPresetPageIndicator.notifyDataSetChanged(); + + jumpToPreset(newidx); + } + } + ); + mEqContainer.findViewById(R.id.rename).setOnClickListener( + new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mConfig.isUserPreset()) { + openRenameDialog(); + } + } + } + ); + mEqContainer.findViewById(R.id.remove).setOnClickListener( + new View.OnClickListener() { + @Override + public void onClick(View v) { + removeCurrentCustomPreset(true); + } + } + ); + + indicator.setViewPager(mFakePager, mConfig.getCurrentPresetIndex()); + indicator.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + // eat all events + return true; + } + }); + indicator.setSnap(true); + + updateFragmentBackgroundColors(getCurrentBackgroundColor()); + + mCurrentRealPage = mInfiniteAdapter.getRealCount() * 100; + + } + + + @Override + public void onBandLevelChange(int band, float dB, boolean fromSystem) { + // call backs we get when bands are changing, check if the user is physically touching them + // and set the preset to "custom" and do proper animations. + if (!fromSystem) { // from user + if (!mConfig.isCustomPreset() // not on custom already + && !mConfig.isUserPreset() // or not on a user preset + && !mConfig.isAnimatingToCustom()) { // and animation hasn't started + if (DEBUG) Log.w(TAG, "met conditions to start an animation to custom trigger"); + // view pager is infinite, so we can't set the item to 0. find NEXT 0 + mConfig.setAnimatingToCustom(true); + + final int newIndex = mConfig.copyToCustom(); + + mInfiniteAdapter.notifyDataSetChanged(); + mDataAdapter.notifyDataSetChanged(); + mViewPager.getAdapter().notifyDataSetChanged(); + // do background transition manually as viewpager can't handle this bg change + final Integer colorTo = !mConfig.isCurrentDeviceEnabled() + ? getDisabledColor() + : mConfig.getAssociatedPresetColorHex(newIndex); + final Animator.AnimatorListener listener = new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + int diff = newIndex - (mCurrentRealPage % mDataAdapter.getCount()); + diff += mDataAdapter.getCount(); + int newPage = mCurrentRealPage + diff; + + mAnimatingToRealPageTarget = newPage; + mViewPager.setCurrentItemAbsolute(newPage); + } + + @Override + public void onAnimationEnd(Animator animation) { + } + + @Override + public void onAnimationCancel(Animator animation) { + } + + @Override + public void onAnimationRepeat(Animator animation) { + } + }; + animateBackgroundColorTo(colorTo, listener, null); + + } + mSelectedPositionBands[band] = dB; + } + } + + @Override + public void onPresetChanged(int newPresetIndex) { + mDataAdapter.notifyDataSetChanged(); + if (!mDeviceChanging) { + mSelectedPositionBands = mConfig.getPresetLevels(newPresetIndex); + } + } + + @Override + public void onPresetsChanged() { + mDataAdapter.notifyDataSetChanged(); + } + + @Override + public void onDeviceChanged(OutputDevice deviceId, boolean userChange) { + int diff = mConfig.getCurrentPresetIndex() - mSelectedPosition; + final boolean samePage = diff == 0; + diff = mDataAdapter.getCount() + diff; + if (DEBUG) { + Log.d(TAG, "diff: " + diff); + } + + if (DEBUG) Log.d(TAG, "mCurrentRealPage Before: " + mCurrentRealPage); + final int newPage = mCurrentRealPage + diff; + if (DEBUG) Log.d(TAG, "mCurrentRealPage After: " + newPage); + + mSelectedPositionBands = mConfig.getPresetLevels(mSelectedPosition); + final float[] targetBandLevels = mConfig.getPresetLevels(mConfig.getCurrentPresetIndex()); + + // do background transition manually as viewpager can't handle this bg change + final Integer colorTo = !mConfig.isCurrentDeviceEnabled() + ? getDisabledColor() + : mConfig.getAssociatedPresetColorHex(mConfig.getCurrentPresetIndex()); + + final Animator.AnimatorListener animatorListener = new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + mConfig.setChangingPresets(true); + + mDeviceChanging = true; + + if (!samePage) { + mViewPager.setCurrentItemAbsolute(newPage); + } + } + + @Override + public void onAnimationEnd(Animator animation) { +// setBackgroundColor(colorTo); + mConfig.setChangingPresets(false); + + mSelectedPosition = mConfig.getCurrentPresetIndex(); + mSelectedPositionBands = mConfig.getPresetLevels(mSelectedPosition); + + mDeviceChanging = false; + } + + @Override + public void onAnimationCancel(Animator animation) { + + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + }; + + final AudioFxFragment.ColorUpdateListener animatorUpdateListener + = new AudioFxFragment.ColorUpdateListener(this) { + @Override + public void onAnimationUpdate(ValueAnimator animator) { + super.onAnimationUpdate(animator); + + final int N = mConfig.getNumBands(); + for (int i = 0; i < N; i++) { // animate bands + float delta = targetBandLevels[i] - mSelectedPositionBands[i]; + float newBandLevel = mSelectedPositionBands[i] + + (delta * animator.getAnimatedFraction()); + //if (DEBUG_VIEWPAGER) Log.d(TAG, i + ", delta: " + delta + ", newBandLevel: " + newBandLevel); + mConfig.setLevel(i, newBandLevel, true); + } + } + }; + + animateBackgroundColorTo(colorTo, animatorListener, animatorUpdateListener); + } + + + private ViewPager.OnPageChangeListener mViewPageChangeListener = new ViewPager.OnPageChangeListener() { + + int mState; + float mLastOffset; + boolean mJustGotToCustomAndSettling; + + @Override + public void onPageScrolled(int newPosition, float positionOffset, int positionOffsetPixels) { + if (DEBUG_VIEWPAGER) + Log.i(TAG, "onPageScrolled(" + newPosition + ", " + positionOffset + ", " + + positionOffsetPixels + ")"); + Integer colorFrom; + Integer colorTo; + + if (newPosition == mAnimatingToRealPageTarget && mConfig.isAnimatingToCustom()) { + if (DEBUG_VIEWPAGER) Log.w(TAG, "settling var set to true"); + mJustGotToCustomAndSettling = true; + mAnimatingToRealPageTarget = -1; + } + + newPosition = newPosition % mDataAdapter.getCount(); + + + if (mConfig.isAnimatingToCustom() || mDeviceChanging) { + if (DEBUG_VIEWPAGER) + Log.i(TAG, "ignoring onPageScrolled because animating to custom or device is changing"); + return; + } + + int toPos; + if (mLastOffset - positionOffset > 0.8) { // this is needed for flings + //Log.e(TAG, "OFFSET DIFF > 0.8! Setting selected position from: " + mSelectedPosition + " to " + newPosition); + mSelectedPosition = newPosition; + // mSelectedPositionBands will be reset by setPreset() below calling back to onPresetChanged() + + mConfig.setPreset(mSelectedPosition); + } + + if (newPosition < mSelectedPosition || (newPosition == mDataAdapter.getCount() - 1) + && mSelectedPosition == 0) { + // scrolling left <<<<< + positionOffset = (1 - positionOffset); + //Log.v(TAG, "<<<<<< positionOffset: " + positionOffset + " (last offset: " + mLastOffset + ")"); + toPos = newPosition; + colorTo = mConfig.getAssociatedPresetColorHex(toPos); + } else { + // scrolling right >>>>> + //Log.v(TAG, ">>>>>>> positionOffset: " + positionOffset + " (last offset: " + mLastOffset + ")"); + toPos = newPosition + 1 % mDataAdapter.getCount(); + if (toPos >= mDataAdapter.getCount()) { + toPos = 0; + } + + colorTo = mConfig.getAssociatedPresetColorHex(toPos); + } + + if (!mDeviceChanging && mConfig.isCurrentDeviceEnabled()) { + colorFrom = mConfig.getAssociatedPresetColorHex(mSelectedPosition); + setBackgroundColor((Integer) mArgbEval.evaluate(positionOffset, colorFrom, colorTo), + true); + } + + if (mSelectedPositionBands == null) { + mSelectedPositionBands = mConfig.getPresetLevels(mSelectedPosition); + } + // get current bands + float[] finalPresetLevels = mConfig.getPresetLevels(toPos); + + final int N = mConfig.getNumBands(); + for (int i = 0; i < N; i++) { // animate bands + float delta = finalPresetLevels[i] - mSelectedPositionBands[i]; + float newBandLevel = mSelectedPositionBands[i] + (delta * positionOffset); + //if (DEBUG_VIEWPAGER) Log.d(TAG, i + ", delta: " + delta + ", newBandLevel: " + newBandLevel); + mConfig.setLevel(i, newBandLevel, true); + } + mLastOffset = positionOffset; + + } + + @Override + public void onPageSelected(int position) { + if (DEBUG_VIEWPAGER) Log.i(TAG, "onPageSelected(" + position + ")"); + mCurrentRealPage = position; + position = position % mDataAdapter.getCount(); + if (DEBUG_VIEWPAGER) Log.e(TAG, "onPageSelected(" + position + ")"); + mFakePager.setCurrentItem(position); + mSelectedPosition = position; + if (!mDeviceChanging) { + mSelectedPositionBands = mConfig.getPresetLevels(mSelectedPosition); + } + } + + + @Override + public void onPageScrollStateChanged(int newState) { + mState = newState; + if (mDeviceChanging) { // avoid setting unwanted presets during custom animations + return; + } + if (DEBUG_VIEWPAGER) + Log.w(TAG, "onPageScrollStateChanged(" + stateToString(newState) + ")"); + + if (mJustGotToCustomAndSettling && mState == ViewPager.SCROLL_STATE_IDLE) { + if (DEBUG_VIEWPAGER) + Log.w(TAG, "onPageScrollChanged() setting animating to custom = false"); + mJustGotToCustomAndSettling = false; + mConfig.setChangingPresets(false); + mConfig.setAnimatingToCustom(false); + } else { + if (mState == ViewPager.SCROLL_STATE_IDLE) { + animateBackgroundColorTo(!mConfig.isCurrentDeviceEnabled() + ? getDisabledColor() + : mConfig.getAssociatedPresetColorHex(mSelectedPosition), + null, null); + + mConfig.setChangingPresets(false); + mConfig.setPreset(mSelectedPosition); + } else { + // not idle + mConfig.setChangingPresets(true); + } + } + } + + private String stateToString(int state) { + switch (state) { + case 0: + return "STATE_IDLE"; + case 1: + return "STATE_DRAGGING"; + case 2: + return "STATE_SETTLING"; + default: + return "STATE_WUT"; + } + } + + }; +} diff --git a/src/com/cyngn/audiofx/knobs/KnobCommander.java b/src/com/cyngn/audiofx/knobs/KnobCommander.java index 3f7d013..4422aee 100644 --- a/src/com/cyngn/audiofx/knobs/KnobCommander.java +++ b/src/com/cyngn/audiofx/knobs/KnobCommander.java @@ -61,7 +61,7 @@ public class KnobCommander { } public boolean hasBassBoost() { - return mConfig.getGlobalPrefs().getBoolean(Constants.DEVICE_AUDIOFX_GLOBAL_HAS_BASSBOOST, false); + return mConfig.getGlobalPrefs().getBoolean(Constants.AUDIOFX_GLOBAL_HAS_BASSBOOST, false); } public boolean hasTreble() { @@ -69,7 +69,7 @@ public class KnobCommander { } public boolean hasVirtualizer() { - return mConfig.getGlobalPrefs().getBoolean(Constants.DEVICE_AUDIOFX_GLOBAL_HAS_VIRTUALIZER, false); + return mConfig.getGlobalPrefs().getBoolean(Constants.AUDIOFX_GLOBAL_HAS_VIRTUALIZER, false); } public boolean isBassEffectEnabled() { diff --git a/src/com/cyngn/audiofx/service/AudioFxService.java b/src/com/cyngn/audiofx/service/AudioFxService.java index bcfdab5..e7342ec 100644 --- a/src/com/cyngn/audiofx/service/AudioFxService.java +++ b/src/com/cyngn/audiofx/service/AudioFxService.java @@ -16,7 +16,6 @@ package com.cyngn.audiofx.service; import android.app.Service; -import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; @@ -35,8 +34,6 @@ import android.media.audiofx.BassBoost; import android.media.audiofx.Equalizer; import android.media.audiofx.PresetReverb; import android.media.audiofx.Virtualizer; -import android.net.NetworkInfo; -import android.net.wifi.p2p.WifiP2pManager; import android.os.Binder; import android.os.Handler; import android.os.HandlerThread; @@ -52,8 +49,8 @@ import com.cyngn.audiofx.eq.EqUtils; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -116,6 +113,8 @@ public class AudioFxService extends Service { } } + private DtsControl mDts; + /** * Receive new broadcast intents for adding DSP to session */ @@ -202,13 +201,26 @@ public class AudioFxService extends Service { case MSG_UPDATE_DSP: + if (mDts.hasDts()) { + if (mDts.shouldUseDts()) { + if (DEBUG) Log.d(TAG, "forcing DTS effects"); + disableAllEffects(); + + mDts.setEnabled(mDts.getUserEnabled()); + return; + } else { + if (DEBUG) Log.d(TAG, "not using DTS"); + mDts.setEnabled(false); + } + } + final String mode = getCurrentDevicePreferenceName(); if (DEBUG) Log.i(TAG, "Updating to configuration: " + mode); synchronized (mAudioSessions) { // immediately update most recent session if (mMostRecentSessionId > 0) { if (DEBUG) Log.d(TAG, "updating DSP for most recent session id (" - + mMostRecentSessionId + "!"); + + mMostRecentSessionId + ")!"); updateDsp(getSharedPreferences(mode, 0), mAudioSessions.get(mMostRecentSessionId) ); @@ -247,6 +259,7 @@ public class AudioFxService extends Service { handlerThread.start(); mHandler = new AudioServiceHandler(handlerThread.getLooper()); + mDts = new DtsControl(this); try { saveDefaults(); } catch (Exception e) { @@ -341,7 +354,7 @@ public class AudioFxService extends Service { mMaxxAudioEffects = new MaxxAudioEffects(1000, sessionId); } catch (Exception e) { mMaxxAudioEffects = null; - Log.w(TAG, "Unable to initialize MaxxAudio library!"); + if (DEBUG) Log.w(TAG, "Unable to initialize MaxxAudio library!"); } mEqualizer = new Equalizer(1000, sessionId); @@ -700,6 +713,10 @@ public class AudioFxService extends Service { } private void updateDsp(SharedPreferences prefs, EffectSet session) { + if (DEBUG) { + Log.i(TAG, "updateDsp() called with " + "prefs = [" + prefs + + "], session = [" + session + "]"); + } if (session == null) { return; } @@ -774,6 +791,20 @@ public class AudioFxService extends Service { } } + private void disableAllEffects() { + final Collection<EffectSet> values = mAudioSessions.values(); + for (EffectSet effectSet : values) { + effectSet.enableBassBoost(false); + effectSet.enableEqualizer(false); + effectSet.enableVirtualizer(false); + effectSet.enableReverb(false); + if (effectSet.hasMaxxAudio()) { + effectSet.mMaxxAudioEffects.setMaxxTrebleEnabled(false); + effectSet.mMaxxAudioEffects.setMaxxVolumeEnabled(false); + } + } + } + /** * This method sets some sane defaults for presets, device defaults, etc * <p/> @@ -828,9 +859,9 @@ public class AudioFxService extends Service { editor.putString("equalizer.preset_names", presetNames.toString()).apply(); - editor.putBoolean(DEVICE_AUDIOFX_GLOBAL_HAS_VIRTUALIZER, temp.hasVirtualizer()).apply(); - editor.putBoolean(DEVICE_AUDIOFX_GLOBAL_HAS_BASSBOOST, temp.hasBassBoost()).apply(); - editor.putBoolean(DEVICE_AUDIOFX_GLOBAL_HAS_MAXXAUDIO, temp.hasMaxxAudio()).apply(); + editor.putBoolean(AUDIOFX_GLOBAL_HAS_VIRTUALIZER, temp.hasVirtualizer()).apply(); + editor.putBoolean(AUDIOFX_GLOBAL_HAS_BASSBOOST, temp.hasBassBoost()).apply(); + editor.putBoolean(AUDIOFX_GLOBAL_HAS_MAXXAUDIO, temp.hasMaxxAudio()).apply(); temp.release(); applyDefaults(false); @@ -849,4 +880,10 @@ public class AudioFxService extends Service { spk.edit().putBoolean(DEVICE_AUDIOFX_MAXXVOLUME_ENABLE, true).apply(); } } + + public static void updateService(Context context) { + final Intent updateServiceIntent = new Intent(AudioFxService.ACTION_UPDATE_PREFERENCES); +// updateServiceIntent.setClass(context, AudioFxService.class); + context.sendBroadcast(updateServiceIntent); + } } |