package com.marverenic.music.fragments;
import android.app.ActionBar;
import android.content.Context;
import android.media.audiofx.Equalizer;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.widget.SwitchCompat;
import android.support.v7.widget.Toolbar;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.Spinner;
import android.widget.TextView;
import com.marverenic.music.JockeyApplication;
import com.marverenic.music.R;
import com.marverenic.music.data.store.PreferenceStore;
import com.marverenic.music.player.PlayerController;
import com.marverenic.music.player.RemoteEqualizer;
import com.marverenic.music.utils.Util;
import javax.inject.Inject;
public class EqualizerFragment extends Fragment implements CompoundButton.OnCheckedChangeListener,
FragmentManager.OnBackStackChangedListener {
@Inject PreferenceStore mPrefStore;
@Inject PlayerController mPlayerController;
private RemoteEqualizer equalizer;
private EqualizerFrame[] sliders;
private TextView presetSpinnerPrefix;
private Spinner presetSpinner;
private SwitchCompat equalizerToggle;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().getSupportFragmentManager().addOnBackStackChangedListener(this);
JockeyApplication.getComponent(this).inject(this);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.fragment_equalizer, container, false);
presetSpinnerPrefix = (TextView) layout.findViewById(R.id.eq_preset_prefix);
presetSpinner = (Spinner) layout.findViewById(R.id.eq_preset_spinner);
Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);
if (toolbar != null) {
equalizerToggle = new SwitchCompat(getActivity());
equalizerToggle.setOnCheckedChangeListener(this);
Toolbar.LayoutParams params = new Toolbar.LayoutParams(
ActionBar.LayoutParams.WRAP_CONTENT,
ActionBar.LayoutParams.WRAP_CONTENT,
Gravity.END);
int padding = (int) (16 * getResources().getDisplayMetrics().density);
params.setMargins(padding, 0, padding, 0);
toolbar.addView(equalizerToggle, params);
AlphaAnimation anim = new AlphaAnimation(0f, 1.0f);
anim.setDuration(getResources().getInteger(android.R.integer.config_shortAnimTime));
anim.setInterpolator(getContext(), android.R.anim.decelerate_interpolator);
equalizerToggle.startAnimation(anim);
}
LinearLayout equalizerPanel = (LinearLayout) layout.findViewById(R.id.equalizer_panel);
equalizer = generateEqualizerConfig();
int bandCount = (equalizer != null) ? equalizer.getNumberOfBands() : 0;
sliders = new EqualizerFrame[bandCount];
PresetAdapter presetAdapter = new PresetAdapter(getActivity(), equalizer, sliders);
presetSpinner.setAdapter(presetAdapter);
presetSpinner.setSelection(mPrefStore.getEqualizerPresetId() + 1);
presetSpinner.setOnItemSelectedListener(presetAdapter);
for (short i = 0; i < bandCount; i++) {
inflater.inflate(R.layout.instance_eq_slider, equalizerPanel, true);
sliders[i] = new EqualizerFrame(equalizerPanel.getChildAt(i), equalizer,
i, presetSpinner);
}
setEqualizerEnabled(mPrefStore.getEqualizerEnabled());
// If this device already has an application that can handle equalizers system-wide, inform
// the user of possible issues by using Jockey's built-in equalizer
if (Util.getSystemEqIntent(getActivity()) != null) {
((TextView) layout.findViewById(R.id.equalizer_notes))
.setText(R.string.equalizerNoteSystem);
}
return layout;
}
private RemoteEqualizer generateEqualizerConfig() {
// Obtain an instance of the system equalizer to discover available configuration options
// for an equalizer including bands and presets. This equalizer is not used to control
// audio settings and is released before this method ends
Equalizer systemEqualizer = new Equalizer(0, 1);
RemoteEqualizer eq = new RemoteEqualizer(systemEqualizer);
Equalizer.Settings settings = mPrefStore.getEqualizerSettings();
if (settings != null) {
eq.setProperties(mPrefStore.getEqualizerSettings());
}
systemEqualizer.release();
return eq;
}
private void applyEqualizer() {
mPrefStore.setEqualizerPresetId((int) presetSpinner.getSelectedItemId());
mPrefStore.setEqualizerSettings(equalizer.getProperties());
mPrefStore.setEqualizerEnabled(equalizerToggle.isChecked());
mPlayerController.updatePlayerPreferences(mPrefStore);
}
@Override
public void onResume() {
super.onResume();
Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);
if (toolbar != null) {
toolbar.setTitle(R.string.header_equalizer);
}
}
private void setEqualizerEnabled(boolean enabled) {
if (equalizerToggle.isChecked() != enabled) {
equalizerToggle.setChecked(enabled);
}
presetSpinnerPrefix.setEnabled(enabled);
presetSpinner.setEnabled(enabled);
for (EqualizerFrame f : sliders) {
f.update(equalizer.getCurrentPreset() == -1 && enabled);
}
applyEqualizer();
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
setEqualizerEnabled(isChecked);
applyEqualizer();
}
@Override
public void onBackStackChanged() {
if (isRemoving()) {
final Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);
if (toolbar != null) {
final int duration = getResources().getInteger(android.R.integer.config_mediumAnimTime);
AlphaAnimation anim = new AlphaAnimation(1.0f, 0f);
anim.setDuration(duration);
anim.setInterpolator(getContext(), android.R.anim.decelerate_interpolator);
equalizerToggle.startAnimation(anim);
new Handler().postDelayed(() -> toolbar.removeView(equalizerToggle), duration);
}
applyEqualizer();
}
}
private class PresetAdapter extends BaseAdapter implements AdapterView.OnItemSelectedListener {
private Context context;
private String[] presets;
private EqualizerFrame[] sliders;
PresetAdapter(Context context, RemoteEqualizer equalizer, EqualizerFrame[] sliders) {
this.context = context;
this.sliders = sliders;
presets = new String[equalizer.getNumberOfPresets() + 1];
presets[0] = "Custom"; // TODO String resource
for (short i = 0; i < presets.length - 1; i++) {
presets[i + 1] = equalizer.getPresetName(i);
}
}
@Override
public int getCount() {
return presets.length;
}
@Override
public Object getItem(int position) {
return presets[position];
}
@Override
public long getItemId(int position) {
return position - 1;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater
.from(context)
.inflate(android.R.layout.simple_spinner_item, parent, false);
}
TextView textView = (TextView) convertView.findViewById(android.R.id.text1);
textView.setText(presets[position]);
return convertView;
}
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater
.from(context)
.inflate(android.R.layout.simple_spinner_dropdown_item, parent, false);
}
return getView(position, convertView, parent);
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
equalizer.usePreset((short) id);
applyEqualizer();
for (EqualizerFrame f : sliders) {
f.update(id == -1 && equalizerToggle.isChecked());
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
}
private class EqualizerFrame implements SeekBar.OnSeekBarChangeListener {
final short bandNumber;
final SeekBar bandSlider;
final TextView bandLabel;
final Spinner presetSpinner;
final int minLevel;
final int maxLevel;
public EqualizerFrame(View root, RemoteEqualizer eq, short bandNumber,
Spinner presetSpinner) {
this.bandNumber = bandNumber;
this.presetSpinner = presetSpinner;
bandSlider = (SeekBar) root.findViewById(R.id.eq_slider);
bandLabel = (TextView) root.findViewById(R.id.eq_band_name);
int frequency = eq.getCenterFreq(bandNumber) / 1000;
if (frequency > 1000) {
bandLabel.setText(frequency / 1000 + "K");
} else {
bandLabel.setText(Integer.toString(frequency));
}
int[] range = eq.getBandLevelRange();
minLevel = range[0];
maxLevel = range[1];
bandSlider.setMax(Math.abs(minLevel) + maxLevel);
bandSlider.setProgress(eq.getBandLevel(bandNumber) + Math.abs(range[0]));
bandSlider.setOnSeekBarChangeListener(this);
}
public void update(boolean enabled) {
bandSlider.setEnabled(enabled);
bandLabel.setEnabled(enabled);
}
public void update(int level) {
bandSlider.setProgress(level + Math.abs(minLevel));
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
equalizer.setBandLevel(bandNumber, (short) (progress - Math.abs(minLevel)));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
presetSpinner.setSelection(0);
equalizer.usePreset(-1);
applyEqualizer();
}
}
}