diff options
-rw-r--r-- | DeviceSettings/res/layout/preference_dialog_incall_audio_tuning.xml | 139 | ||||
-rw-r--r-- | DeviceSettings/res/layout/preference_dialog_output_audio_tuning.xml | 87 | ||||
-rw-r--r-- | DeviceSettings/res/values/config.xml | 13 | ||||
-rw-r--r-- | DeviceSettings/res/values/strings.xml | 18 | ||||
-rw-r--r-- | DeviceSettings/res/xml/audio_preferences.xml (renamed from DeviceSettings/res/xml/dock_preferences.xml) | 21 | ||||
-rw-r--r-- | DeviceSettings/src/com/cyanogenmod/settings/device/AudioFragmentActivity.java (renamed from DeviceSettings/src/com/cyanogenmod/settings/device/DockFragmentActivity.java) | 35 | ||||
-rw-r--r-- | DeviceSettings/src/com/cyanogenmod/settings/device/AudioOut.java | 269 | ||||
-rw-r--r-- | DeviceSettings/src/com/cyanogenmod/settings/device/DeviceSettings.java | 6 | ||||
-rw-r--r-- | DeviceSettings/src/com/cyanogenmod/settings/device/IncallAudio.java | 347 | ||||
-rw-r--r-- | DeviceSettings/src/com/cyanogenmod/settings/device/Startup.java | 14 |
10 files changed, 933 insertions, 16 deletions
diff --git a/DeviceSettings/res/layout/preference_dialog_incall_audio_tuning.xml b/DeviceSettings/res/layout/preference_dialog_incall_audio_tuning.xml new file mode 100644 index 0000000..633f729 --- /dev/null +++ b/DeviceSettings/res/layout/preference_dialog_incall_audio_tuning.xml @@ -0,0 +1,139 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2013 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. +--> +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <RelativeLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center_horizontal" + android:paddingBottom="20dip"> + + <TextView android:id="@+id/incall_earpiece_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/incall_earpiece_audio_title_head" + android:paddingTop="10dip" + android:paddingLeft="20dip" + android:paddingRight="20dip" /> + <TextView android:id="@+id/earpiece_value" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentRight="true" + android:layout_toRightOf="@id/incall_earpiece_text" + android:paddingTop="10dip" + android:paddingLeft="20dip" + android:paddingRight="20dip" /> + + <SeekBar android:id="@+id/earpiece_seekbar" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@id/incall_earpiece_text" + android:paddingTop="2dip" + android:paddingLeft="20dip" + android:paddingRight="20dip" /> + + <TextView android:id="@+id/incall_headphone_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/incall_headphone_audio_title_head" + android:layout_below="@id/earpiece_seekbar" + android:paddingTop="10dip" + android:paddingLeft="20dip" + android:paddingRight="20dip" /> + <TextView android:id="@+id/headphone_value" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentRight="true" + android:layout_toRightOf="@id/incall_headphone_text" + android:layout_below="@id/earpiece_seekbar" + android:paddingTop="10dip" + android:paddingLeft="20dip" + android:paddingRight="20dip" /> + + <SeekBar android:id="@+id/headphone_seekbar" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@id/incall_headphone_text" + android:paddingTop="2dip" + android:paddingLeft="20dip" + android:paddingRight="20dip" /> + + <TextView android:id="@+id/incall_speaker_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/incall_speaker_audio_title_head" + android:layout_below="@id/headphone_seekbar" + android:paddingTop="10dip" + android:paddingLeft="20dip" + android:paddingRight="20dip" /> + <TextView android:id="@+id/speaker_value" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentRight="true" + android:layout_toRightOf="@id/incall_speaker_text" + android:layout_below="@id/headphone_seekbar" + android:paddingTop="10dip" + android:paddingLeft="20dip" + android:paddingRight="20dip" /> + + <SeekBar android:id="@+id/speaker_seekbar" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@id/incall_speaker_text" + android:paddingTop="2dip" + android:paddingLeft="20dip" + android:paddingRight="20dip" /> + + <TextView android:id="@+id/incall_bt_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/incall_bt_audio_title_head" + android:layout_below="@id/speaker_seekbar" + android:paddingTop="10dip" + android:paddingLeft="20dip" + android:paddingRight="20dip" /> + <TextView android:id="@+id/bt_value" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentRight="true" + android:layout_toRightOf="@id/incall_bt_text" + android:layout_below="@id/speaker_seekbar" + android:paddingTop="10dip" + android:paddingLeft="20dip" + android:paddingRight="20dip" /> + + <SeekBar android:id="@+id/bt_seekbar" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@id/incall_bt_text" + android:paddingTop="2dip" + android:paddingLeft="20dip" + android:paddingRight="20dip" /> + + <TextView + android:id="@+id/incall_textWarn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@id/bt_seekbar" + android:paddingTop="8dip" + android:gravity="center" + android:text="@string/incall_warning" + android:textSize="15dp" /> + + </RelativeLayout> +</ScrollView> diff --git a/DeviceSettings/res/layout/preference_dialog_output_audio_tuning.xml b/DeviceSettings/res/layout/preference_dialog_output_audio_tuning.xml new file mode 100644 index 0000000..c6d5018 --- /dev/null +++ b/DeviceSettings/res/layout/preference_dialog_output_audio_tuning.xml @@ -0,0 +1,87 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2013 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. +--> +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <RelativeLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center_horizontal" + android:paddingBottom="20dip"> + + <TextView android:id="@+id/audioout_headphone_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/audioout_headphone_audio_title_head" + android:paddingTop="10dip" + android:paddingLeft="20dip" + android:paddingRight="20dip" /> + <TextView android:id="@+id/audioout_headphone_value" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentRight="true" + android:layout_toRightOf="@id/audioout_headphone_text" + android:paddingTop="10dip" + android:paddingLeft="20dip" + android:paddingRight="20dip" /> + + <SeekBar android:id="@+id/audioout_headphone_seekbar" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@id/audioout_headphone_text" + android:paddingTop="2dip" + android:paddingLeft="20dip" + android:paddingRight="20dip" /> + + <TextView android:id="@+id/audioout_speaker_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/audioout_speaker_audio_title_head" + android:layout_below="@id/audioout_headphone_seekbar" + android:paddingTop="10dip" + android:paddingLeft="20dip" + android:paddingRight="20dip" /> + <TextView android:id="@+id/audioout_speaker_value" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentRight="true" + android:layout_toRightOf="@id/audioout_speaker_text" + android:layout_below="@id/audioout_headphone_seekbar" + android:paddingTop="10dip" + android:paddingLeft="20dip" + android:paddingRight="20dip" /> + + <SeekBar android:id="@+id/audioout_speaker_seekbar" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@id/audioout_speaker_text" + android:paddingTop="2dip" + android:paddingLeft="20dip" + android:paddingRight="20dip" /> + + <TextView + android:id="@+id/audioout_textWarn" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_below="@id/audioout_speaker_seekbar" + android:paddingTop="8dip" + android:gravity="center" + android:text="@string/audioout_warning" + android:textSize="15dp" /> + + </RelativeLayout> +</ScrollView> diff --git a/DeviceSettings/res/values/config.xml b/DeviceSettings/res/values/config.xml index b289bd9..df9a427 100644 --- a/DeviceSettings/res/values/config.xml +++ b/DeviceSettings/res/values/config.xml @@ -30,4 +30,17 @@ <string name="spen_sysfs_file">"/sys/class/sec/sec_epen"</string> <string name="spen_powersaving_sysfs_file">"/sys/class/sec/sec_epen/epen_saving_mode"</string> + <!-- Audio Tuning --> + <bool name="has_incall_audio_tuning">false</bool> + <bool name="has_output_audio_tuning">false</bool> + + <string name="incall_max_value">10</string> + <string name="incall_warning_threshold">9</string> + <string name="incall_default_value">5</string> + <string name="incall_min_value">1</string> + <string name="audioout_max_value">63</string> + <string name="audioout_warning_threshold">60</string> + <string name="audioout_default_value">0</string> + <string name="audioout_min_value">0</string> + </resources> diff --git a/DeviceSettings/res/values/strings.xml b/DeviceSettings/res/values/strings.xml index e3cb7e8..0f75ae3 100644 --- a/DeviceSettings/res/values/strings.xml +++ b/DeviceSettings/res/values/strings.xml @@ -61,11 +61,21 @@ <string name="hspa_title_head">HSPA</string> <string name="hspa_summary_head">Enable HSDPA/HSUPA</string> - <!-- Dock Preference --> - <string name="category_dock_title">Dock</string> - <string name="dockaudio_subcat_title">Audio</string> - <string name="use_dock_audio_title_head">Use Dock USB Audio</string> + <!-- Audio Preference --> + <string name="category_audio_title">Audio</string> + <string name="dockaudio_subcat_title">Dock audio</string> + <string name="use_dock_audio_title_head">Use USB Dock Audio</string> <string name="use_dock_audio_summary_head">Use the passive audio out on the dock</string> + <string name="incallaudio_subcat_title">In-call audio volumes</string> + <string name="incall_earpiece_audio_title_head">Earpiece</string> + <string name="incall_headphone_audio_title_head">Headphone</string> + <string name="incall_speaker_audio_title_head">Speaker</string> + <string name="incall_bt_audio_title_head">BT</string> + <string name="incall_warning">Values higher than %1$d are not recommended</string> + <string name="audioout_subcat_title">Streaming audio volumes</string> + <string name="audioout_headphone_audio_title_head">Headphone</string> + <string name="audioout_speaker_audio_title_head">Speaker</string> + <string name="audioout_warning">Values higher than %1$d are not recommended</string> <!-- S-Pen --> <string name="spen_subcat_title">S-Pen</string> diff --git a/DeviceSettings/res/xml/dock_preferences.xml b/DeviceSettings/res/xml/audio_preferences.xml index 62c962c..e6f762e 100644 --- a/DeviceSettings/res/xml/dock_preferences.xml +++ b/DeviceSettings/res/xml/audio_preferences.xml @@ -23,4 +23,25 @@ android:summary="@string/use_dock_audio_summary_head" /> </PreferenceCategory> + + <PreferenceCategory + android:title="@string/incallaudio_subcat_title"> + + <com.cyanogenmod.settings.device.IncallAudio + android:key="incall_tuning" + android:title="@string/incallaudio_subcat_title" + android:dialogTitle="@string/incallaudio_subcat_title" /> + + </PreferenceCategory> + + <PreferenceCategory + android:title="@string/audioout_subcat_title"> + + <com.cyanogenmod.settings.device.AudioOut + android:key="audioout_tuning" + android:title="@string/audioout_subcat_title" + android:dialogTitle="@string/audioout_subcat_title" /> + + </PreferenceCategory> + </PreferenceScreen> diff --git a/DeviceSettings/src/com/cyanogenmod/settings/device/DockFragmentActivity.java b/DeviceSettings/src/com/cyanogenmod/settings/device/AudioFragmentActivity.java index 0e555e4..807a3b0 100644 --- a/DeviceSettings/src/com/cyanogenmod/settings/device/DockFragmentActivity.java +++ b/DeviceSettings/src/com/cyanogenmod/settings/device/AudioFragmentActivity.java @@ -19,6 +19,7 @@ package com.cyanogenmod.settings.device; import android.app.ActivityManagerNative; import android.content.Context; import android.content.Intent; +import android.content.res.Resources; import android.content.SharedPreferences; import android.os.Bundle; import android.os.UserHandle; @@ -32,17 +33,45 @@ import android.util.Log; import com.cyanogenmod.settings.device.R; -public class DockFragmentActivity extends PreferenceFragment { +public class AudioFragmentActivity extends PreferenceFragment { private static final String PREF_ENABLED = "1"; - private static final String TAG = "DeviceSettings_Dock"; + private static final String TAG = "DeviceSettings_Audio"; + public static final String KEY_INCALL_TUNING = "incall_tuning"; + public static final String KEY_AUDIOOUT_TUNING = "audioout_tuning"; + + private static boolean sIncallTuning; + private static boolean sAudioOutTuning; + private IncallAudio mIncallTuning; + private AudioOut mAudioOutTuning; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - addPreferencesFromResource(R.xml.dock_preferences); + addPreferencesFromResource(R.xml.audio_preferences); PreferenceScreen prefSet = getPreferenceScreen(); + + Resources res = getResources(); + sIncallTuning = res.getBoolean(R.bool.has_incall_audio_tuning); + sAudioOutTuning = res.getBoolean(R.bool.has_output_audio_tuning); + + if(sIncallTuning){ + mIncallTuning = (IncallAudio) findPreference(KEY_INCALL_TUNING); + if(mIncallTuning.isSupported("earpiece") || mIncallTuning.isSupported("headphone") || + mIncallTuning.isSupported("speaker") || mIncallTuning.isSupported("bt")) + mIncallTuning.setEnabled(true); + else + mIncallTuning.setEnabled(false); + } + + if(sAudioOutTuning){ + mAudioOutTuning = (AudioOut) findPreference(KEY_AUDIOOUT_TUNING); + if(mAudioOutTuning.isSupported("headphone") || mAudioOutTuning.isSupported("speaker")) + mAudioOutTuning.setEnabled(true); + else + mAudioOutTuning.setEnabled(false); + } } @Override diff --git a/DeviceSettings/src/com/cyanogenmod/settings/device/AudioOut.java b/DeviceSettings/src/com/cyanogenmod/settings/device/AudioOut.java new file mode 100644 index 0000000..e3b5b9f --- /dev/null +++ b/DeviceSettings/src/com/cyanogenmod/settings/device/AudioOut.java @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2013 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. + */ + +package com.cyanogenmod.settings.device; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.graphics.Color; +import android.graphics.LightingColorFilter; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; +import android.os.Bundle; +import android.os.Vibrator; +import android.preference.DialogPreference; +import android.preference.PreferenceManager; +import android.util.AttributeSet; +import android.util.Log; +import android.view.View; +import android.widget.SeekBar; +import android.widget.TextView; +import android.widget.Button; + +import java.lang.Math; +import java.text.DecimalFormat; + +/** + * Special preference type that allows configuration of audio out volume on some smdk4412 + * Devices + */ +public class AudioOut extends DialogPreference implements SeekBar.OnSeekBarChangeListener { + private static final String TAG = "DeviceSettings_AudioOut"; + + private static String AUDIOOUT_HEADPHONE_FILE = "/data/local/audio/out_headphone"; + private static String AUDIOOUT_SPEAKER_FILE = "/data/local/audio/out_speaker"; + private static int MAX_VALUE; + private static int WARNING_THRESHOLD; + private static int DEFAULT_VALUE; + private static int MIN_VALUE; + + private SeekBar mHeadphoneSeekBar; + private SeekBar mSpeakerSeekBar; + private TextView mHeadphoneValue; + private TextView mSpeakerValue; + private TextView mWarning; + + private String mHeadphoneOgValue; + private String mSpeakerOgValue; + private int mHeadphoneOgPercent; + private int mSpeakerOgPercent; + + private Drawable mHeadphoneProgressDrawable; + private Drawable mSpeakerProgressDrawable; + private Drawable mHeadphoneProgressThumb; + private Drawable mSpeakerProgressThumb; + private LightingColorFilter mRedFilter; + + private enum Device { + headphone, + speaker + } + + public AudioOut(Context context, AttributeSet attrs) { + super(context, attrs); + + MAX_VALUE = Integer.valueOf(context.getResources().getString(R.string.audioout_max_value)); + WARNING_THRESHOLD = Integer.valueOf(context.getResources().getString(R.string.audioout_warning_threshold)); + DEFAULT_VALUE = Integer.valueOf(context.getResources().getString(R.string.audioout_default_value)); + MIN_VALUE = Integer.valueOf(context.getResources().getString(R.string.audioout_min_value)); + + setDialogLayoutResource(R.layout.preference_dialog_output_audio_tuning); + } + + @Override + protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { + builder.setNeutralButton(R.string.defaults_button, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + } + }); + } + + @Override + protected void onBindDialogView(View view) { + super.onBindDialogView(view); + + mHeadphoneSeekBar = (SeekBar) view.findViewById(R.id.audioout_headphone_seekbar); + mHeadphoneValue = (TextView) view.findViewById(R.id.audioout_headphone_value); + mSpeakerSeekBar = (SeekBar) view.findViewById(R.id.audioout_speaker_seekbar); + mSpeakerValue = (TextView) view.findViewById(R.id.audioout_speaker_value); + mWarning = (TextView) view.findViewById(R.id.audioout_textWarn); + + String strWarnMsg = getContext().getResources().getString(R.string.audioout_warning, volumeToPercent(WARNING_THRESHOLD)); + mWarning.setText(strWarnMsg); + + Drawable progressDrawableHeadphone = mHeadphoneSeekBar.getProgressDrawable(); + if (progressDrawableHeadphone instanceof LayerDrawable) { + LayerDrawable ldHeadphone = (LayerDrawable) progressDrawableHeadphone; + mHeadphoneProgressDrawable = ldHeadphone.findDrawableByLayerId(android.R.id.progress); + } + Drawable progressDrawableSpeaker = mSpeakerSeekBar.getProgressDrawable(); + if (progressDrawableSpeaker instanceof LayerDrawable) { + LayerDrawable ldSpeaker = (LayerDrawable) progressDrawableSpeaker; + mSpeakerProgressDrawable = ldSpeaker.findDrawableByLayerId(android.R.id.progress); + } + + mHeadphoneProgressThumb = mHeadphoneSeekBar.getThumb(); + mSpeakerProgressThumb = mSpeakerSeekBar.getThumb(); + + mRedFilter = new LightingColorFilter(Color.BLACK, + getContext().getResources().getColor(android.R.color.holo_red_light)); + + mHeadphoneOgValue = Utils.readOneLine(AUDIOOUT_HEADPHONE_FILE); + mHeadphoneOgPercent = volumeToPercent(Integer.parseInt(mHeadphoneOgValue)); + + mHeadphoneSeekBar.setOnSeekBarChangeListener(this); + mHeadphoneSeekBar.setProgress(Integer.valueOf(mHeadphoneOgPercent)); + + mSpeakerOgValue = Utils.readOneLine(AUDIOOUT_SPEAKER_FILE); + mSpeakerOgPercent = volumeToPercent(Integer.parseInt(mSpeakerOgValue)); + + mSpeakerSeekBar.setOnSeekBarChangeListener(this); + mSpeakerSeekBar.setProgress(Integer.valueOf(mSpeakerOgPercent)); + } + + @Override + protected void showDialog(Bundle state) { + super.showDialog(state); + + // can't use onPrepareDialogBuilder for this as we want the dialog + // to be kept open on click + AlertDialog d = (AlertDialog) getDialog(); + Button defaultsButton = d.getButton(DialogInterface.BUTTON_NEUTRAL); + defaultsButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mHeadphoneSeekBar.setProgress(volumeToPercent(DEFAULT_VALUE)); + mSpeakerSeekBar.setProgress(volumeToPercent(DEFAULT_VALUE)); + } + }); + } + + @Override + protected void onDialogClosed(boolean positiveResult) { + super.onDialogClosed(positiveResult); + int volumeHeadphone, volumeSpeaker; + + if (positiveResult) { + Editor editor = getEditor(); + + volumeHeadphone = percentToVolume(mHeadphoneSeekBar.getProgress()); + editor.putString(AUDIOOUT_HEADPHONE_FILE, String.valueOf(volumeHeadphone)); + volumeSpeaker = percentToVolume(mSpeakerSeekBar.getProgress()); + editor.putString(AUDIOOUT_SPEAKER_FILE, String.valueOf(volumeSpeaker)); + editor.commit(); + } else { + Utils.writeValue(AUDIOOUT_HEADPHONE_FILE, String.valueOf(mHeadphoneOgPercent)); + Utils.writeValue(AUDIOOUT_SPEAKER_FILE, String.valueOf(mSpeakerOgPercent)); + } + } + + public static void restore(Context context) { + SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context); + + if (isSupported("headphone")) + Utils.writeValue(AUDIOOUT_HEADPHONE_FILE, sharedPrefs.getString(AUDIOOUT_HEADPHONE_FILE, "50")); + if (isSupported("speaker")) + Utils.writeValue(AUDIOOUT_SPEAKER_FILE, sharedPrefs.getString(AUDIOOUT_SPEAKER_FILE, "50")); + } + + public static boolean isSupported(String output) { + String FILE = null; + Device outputDevice = Device.valueOf(output); + + switch(outputDevice) { + case headphone: + FILE = AUDIOOUT_HEADPHONE_FILE; + case speaker: + FILE = AUDIOOUT_SPEAKER_FILE; + } + return Utils.fileExists(FILE); + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + boolean shouldWarn = progress >= volumeToPercent(WARNING_THRESHOLD); + int stepSize = 1; + progress = Math.round(progress/stepSize)*stepSize; + + if(seekBar == mHeadphoneSeekBar){ + if (mHeadphoneProgressDrawable != null) { + mHeadphoneProgressDrawable.setColorFilter(shouldWarn ? mRedFilter : null); + } + if (mHeadphoneProgressThumb != null) { + mHeadphoneProgressThumb.setColorFilter(shouldWarn ? mRedFilter : null); + } + mHeadphoneSeekBar.setProgress(progress); + Utils.writeValue(AUDIOOUT_HEADPHONE_FILE, String.valueOf(percentToVolume(progress))); + mHeadphoneValue.setText(String.format("%d%%", progress)); + }else if(seekBar == mSpeakerSeekBar){ + if (mSpeakerProgressDrawable != null) { + mSpeakerProgressDrawable.setColorFilter(shouldWarn ? mRedFilter : null); + } + if (mSpeakerProgressThumb != null) { + mSpeakerProgressThumb.setColorFilter(shouldWarn ? mRedFilter : null); + } + mSpeakerSeekBar.setProgress(progress); + Utils.writeValue(AUDIOOUT_SPEAKER_FILE, String.valueOf(percentToVolume(progress))); + mSpeakerValue.setText(String.format("%d%%", progress)); + } + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + // Do nothing + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + //Vibrator vib = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE); + //vib.vibrate(200); + } + + /** + * Convert volume to percent + */ + public static int volumeToPercent(int volume) { + double maxValue = MAX_VALUE; + double minValue = MIN_VALUE; + + double percent = (volume - minValue) * (100 / (maxValue - minValue)); + + if (percent > 100) + percent = 100; + else if (percent < 0) + percent = 0; + + return (int) percent; + } + + /** + * Convert percent to volume + */ + public static int percentToVolume(int percent) { + int volume = Math.round((((MAX_VALUE - MIN_VALUE) * percent) / 100) + MIN_VALUE); + + if (volume > MAX_VALUE) + volume = MAX_VALUE; + else if (volume < MIN_VALUE) + volume = MIN_VALUE; + + return volume; + } +} diff --git a/DeviceSettings/src/com/cyanogenmod/settings/device/DeviceSettings.java b/DeviceSettings/src/com/cyanogenmod/settings/device/DeviceSettings.java index 6bf4b0b..7c1072f 100644 --- a/DeviceSettings/src/com/cyanogenmod/settings/device/DeviceSettings.java +++ b/DeviceSettings/src/com/cyanogenmod/settings/device/DeviceSettings.java @@ -46,7 +46,7 @@ public class DeviceSettings extends FragmentActivity { public static final String KEY_HSPA = "hspa"; public static final String KEY_USE_DOCK_AUDIO = "dock_audio"; public static final String KEY_CATEGORY_SPEN = "category_spen"; - public static final String KEY_SPEN_POWER_SAVING_MODE = "spen_power_saving"; + public static final String KEY_SPEN_POWER_SAVING_MODE = "spen_power_saving"; ViewPager mViewPager; TabsAdapter mTabsAdapter; @@ -72,8 +72,8 @@ public class DeviceSettings extends FragmentActivity { ScreenFragmentActivity.class, null); mTabsAdapter.addTab(bar.newTab().setText(R.string.category_haptic_title), HapticFragmentActivity.class, null); - mTabsAdapter.addTab(bar.newTab().setText(R.string.category_dock_title), - DockFragmentActivity.class, null); + mTabsAdapter.addTab(bar.newTab().setText(R.string.category_audio_title), + AudioFragmentActivity.class, null); if (savedInstanceState != null) { bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0)); diff --git a/DeviceSettings/src/com/cyanogenmod/settings/device/IncallAudio.java b/DeviceSettings/src/com/cyanogenmod/settings/device/IncallAudio.java new file mode 100644 index 0000000..44fa1c3 --- /dev/null +++ b/DeviceSettings/src/com/cyanogenmod/settings/device/IncallAudio.java @@ -0,0 +1,347 @@ +/* + * Copyright (C) 2013 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. + */ + +package com.cyanogenmod.settings.device; + +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.graphics.Color; +import android.graphics.LightingColorFilter; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; +import android.os.Bundle; +import android.os.Vibrator; +import android.preference.DialogPreference; +import android.preference.PreferenceManager; +import android.util.AttributeSet; +import android.util.Log; +import android.view.View; +import android.widget.SeekBar; +import android.widget.TextView; +import android.widget.Button; + +import java.lang.Math; +import java.text.DecimalFormat; + +/** + * Special preference type that allows configuration of incall volume on some smdk4412 + * Devices + */ +public class IncallAudio extends DialogPreference implements SeekBar.OnSeekBarChangeListener { + private static final String TAG = "DeviceSettings_IncallAudio"; + + private static String INCALL_EARPIECE_FILE = "/data/local/audio/incall_earpiece"; + private static String INCALL_HEADPHONE_FILE = "/data/local/audio/incall_headphone"; + private static String INCALL_SPEAKER_FILE = "/data/local/audio/incall_speaker"; + private static String INCALL_BT_FILE = "/data/local/audio/incall_bt"; + private static int MAX_VALUE; + private static int WARNING_THRESHOLD; + private static int DEFAULT_VALUE; + private static int MIN_VALUE; + + private SeekBar mEarpieceSeekBar; + private SeekBar mHeadphoneSeekBar; + private SeekBar mSpeakerSeekBar; + private SeekBar mBtSeekBar; + private TextView mEarpieceValue; + private TextView mHeadphoneValue; + private TextView mSpeakerValue; + private TextView mBtValue; + private TextView mWarning; + + private String mEarpieceOgValue; + private String mHeadphoneOgValue; + private String mSpeakerOgValue; + private String mBtOgValue; + private int mEarpieceOgPercent; + private int mHeadphoneOgPercent; + private int mSpeakerOgPercent; + private int mBtOgPercent; + + private Drawable mEarpieceProgressDrawable; + private Drawable mHeadphoneProgressDrawable; + private Drawable mSpeakerProgressDrawable; + private Drawable mBtProgressDrawable; + private Drawable mEarpieceProgressThumb; + private Drawable mHeadphoneProgressThumb; + private Drawable mSpeakerProgressThumb; + private Drawable mBtProgressThumb; + private LightingColorFilter mRedFilter; + + private enum Device { + earpiece, + headphone, + speaker, + bt + } + + public IncallAudio(Context context, AttributeSet attrs) { + super(context, attrs); + + MAX_VALUE = Integer.valueOf(context.getResources().getString(R.string.incall_max_value)); + WARNING_THRESHOLD = Integer.valueOf(context.getResources().getString(R.string.incall_warning_threshold)); + DEFAULT_VALUE = Integer.valueOf(context.getResources().getString(R.string.incall_default_value)); + MIN_VALUE = Integer.valueOf(context.getResources().getString(R.string.incall_min_value)); + + setDialogLayoutResource(R.layout.preference_dialog_incall_audio_tuning); + } + + @Override + protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { + builder.setNeutralButton(R.string.defaults_button, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + } + }); + } + + @Override + protected void onBindDialogView(View view) { + super.onBindDialogView(view); + + mEarpieceSeekBar = (SeekBar) view.findViewById(R.id.earpiece_seekbar); + mEarpieceValue = (TextView) view.findViewById(R.id.earpiece_value); + mHeadphoneSeekBar = (SeekBar) view.findViewById(R.id.headphone_seekbar); + mHeadphoneValue = (TextView) view.findViewById(R.id.headphone_value); + mSpeakerSeekBar = (SeekBar) view.findViewById(R.id.speaker_seekbar); + mSpeakerValue = (TextView) view.findViewById(R.id.speaker_value); + mBtSeekBar = (SeekBar) view.findViewById(R.id.bt_seekbar); + mBtValue = (TextView) view.findViewById(R.id.bt_value); + mWarning = (TextView) view.findViewById(R.id.incall_textWarn); + + String strWarnMsg = getContext().getResources().getString(R.string.incall_warning, volumeToPercent(WARNING_THRESHOLD)); + mWarning.setText(strWarnMsg); + + Drawable progressDrawableEarpiece = mEarpieceSeekBar.getProgressDrawable(); + if (progressDrawableEarpiece instanceof LayerDrawable) { + LayerDrawable ldEarpiece = (LayerDrawable) progressDrawableEarpiece; + mEarpieceProgressDrawable = ldEarpiece.findDrawableByLayerId(android.R.id.progress); + } + Drawable progressDrawableHeadphone = mHeadphoneSeekBar.getProgressDrawable(); + if (progressDrawableHeadphone instanceof LayerDrawable) { + LayerDrawable ldHeadphone = (LayerDrawable) progressDrawableHeadphone; + mHeadphoneProgressDrawable = ldHeadphone.findDrawableByLayerId(android.R.id.progress); + } + Drawable progressDrawableSpeaker = mSpeakerSeekBar.getProgressDrawable(); + if (progressDrawableSpeaker instanceof LayerDrawable) { + LayerDrawable ldSpeaker = (LayerDrawable) progressDrawableSpeaker; + mSpeakerProgressDrawable = ldSpeaker.findDrawableByLayerId(android.R.id.progress); + } + Drawable progressDrawableBt = mBtSeekBar.getProgressDrawable(); + if (progressDrawableBt instanceof LayerDrawable) { + LayerDrawable ldBt = (LayerDrawable) progressDrawableBt; + mBtProgressDrawable = ldBt.findDrawableByLayerId(android.R.id.progress); + } + mEarpieceProgressThumb = mEarpieceSeekBar.getThumb(); + mHeadphoneProgressThumb = mHeadphoneSeekBar.getThumb(); + mSpeakerProgressThumb = mSpeakerSeekBar.getThumb(); + mBtProgressThumb = mBtSeekBar.getThumb(); + mRedFilter = new LightingColorFilter(Color.BLACK, + getContext().getResources().getColor(android.R.color.holo_red_light)); + + mEarpieceOgValue = Utils.readOneLine(INCALL_EARPIECE_FILE); + mEarpieceOgPercent = volumeToPercent(Integer.parseInt(mEarpieceOgValue)); + + mEarpieceSeekBar.setOnSeekBarChangeListener(this); + mEarpieceSeekBar.setProgress(Integer.valueOf(mEarpieceOgPercent)); + + mHeadphoneOgValue = Utils.readOneLine(INCALL_HEADPHONE_FILE); + mHeadphoneOgPercent = volumeToPercent(Integer.parseInt(mHeadphoneOgValue)); + + mHeadphoneSeekBar.setOnSeekBarChangeListener(this); + mHeadphoneSeekBar.setProgress(Integer.valueOf(mHeadphoneOgPercent)); + + mSpeakerOgValue = Utils.readOneLine(INCALL_SPEAKER_FILE); + mSpeakerOgPercent = volumeToPercent(Integer.parseInt(mSpeakerOgValue)); + + mSpeakerSeekBar.setOnSeekBarChangeListener(this); + mSpeakerSeekBar.setProgress(Integer.valueOf(mSpeakerOgPercent)); + + mBtOgValue = Utils.readOneLine(INCALL_BT_FILE); + mBtOgPercent = volumeToPercent(Integer.parseInt(mBtOgValue)); + + mBtSeekBar.setOnSeekBarChangeListener(this); + mBtSeekBar.setProgress(Integer.valueOf(mBtOgPercent)); + } + + @Override + protected void showDialog(Bundle state) { + super.showDialog(state); + + // can't use onPrepareDialogBuilder for this as we want the dialog + // to be kept open on click + AlertDialog d = (AlertDialog) getDialog(); + Button defaultsButton = d.getButton(DialogInterface.BUTTON_NEUTRAL); + defaultsButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mEarpieceSeekBar.setProgress(volumeToPercent(DEFAULT_VALUE)); + mHeadphoneSeekBar.setProgress(volumeToPercent(DEFAULT_VALUE)); + mSpeakerSeekBar.setProgress(volumeToPercent(DEFAULT_VALUE)); + mBtSeekBar.setProgress(volumeToPercent(DEFAULT_VALUE)); + } + }); + } + + @Override + protected void onDialogClosed(boolean positiveResult) { + super.onDialogClosed(positiveResult); + int volumeEarpiece, volumeHeadphone, volumeSpeaker, volumeBt; + + if (positiveResult) { + Editor editor = getEditor(); + + volumeEarpiece = percentToVolume(mEarpieceSeekBar.getProgress()); + editor.putString(INCALL_EARPIECE_FILE, String.valueOf(volumeEarpiece)); + volumeHeadphone = percentToVolume(mHeadphoneSeekBar.getProgress()); + editor.putString(INCALL_HEADPHONE_FILE, String.valueOf(volumeHeadphone)); + volumeSpeaker = percentToVolume(mSpeakerSeekBar.getProgress()); + editor.putString(INCALL_SPEAKER_FILE, String.valueOf(volumeSpeaker)); + volumeBt = percentToVolume(mBtSeekBar.getProgress()); + editor.putString(INCALL_BT_FILE, String.valueOf(volumeBt)); + editor.commit(); + } else { + Utils.writeValue(INCALL_EARPIECE_FILE, String.valueOf(mEarpieceOgPercent)); + Utils.writeValue(INCALL_HEADPHONE_FILE, String.valueOf(mHeadphoneOgPercent)); + Utils.writeValue(INCALL_SPEAKER_FILE, String.valueOf(mSpeakerOgPercent)); + Utils.writeValue(INCALL_BT_FILE, String.valueOf(mBtOgPercent)); + } + } + + public static void restore(Context context) { + SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context); + + if (isSupported("earpiece")) + Utils.writeValue(INCALL_EARPIECE_FILE, sharedPrefs.getString(INCALL_EARPIECE_FILE, "5")); + if (isSupported("headphone")) + Utils.writeValue(INCALL_HEADPHONE_FILE, sharedPrefs.getString(INCALL_HEADPHONE_FILE, "5")); + if (isSupported("speaker")) + Utils.writeValue(INCALL_SPEAKER_FILE, sharedPrefs.getString(INCALL_SPEAKER_FILE, "5")); + if (isSupported("bt")) + Utils.writeValue(INCALL_BT_FILE, sharedPrefs.getString(INCALL_BT_FILE, "5")); + } + + public static boolean isSupported(String output) { + String FILE = null; + Device outputDevice = Device.valueOf(output); + + switch(outputDevice) { + case earpiece: + FILE = INCALL_EARPIECE_FILE; + case headphone: + FILE = INCALL_HEADPHONE_FILE; + case speaker: + FILE = INCALL_SPEAKER_FILE; + case bt: + FILE = INCALL_BT_FILE; + } + return Utils.fileExists(FILE); + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + boolean shouldWarn = progress >= volumeToPercent(WARNING_THRESHOLD); + int stepSize = 10; + progress = Math.round(progress/stepSize)*stepSize; + + if(seekBar == mEarpieceSeekBar){ + if (mEarpieceProgressDrawable != null) { + mEarpieceProgressDrawable.setColorFilter(shouldWarn ? mRedFilter : null); + } + if (mEarpieceProgressThumb != null) { + mEarpieceProgressThumb.setColorFilter(shouldWarn ? mRedFilter : null); + } + mEarpieceSeekBar.setProgress(progress); + Utils.writeValue(INCALL_EARPIECE_FILE, String.valueOf(percentToVolume(progress))); + mEarpieceValue.setText(String.format("%d%%", progress)); + }else if(seekBar == mHeadphoneSeekBar){ + if (mHeadphoneProgressDrawable != null) { + mHeadphoneProgressDrawable.setColorFilter(shouldWarn ? mRedFilter : null); + } + if (mHeadphoneProgressThumb != null) { + mHeadphoneProgressThumb.setColorFilter(shouldWarn ? mRedFilter : null); + } + mHeadphoneSeekBar.setProgress(progress); + Utils.writeValue(INCALL_HEADPHONE_FILE, String.valueOf(percentToVolume(progress))); + mHeadphoneValue.setText(String.format("%d%%", progress)); + }else if(seekBar == mSpeakerSeekBar){ + if (mSpeakerProgressDrawable != null) { + mSpeakerProgressDrawable.setColorFilter(shouldWarn ? mRedFilter : null); + } + if (mSpeakerProgressThumb != null) { + mSpeakerProgressThumb.setColorFilter(shouldWarn ? mRedFilter : null); + } + mSpeakerSeekBar.setProgress(progress); + Utils.writeValue(INCALL_SPEAKER_FILE, String.valueOf(percentToVolume(progress))); + mSpeakerValue.setText(String.format("%d%%", progress)); + }else if(seekBar == mBtSeekBar){ + if (mBtProgressThumb != null) { + mBtProgressThumb.setColorFilter(shouldWarn ? mRedFilter : null); + } + if (mBtProgressDrawable != null) { + mBtProgressDrawable.setColorFilter(shouldWarn ? mRedFilter : null); + } + mBtSeekBar.setProgress(progress); + Utils.writeValue(INCALL_BT_FILE, String.valueOf(percentToVolume(progress))); + mBtValue.setText(String.format("%d%%", progress)); + } + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + // Do nothing + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + //Vibrator vib = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE); + //vib.vibrate(200); + } + + /** + * Convert volume to percent + */ + public static int volumeToPercent(int volume) { + double maxValue = MAX_VALUE; + double minValue = MIN_VALUE; + + double percent = volume * 10; + + if (percent > 100) + percent = 100; + else if (percent < 0) + percent = 0; + + return (int) percent; + } + + /** + * Convert percent to volume + */ + public static int percentToVolume(int percent) { + int volume = Math.round(percent / 10); + + if (volume > MAX_VALUE) + volume = MAX_VALUE; + else if (volume < MIN_VALUE) + volume = MIN_VALUE; + + return volume; + } +} diff --git a/DeviceSettings/src/com/cyanogenmod/settings/device/Startup.java b/DeviceSettings/src/com/cyanogenmod/settings/device/Startup.java index d93d6bf..b91a197 100644 --- a/DeviceSettings/src/com/cyanogenmod/settings/device/Startup.java +++ b/DeviceSettings/src/com/cyanogenmod/settings/device/Startup.java @@ -24,18 +24,20 @@ public class Startup extends BroadcastReceiver { @Override public void onReceive(final Context context, final Intent bootintent) { - DockFragmentActivity.restore(context); + AudioFragmentActivity.restore(context); + AudioOut.restore(context); + CABC.restore(context); HapticFragmentActivity.restore(context); Hspa.restore(context); - RadioFragmentActivity.restore(context); - ScreenFragmentActivity.restore(context); - CABC.restore(context); + IncallAudio.restore(context); + LedFade.restore(context); mDNIeScenario.restore(context); mDNIeMode.restore(context); mDNIeNegative.restore(context); - LedFade.restore(context); + RadioFragmentActivity.restore(context); + ScreenFragmentActivity.restore(context); + SPenPowerSavingMode.restore(context); TouchkeyTimeout.restore(context); VibratorTuningPreference.restore(context); - SPenPowerSavingMode.restore(context); } } |