1 /* 2 * Copyright (C) 2010-2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.musicfx; 18 19 import com.android.audiofx.OpenSLESConstants; 20 import com.android.musicfx.seekbar.SeekBar; 21 import com.android.musicfx.seekbar.SeekBar.OnSeekBarChangeListener; 22 23 import android.app.Activity; 24 import android.app.AlertDialog; 25 import android.app.Dialog; 26 import android.bluetooth.BluetoothClass; 27 import android.bluetooth.BluetoothDevice; 28 import android.content.BroadcastReceiver; 29 import android.content.Context; 30 import android.content.DialogInterface; 31 import android.content.DialogInterface.OnCancelListener; 32 import android.content.Intent; 33 import android.content.IntentFilter; 34 import android.media.AudioManager; 35 import android.media.audiofx.AudioEffect; 36 import android.media.audiofx.AudioEffect.Descriptor; 37 import android.os.Bundle; 38 import android.util.Log; 39 import android.view.Gravity; 40 import android.view.LayoutInflater; 41 import android.view.MotionEvent; 42 import android.view.View; 43 import android.view.View.OnClickListener; 44 import android.view.View.OnTouchListener; 45 import android.view.ViewGroup; 46 import android.widget.AdapterView; 47 import android.widget.AdapterView.OnItemSelectedListener; 48 import android.widget.ArrayAdapter; 49 import android.widget.CompoundButton; 50 import android.widget.CompoundButton.OnCheckedChangeListener; 51 import android.widget.LinearLayout; 52 import android.widget.ListView; 53 import android.widget.RelativeLayout; 54 import android.widget.Spinner; 55 import android.widget.TextView; 56 import android.widget.Toast; 57 58 import java.util.Formatter; 59 import java.util.Locale; 60 61 /** 62 * 63 */ 64 public class ActivityMusic extends Activity implements OnSeekBarChangeListener { 65 private final static String TAG = "MusicFXActivityMusic"; 66 67 /** 68 * Max number of EQ bands supported 69 */ 70 private final static int EQUALIZER_MAX_BANDS = 32; 71 72 /** 73 * Indicates if Virtualizer effect is supported. 74 */ 75 private boolean mVirtualizerSupported; 76 /** 77 * Indicates if BassBoost effect is supported. 78 */ 79 private boolean mBassBoostSupported; 80 /** 81 * Indicates if Equalizer effect is supported. 82 */ 83 private boolean mEqualizerSupported; 84 /** 85 * Indicates if Preset Reverb effect is supported. 86 */ 87 private boolean mPresetReverbSupported; 88 89 // Equalizer fields 90 private final SeekBar[] mEqualizerSeekBar = new SeekBar[EQUALIZER_MAX_BANDS]; 91 private int mNumberEqualizerBands; 92 private int mEqualizerMinBandLevel; 93 private int mEQPresetUserPos = 1; 94 private int mEQPreset; 95 private int mEQPresetPrevious; 96 private int[] mEQPresetUserBandLevelsPrev; 97 private String[] mEQPresetNames; 98 99 private int mPRPreset; 100 private int mPRPresetPrevious; 101 102 private boolean mIsHeadsetOn = false; 103 104 private StringBuilder mFormatBuilder = new StringBuilder(); 105 private Formatter mFormatter = new Formatter(mFormatBuilder, Locale.getDefault()); 106 107 /** 108 * Mapping for the EQ widget ids per band 109 */ 110 private static final int[][] EQViewElementIds = { 111 { R.id.EQBand0TextView, R.id.EQBand0SeekBar }, 112 { R.id.EQBand1TextView, R.id.EQBand1SeekBar }, 113 { R.id.EQBand2TextView, R.id.EQBand2SeekBar }, 114 { R.id.EQBand3TextView, R.id.EQBand3SeekBar }, 115 { R.id.EQBand4TextView, R.id.EQBand4SeekBar }, 116 { R.id.EQBand5TextView, R.id.EQBand5SeekBar }, 117 { R.id.EQBand6TextView, R.id.EQBand6SeekBar }, 118 { R.id.EQBand7TextView, R.id.EQBand7SeekBar }, 119 { R.id.EQBand8TextView, R.id.EQBand8SeekBar }, 120 { R.id.EQBand9TextView, R.id.EQBand9SeekBar }, 121 { R.id.EQBand10TextView, R.id.EQBand10SeekBar }, 122 { R.id.EQBand11TextView, R.id.EQBand11SeekBar }, 123 { R.id.EQBand12TextView, R.id.EQBand12SeekBar }, 124 { R.id.EQBand13TextView, R.id.EQBand13SeekBar }, 125 { R.id.EQBand14TextView, R.id.EQBand14SeekBar }, 126 { R.id.EQBand15TextView, R.id.EQBand15SeekBar }, 127 { R.id.EQBand16TextView, R.id.EQBand16SeekBar }, 128 { R.id.EQBand17TextView, R.id.EQBand17SeekBar }, 129 { R.id.EQBand18TextView, R.id.EQBand18SeekBar }, 130 { R.id.EQBand19TextView, R.id.EQBand19SeekBar }, 131 { R.id.EQBand20TextView, R.id.EQBand20SeekBar }, 132 { R.id.EQBand21TextView, R.id.EQBand21SeekBar }, 133 { R.id.EQBand22TextView, R.id.EQBand22SeekBar }, 134 { R.id.EQBand23TextView, R.id.EQBand23SeekBar }, 135 { R.id.EQBand24TextView, R.id.EQBand24SeekBar }, 136 { R.id.EQBand25TextView, R.id.EQBand25SeekBar }, 137 { R.id.EQBand26TextView, R.id.EQBand26SeekBar }, 138 { R.id.EQBand27TextView, R.id.EQBand27SeekBar }, 139 { R.id.EQBand28TextView, R.id.EQBand28SeekBar }, 140 { R.id.EQBand29TextView, R.id.EQBand29SeekBar }, 141 { R.id.EQBand30TextView, R.id.EQBand30SeekBar }, 142 { R.id.EQBand31TextView, R.id.EQBand31SeekBar } }; 143 144 // Preset Reverb fields 145 /** 146 * Array containing the PR preset names. 147 */ 148 private static final String[] PRESETREVERBPRESETSTRINGS = { "None", "SmallRoom", "MediumRoom", 149 "LargeRoom", "MediumHall", "LargeHall", "Plate" }; 150 151 /** 152 * Context field 153 */ 154 private Context mContext; 155 156 /** 157 * Calling package name field 158 */ 159 private String mCallingPackageName = "empty"; 160 161 /** 162 * Audio session field 163 */ 164 private int mAudioSession = AudioEffect.ERROR_BAD_VALUE; 165 166 // Broadcast receiver to handle wired and Bluetooth A2dp headset events 167 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 168 @Override 169 public void onReceive(final Context context, final Intent intent) { 170 final String action = intent.getAction(); 171 final boolean isHeadsetOnPrev = mIsHeadsetOn; 172 final AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 173 if (action.equals(Intent.ACTION_HEADSET_PLUG)) { 174 mIsHeadsetOn = (intent.getIntExtra("state", 0) == 1) 175 || audioManager.isBluetoothA2dpOn(); 176 } else if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) { 177 final int deviceClass = ((BluetoothDevice) intent 178 .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)).getBluetoothClass() 179 .getDeviceClass(); 180 if ((deviceClass == BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES) 181 || (deviceClass == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET)) { 182 mIsHeadsetOn = true; 183 } 184 } else if (action.equals(AudioManager.ACTION_AUDIO_BECOMING_NOISY)) { 185 mIsHeadsetOn = audioManager.isBluetoothA2dpOn() || audioManager.isWiredHeadsetOn(); 186 } else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) { 187 final int deviceClass = ((BluetoothDevice) intent 188 .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)).getBluetoothClass() 189 .getDeviceClass(); 190 if ((deviceClass == BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES) 191 || (deviceClass == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET)) { 192 mIsHeadsetOn = audioManager.isWiredHeadsetOn(); 193 } 194 } 195 if (isHeadsetOnPrev != mIsHeadsetOn) { 196 updateUIHeadset(); 197 } 198 } 199 }; 200 201 /* 202 * Declares and initializes all objects and widgets in the layouts and the CheckBox and SeekBar 203 * onchange methods on creation. 204 * 205 * (non-Javadoc) 206 * 207 * @see android.app.ActivityGroup#onCreate(android.os.Bundle) 208 */ 209 @Override 210 public void onCreate(final Bundle savedInstanceState) { 211 super.onCreate(savedInstanceState); 212 213 // Init context to be used in listeners 214 mContext = this; 215 216 // Receive intent 217 // get calling intent 218 final Intent intent = getIntent(); 219 mAudioSession = intent.getIntExtra(AudioEffect.EXTRA_AUDIO_SESSION, 220 AudioEffect.ERROR_BAD_VALUE); 221 Log.v(TAG, "audio session: " + mAudioSession); 222 223 mCallingPackageName = getCallingPackage(); 224 225 // check for errors 226 if (mCallingPackageName == null) { 227 Log.e(TAG, "Package name is null"); 228 setResult(RESULT_CANCELED); 229 finish(); 230 return; 231 } 232 setResult(RESULT_OK); 233 234 Log.v(TAG, mCallingPackageName + " (" + mAudioSession + ")"); 235 236 ControlPanelEffect.initEffectsPreferences(mContext, mCallingPackageName, mAudioSession); 237 238 // query available effects 239 final Descriptor[] effects = AudioEffect.queryEffects(); 240 241 // Determine available/supported effects 242 Log.v(TAG, "Available effects:"); 243 for (final Descriptor effect : effects) { 244 Log.v(TAG, effect.name.toString() + ", type: " + effect.type.toString()); 245 246 if (effect.type.equals(AudioEffect.EFFECT_TYPE_VIRTUALIZER)) { 247 mVirtualizerSupported = true; 248 } else if (effect.type.equals(AudioEffect.EFFECT_TYPE_BASS_BOOST)) { 249 mBassBoostSupported = true; 250 } else if (effect.type.equals(AudioEffect.EFFECT_TYPE_EQUALIZER)) { 251 mEqualizerSupported = true; 252 } else if (effect.type.equals(AudioEffect.EFFECT_TYPE_PRESET_REVERB)) { 253 mPresetReverbSupported = true; 254 } 255 } 256 257 setContentView(R.layout.music_main); 258 final ViewGroup viewGroup = (ViewGroup) findViewById(R.id.contentSoundEffects); 259 final View mainToggleView = findViewById(R.id.mainToggleEffectsLayout); 260 261 // Fill array with presets from AudioEffects call. 262 // allocate a space for 2 extra strings (CI Extreme & User) 263 final int numPresets = ControlPanelEffect.getParameterInt(mContext, mCallingPackageName, 264 mAudioSession, ControlPanelEffect.Key.eq_num_presets); 265 mEQPresetNames = new String[numPresets + 2]; 266 for (short i = 0; i < numPresets; i++) { 267 mEQPresetNames[i] = ControlPanelEffect.getParameterString(mContext, 268 mCallingPackageName, mAudioSession, ControlPanelEffect.Key.eq_preset_name, i); 269 } 270 mEQPresetNames[numPresets] = getString(R.string.ci_extreme); 271 mEQPresetNames[numPresets + 1] = getString(R.string.user); 272 mEQPresetUserPos = numPresets + 1; 273 274 // Watch for button clicks and initialization. 275 if ((mVirtualizerSupported) || (mBassBoostSupported) || (mEqualizerSupported) 276 || (mPresetReverbSupported)) { 277 // Set the listener for the main enhancements toggle button. 278 // Depending on the state enable the supported effects if they were 279 // checked in the setup tab. 280 final CompoundButton toggleEffects = (CompoundButton) findViewById(R.id.mainToggleEffectsCheckBox); 281 toggleEffects.setOnCheckedChangeListener(new OnCheckedChangeListener() { 282 @Override 283 public void onCheckedChanged(final CompoundButton buttonView, 284 final boolean isChecked) { 285 286 // set parameter and state 287 ControlPanelEffect.setParameterBoolean(mContext, mCallingPackageName, 288 mAudioSession, ControlPanelEffect.Key.global_enabled, isChecked); 289 // Enable Linear layout (in scroll layout) view with all 290 // effect contents depending on checked state 291 setEnabledAllChildren(viewGroup, isChecked); 292 // update UI according to headset state 293 updateUIHeadset(); 294 } 295 }); 296 297 mainToggleView.setVisibility(View.VISIBLE); 298 299 // Initialize the Virtualizer elements. 300 // Set the SeekBar listener. 301 if (mVirtualizerSupported) { 302 // Show msg when disabled slider (layout) is touched 303 findViewById(R.id.vILayout).setOnTouchListener(new OnTouchListener() { 304 305 @Override 306 public boolean onTouch(final View v, final MotionEvent event) { 307 if (event.getAction() == MotionEvent.ACTION_UP) { 308 showHeadsetMsg(); 309 } 310 return false; 311 } 312 }); 313 314 final SeekBar seekbar = (SeekBar) findViewById(R.id.vIStrengthSeekBar); 315 seekbar.setMax(OpenSLESConstants.VIRTUALIZER_MAX_STRENGTH 316 - OpenSLESConstants.VIRTUALIZER_MIN_STRENGTH); 317 318 seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { 319 // Update the parameters while SeekBar changes and set the 320 // effect parameter. 321 322 @Override 323 public void onProgressChanged(final SeekBar seekBar, final int progress, 324 final boolean fromUser) { 325 // set parameter and state 326 ControlPanelEffect.setParameterInt(mContext, mCallingPackageName, 327 mAudioSession, ControlPanelEffect.Key.virt_strength, progress); 328 } 329 330 // If slider pos was 0 when starting re-enable effect 331 @Override 332 public void onStartTrackingTouch(final SeekBar seekBar) { 333 if (seekBar.getProgress() == 0) { 334 ControlPanelEffect.setParameterBoolean(mContext, mCallingPackageName, 335 mAudioSession, ControlPanelEffect.Key.virt_enabled, true); 336 } 337 } 338 339 // If slider pos = 0 when stopping disable effect 340 @Override 341 public void onStopTrackingTouch(final SeekBar seekBar) { 342 if (seekBar.getProgress() == 0) { 343 // disable 344 ControlPanelEffect.setParameterBoolean(mContext, mCallingPackageName, 345 mAudioSession, ControlPanelEffect.Key.virt_enabled, false); 346 } 347 } 348 }); 349 } 350 351 // Initialize the Bass Boost elements. 352 // Set the SeekBar listener. 353 if (mBassBoostSupported) { 354 // Show msg when disabled slider (layout) is touched 355 findViewById(R.id.bBLayout).setOnTouchListener(new OnTouchListener() { 356 357 @Override 358 public boolean onTouch(final View v, final MotionEvent event) { 359 if (event.getAction() == MotionEvent.ACTION_UP) { 360 showHeadsetMsg(); 361 } 362 return false; 363 } 364 }); 365 366 final SeekBar seekbar = (SeekBar) findViewById(R.id.bBStrengthSeekBar); 367 seekbar.setMax(OpenSLESConstants.BASSBOOST_MAX_STRENGTH 368 - OpenSLESConstants.BASSBOOST_MIN_STRENGTH); 369 370 seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { 371 // Update the parameters while SeekBar changes and set the 372 // effect parameter. 373 374 @Override 375 public void onProgressChanged(final SeekBar seekBar, final int progress, 376 final boolean fromUser) { 377 // set parameter and state 378 ControlPanelEffect.setParameterInt(mContext, mCallingPackageName, 379 mAudioSession, ControlPanelEffect.Key.bb_strength, progress); 380 } 381 382 // If slider pos was 0 when starting re-enable effect 383 @Override 384 public void onStartTrackingTouch(final SeekBar seekBar) { 385 if (seekBar.getProgress() == 0) { 386 ControlPanelEffect.setParameterBoolean(mContext, mCallingPackageName, 387 mAudioSession, ControlPanelEffect.Key.bb_enabled, true); 388 } 389 } 390 391 // If slider pos = 0 when stopping disable effect 392 @Override 393 public void onStopTrackingTouch(final SeekBar seekBar) { 394 if (seekBar.getProgress() == 0) { 395 // disable 396 ControlPanelEffect.setParameterBoolean(mContext, mCallingPackageName, 397 mAudioSession, ControlPanelEffect.Key.bb_enabled, false); 398 } 399 400 } 401 }); 402 } 403 404 // Initialize the Equalizer elements. 405 if (mEqualizerSupported) { 406 mEQPreset = ControlPanelEffect.getParameterInt(mContext, mCallingPackageName, 407 mAudioSession, ControlPanelEffect.Key.eq_current_preset); 408 if (mEQPreset >= mEQPresetNames.length) { 409 mEQPreset = 0; 410 } 411 mEQPresetPrevious = mEQPreset; 412 equalizerSpinnerInit((Spinner)findViewById(R.id.eqSpinner)); 413 equalizerBandsInit(findViewById(R.id.eqcontainer)); 414 } 415 416 // Initialize the Preset Reverb elements. 417 // Set Spinner listeners. 418 if (mPresetReverbSupported) { 419 mPRPreset = ControlPanelEffect.getParameterInt(mContext, mCallingPackageName, 420 mAudioSession, ControlPanelEffect.Key.pr_current_preset); 421 mPRPresetPrevious = mPRPreset; 422 reverbSpinnerInit((Spinner)findViewById(R.id.prSpinner)); 423 } 424 425 } else { 426 viewGroup.setVisibility(View.GONE); 427 mainToggleView.setVisibility(View.GONE); 428 ((TextView) findViewById(R.id.noEffectsTextView)).setVisibility(View.VISIBLE); 429 } 430 431 // TODO, actually use the action bar 432 getActionBar().hide(); 433 } 434 435 /* 436 * (non-Javadoc) 437 * 438 * @see android.app.Activity#onResume() 439 */ 440 @Override 441 protected void onResume() { 442 super.onResume(); 443 if ((mVirtualizerSupported) || (mBassBoostSupported) || (mEqualizerSupported) 444 || (mPresetReverbSupported)) { 445 // Listen for broadcast intents that might affect the onscreen UI for headset. 446 final IntentFilter intentFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG); 447 intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED); 448 intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); 449 intentFilter.addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY); 450 registerReceiver(mReceiver, intentFilter); 451 452 // Check if wired or Bluetooth headset is connected/on 453 final AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 454 mIsHeadsetOn = (audioManager.isWiredHeadsetOn() || audioManager.isBluetoothA2dpOn()); 455 Log.v(TAG, "onResume: mIsHeadsetOn : " + mIsHeadsetOn); 456 457 // Update UI 458 updateUI(); 459 } 460 } 461 462 /* 463 * (non-Javadoc) 464 * 465 * @see android.app.Activity#onPause() 466 */ 467 @Override 468 protected void onPause() { 469 super.onPause(); 470 471 // Unregister for broadcast intents. (These affect the visible UI, 472 // so we only care about them while we're in the foreground.) 473 unregisterReceiver(mReceiver); 474 } 475 476 private void reverbSpinnerInit(Spinner spinner) { 477 ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, 478 android.R.layout.simple_spinner_item, PRESETREVERBPRESETSTRINGS); 479 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 480 spinner.setAdapter(adapter); 481 spinner.setOnItemSelectedListener(new OnItemSelectedListener() { 482 483 @Override 484 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { 485 if (position != mPRPresetPrevious) { 486 presetReverbSetPreset(position); 487 } 488 mPRPresetPrevious = position; 489 } 490 491 @Override 492 public void onNothingSelected(AdapterView<?> parent) { 493 } 494 }); 495 spinner.setSelection(mPRPreset); 496 } 497 498 private void equalizerSpinnerInit(Spinner spinner) { 499 ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, 500 android.R.layout.simple_spinner_item, mEQPresetNames); 501 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 502 spinner.setAdapter(adapter); 503 spinner.setOnItemSelectedListener(new OnItemSelectedListener() { 504 505 @Override 506 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { 507 if (position != mEQPresetPrevious) { 508 equalizerSetPreset(position); 509 } 510 mEQPresetPrevious = position; 511 } 512 513 @Override 514 public void onNothingSelected(AdapterView<?> parent) { 515 } 516 }); 517 spinner.setSelection(mEQPreset); 518 } 519 520 521 /** 522 * En/disables all children for a given view. For linear and relative layout children do this 523 * recursively 524 * 525 * @param viewGroup 526 * @param enabled 527 */ 528 private void setEnabledAllChildren(final ViewGroup viewGroup, final boolean enabled) { 529 final int count = viewGroup.getChildCount(); 530 for (int i = 0; i < count; i++) { 531 final View view = viewGroup.getChildAt(i); 532 if ((view instanceof LinearLayout) || (view instanceof RelativeLayout)) { 533 final ViewGroup vg = (ViewGroup) view; 534 setEnabledAllChildren(vg, enabled); 535 } 536 view.setEnabled(enabled); 537 } 538 } 539 540 /** 541 * Updates UI (checkbox, seekbars, enabled states) according to the current stored preferences. 542 */ 543 private void updateUI() { 544 final boolean isEnabled = ControlPanelEffect.getParameterBoolean(mContext, 545 mCallingPackageName, mAudioSession, ControlPanelEffect.Key.global_enabled); 546 ((CompoundButton) findViewById(R.id.mainToggleEffectsCheckBox)).setChecked(isEnabled); 547 setEnabledAllChildren((ViewGroup) findViewById(R.id.contentSoundEffects), isEnabled); 548 updateUIHeadset(); 549 550 if (mVirtualizerSupported) { 551 ((SeekBar) findViewById(R.id.vIStrengthSeekBar)).setProgress(ControlPanelEffect 552 .getParameterInt(mContext, mCallingPackageName, mAudioSession, 553 ControlPanelEffect.Key.virt_strength)); 554 } 555 if (mBassBoostSupported) { 556 ((SeekBar) findViewById(R.id.bBStrengthSeekBar)).setProgress(ControlPanelEffect 557 .getParameterInt(mContext, mCallingPackageName, mAudioSession, 558 ControlPanelEffect.Key.bb_strength)); 559 } 560 if (mEqualizerSupported) { 561 equalizerUpdateDisplay(); 562 } 563 if (mPresetReverbSupported) { 564 int reverb = ControlPanelEffect.getParameterInt( 565 mContext, mCallingPackageName, mAudioSession, 566 ControlPanelEffect.Key.pr_current_preset); 567 ((Spinner)findViewById(R.id.prSpinner)).setSelection(reverb); 568 } 569 } 570 571 /** 572 * Updates UI for headset mode. En/disable VI and BB controls depending on headset state 573 * (on/off) if effects are on. Do the inverse for their layouts so they can take over 574 * control/events. 575 */ 576 private void updateUIHeadset() { 577 if (((CompoundButton) findViewById(R.id.mainToggleEffectsCheckBox)).isChecked()) { 578 ((TextView) findViewById(R.id.vIStrengthText)).setEnabled(mIsHeadsetOn); 579 ((SeekBar) findViewById(R.id.vIStrengthSeekBar)).setEnabled(mIsHeadsetOn); 580 findViewById(R.id.vILayout).setEnabled(!mIsHeadsetOn); 581 ((TextView) findViewById(R.id.bBStrengthText)).setEnabled(mIsHeadsetOn); 582 ((SeekBar) findViewById(R.id.bBStrengthSeekBar)).setEnabled(mIsHeadsetOn); 583 findViewById(R.id.bBLayout).setEnabled(!mIsHeadsetOn); 584 } 585 } 586 587 /** 588 * Initializes the equalizer elements. Set the SeekBars and Spinner listeners. 589 */ 590 private void equalizerBandsInit(View eqcontainer) { 591 // Initialize the N-Band Equalizer elements. 592 mNumberEqualizerBands = ControlPanelEffect.getParameterInt(mContext, mCallingPackageName, 593 mAudioSession, ControlPanelEffect.Key.eq_num_bands); 594 mEQPresetUserBandLevelsPrev = ControlPanelEffect.getParameterIntArray(mContext, 595 mCallingPackageName, mAudioSession, 596 ControlPanelEffect.Key.eq_preset_user_band_level); 597 final int[] centerFreqs = ControlPanelEffect.getParameterIntArray(mContext, 598 mCallingPackageName, mAudioSession, ControlPanelEffect.Key.eq_center_freq); 599 final int[] bandLevelRange = ControlPanelEffect.getParameterIntArray(mContext, 600 mCallingPackageName, mAudioSession, ControlPanelEffect.Key.eq_level_range); 601 mEqualizerMinBandLevel = bandLevelRange[0]; 602 final int mEqualizerMaxBandLevel = bandLevelRange[1]; 603 604 for (int band = 0; band < mNumberEqualizerBands; band++) { 605 // Unit conversion from mHz to Hz and use k prefix if necessary to display 606 final int centerFreq = centerFreqs[band] / 1000; 607 float centerFreqHz = centerFreq; 608 String unitPrefix = ""; 609 if (centerFreqHz >= 1000) { 610 centerFreqHz = centerFreqHz / 1000; 611 unitPrefix = "k"; 612 } 613 ((TextView) eqcontainer.findViewById(EQViewElementIds[band][0])).setText( 614 format("%.0f ", centerFreqHz) + unitPrefix + "Hz"); 615 mEqualizerSeekBar[band] = (SeekBar) eqcontainer 616 .findViewById(EQViewElementIds[band][1]); 617 mEqualizerSeekBar[band].setMax(mEqualizerMaxBandLevel - mEqualizerMinBandLevel); 618 mEqualizerSeekBar[band].setOnSeekBarChangeListener(this); 619 } 620 621 // Hide the inactive Equalizer bands. 622 for (int band = mNumberEqualizerBands; band < EQUALIZER_MAX_BANDS; band++) { 623 // CenterFreq text 624 eqcontainer.findViewById(EQViewElementIds[band][0]).setVisibility(View.GONE); 625 // SeekBar 626 eqcontainer.findViewById(EQViewElementIds[band][1]).setVisibility(View.GONE); 627 } 628 629 // TODO: get the actual values from somewhere 630 TextView tv = (TextView) findViewById(R.id.maxLevelText); 631 tv.setText("+15 dB"); 632 tv = (TextView) findViewById(R.id.centerLevelText); 633 tv.setText("0 dB"); 634 tv = (TextView) findViewById(R.id.minLevelText); 635 tv.setText("-15 dB"); 636 equalizerUpdateDisplay(); 637 } 638 639 private String format(String format, Object... args) { 640 mFormatBuilder.setLength(0); 641 mFormatter.format(format, args); 642 return mFormatBuilder.toString(); 643 } 644 645 /* 646 * For the EQ Band SeekBars 647 * 648 * (non-Javadoc) 649 * 650 * @see android.widget.SeekBar.OnSeekBarChangeListener#onProgressChanged(android 651 * .widget.SeekBar, int, boolean) 652 */ 653 654 @Override 655 public void onProgressChanged(final SeekBar seekbar, final int progress, final boolean fromUser) { 656 final int id = seekbar.getId(); 657 658 for (short band = 0; band < mNumberEqualizerBands; band++) { 659 if (id == EQViewElementIds[band][1]) { 660 final short level = (short) (progress + mEqualizerMinBandLevel); 661 if (fromUser) { 662 equalizerBandUpdate(band, level); 663 } 664 break; 665 } 666 } 667 } 668 669 /* 670 * (non-Javadoc) 671 * 672 * @see android.widget.SeekBar.OnSeekBarChangeListener#onStartTrackingTouch(android 673 * .widget.SeekBar) 674 */ 675 676 @Override 677 public void onStartTrackingTouch(final SeekBar seekbar) { 678 // get current levels 679 final int[] bandLevels = ControlPanelEffect.getParameterIntArray(mContext, 680 mCallingPackageName, mAudioSession, ControlPanelEffect.Key.eq_band_level); 681 // copy current levels to user preset 682 for (short band = 0; band < mNumberEqualizerBands; band++) { 683 equalizerBandUpdate(band, bandLevels[band]); 684 } 685 equalizerSetPreset(mEQPresetUserPos); 686 } 687 688 /* 689 * Updates the EQ display when the user stops changing. 690 * 691 * (non-Javadoc) 692 * 693 * @see android.widget.SeekBar.OnSeekBarChangeListener#onStopTrackingTouch(android 694 * .widget.SeekBar) 695 */ 696 697 @Override 698 public void onStopTrackingTouch(final SeekBar seekbar) { 699 equalizerUpdateDisplay(); 700 } 701 702 /** 703 * Updates the EQ by getting the parameters. 704 */ 705 private void equalizerUpdateDisplay() { 706 // Update and show the active N-Band Equalizer bands. 707 final int[] bandLevels = ControlPanelEffect.getParameterIntArray(mContext, 708 mCallingPackageName, mAudioSession, ControlPanelEffect.Key.eq_band_level); 709 for (short band = 0; band < mNumberEqualizerBands; band++) { 710 final int level = bandLevels[band]; 711 final int progress = level - mEqualizerMinBandLevel; 712 mEqualizerSeekBar[band].setProgress(progress); 713 } 714 } 715 716 /** 717 * Updates/sets a given EQ band level. 718 * 719 * @param band 720 * Band id 721 * @param level 722 * EQ band level 723 */ 724 private void equalizerBandUpdate(final int band, final int level) { 725 ControlPanelEffect.setParameterInt(mContext, mCallingPackageName, mAudioSession, 726 ControlPanelEffect.Key.eq_band_level, level, band); 727 } 728 729 /** 730 * Sets the given EQ preset. 731 * 732 * @param preset 733 * EQ preset id. 734 */ 735 private void equalizerSetPreset(final int preset) { 736 ControlPanelEffect.setParameterInt(mContext, mCallingPackageName, mAudioSession, 737 ControlPanelEffect.Key.eq_current_preset, preset); 738 equalizerUpdateDisplay(); 739 } 740 741 /** 742 * Sets the given PR preset. 743 * 744 * @param preset 745 * PR preset id. 746 */ 747 private void presetReverbSetPreset(final int preset) { 748 ControlPanelEffect.setParameterInt(mContext, mCallingPackageName, mAudioSession, 749 ControlPanelEffect.Key.pr_current_preset, preset); 750 } 751 752 /** 753 * Show msg that headset needs to be plugged. 754 */ 755 private void showHeadsetMsg() { 756 final Context context = getApplicationContext(); 757 final int duration = Toast.LENGTH_SHORT; 758 759 final Toast toast = Toast.makeText(context, getString(R.string.headset_plug), duration); 760 toast.setGravity(Gravity.CENTER, toast.getXOffset() / 2, toast.getYOffset() / 2); 761 toast.show(); 762 } 763 } 764