summaryrefslogtreecommitdiffstats
path: root/src/org/cyanogenmod/audiofx/eq/EqContainerView.java
diff options
context:
space:
mode:
authorRoman Birg <roman@cyngn.com>2016-08-29 16:26:56 -0700
committerGerrit Code Review <gerrit@cyanogenmod.org>2016-08-29 16:26:56 -0700
commit33b5c82b68ecf8c18f284214b65db0c2e80589ce (patch)
tree41741e034f2057289f485f49761ebe6bc2135532 /src/org/cyanogenmod/audiofx/eq/EqContainerView.java
parent10fc11011278db3da38e3d28f729887426c1c3a1 (diff)
parent71e5da3c38e5a7e79d5c1f94a13f239cc7ca7458 (diff)
downloadandroid_packages_apps_AudioFX-33b5c82b68ecf8c18f284214b65db0c2e80589ce.tar.gz
android_packages_apps_AudioFX-33b5c82b68ecf8c18f284214b65db0c2e80589ce.tar.bz2
android_packages_apps_AudioFX-33b5c82b68ecf8c18f284214b65db0c2e80589ce.zip
Merge "AudioFX: finish rename; persist process" into cm-13.0
Diffstat (limited to 'src/org/cyanogenmod/audiofx/eq/EqContainerView.java')
-rw-r--r--src/org/cyanogenmod/audiofx/eq/EqContainerView.java533
1 files changed, 533 insertions, 0 deletions
diff --git a/src/org/cyanogenmod/audiofx/eq/EqContainerView.java b/src/org/cyanogenmod/audiofx/eq/EqContainerView.java
new file mode 100644
index 0000000..39146da
--- /dev/null
+++ b/src/org/cyanogenmod/audiofx/eq/EqContainerView.java
@@ -0,0 +1,533 @@
+/*
+ * Copyright (C) 2016 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 org.cyanogenmod.audiofx.eq;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.DashPathEffect;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Vibrator;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewPropertyAnimator;
+import android.view.ViewTreeObserver;
+import android.widget.CheckBox;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import org.cyanogenmod.audiofx.R;
+import org.cyanogenmod.audiofx.activity.EqualizerManager;
+import org.cyanogenmod.audiofx.activity.MasterConfigControl;
+import org.cyanogenmod.audiofx.activity.StateCallbacks;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class EqContainerView extends FrameLayout
+ implements StateCallbacks.EqUpdatedCallback, StateCallbacks.EqControlStateCallback {
+
+ private static final String TAG = EqContainerView.class.getSimpleName();
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private int mWidth;
+ private int mHeight;
+ private MasterConfigControl mConfig;
+ private EqualizerManager mEqManager;
+ private List<EqBandInfo> mBandInfo;
+ private List<EqBarView> mBarViews;
+ private List<Integer> mSelectedBands;
+
+ private CheckBox mLockBox;
+ private ImageView mRenameControl;
+ private ImageView mRemoveControl;
+ private ImageView mSaveControl;
+ private ViewGroup mControls;
+ private boolean mControlsVisible;
+
+ private boolean mSaveVisible;
+ private boolean mRemoveVisible;
+ private boolean mRenameVisible;
+ private boolean mUnlockVisible;
+
+ private int mSelectedBandColor;
+ private boolean mFirstLayout = true;
+
+ private Paint mTextPaint;
+ private Paint mFreqPaint;
+ private Paint mSelectedFreqPaint;
+ private Paint mCenterLinePaint;
+ private Path mDashPath;
+
+ private Handler mHandler;
+
+ private Runnable mVibrateRunnable = new Runnable() {
+ @Override
+ public void run() {
+ Vibrator v = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
+ v.vibrate(30);
+ }
+ };
+
+ private int mPaddingTop;
+ private int mPaddingBottom;
+ private int mBarWidth;
+ private int mBarSeparation;
+ private int mBarBottomGrabSpacePadding;
+
+ public void stopListening() {
+ for (EqBarView barView : mBarViews) {
+ barView.setTag(null);
+ mConfig.getCallbacks().removeEqUpdatedCallback(barView);
+ }
+ mConfig.getCallbacks().removeEqUpdatedCallback(this);
+ }
+
+ public void startListening() {
+ for (int i = 0; i < mBandInfo.size(); i++) {
+
+ final EqBarView eqBarView = mBarViews.get(i);
+ eqBarView.setTag(mBandInfo.get(i));
+ mConfig.getCallbacks().addEqUpdatedCallback(eqBarView);
+ }
+ mConfig.getCallbacks().addEqUpdatedCallback(this);
+ }
+
+ public static class EqBandInfo {
+ public int mIndex;
+
+ public String mFreq;
+ public String mDb;
+ public EqBarView mBar;
+ }
+
+ public EqContainerView(Context context) {
+ super(context);
+ init();
+ }
+
+ public EqContainerView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ public EqContainerView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init();
+ }
+
+ private void init() {
+ setLayerType(LAYER_TYPE_HARDWARE, null);
+
+ mHandler = new Handler();
+
+ final Resources r = getResources();
+
+ mBarWidth = r.getDimensionPixelSize(R.dimen.eq_bar_width);
+ mBarSeparation = r.getDimensionPixelSize(R.dimen.separator_width);
+
+ mBarBottomGrabSpacePadding = r.getDimensionPixelSize(R.dimen.eq_bar_bottom_grab_space);
+ int freqTextSize = r.getDimensionPixelSize(R.dimen.eq_label_text_size);
+ int selectedBoxTextSize = r.getDimensionPixelSize(R.dimen.eq_selected_box_height);
+
+ int extraTopSpace = r.getDimensionPixelSize(R.dimen.eq_bar_top_padding);
+
+ mPaddingTop = selectedBoxTextSize + extraTopSpace;
+ mPaddingBottom = selectedBoxTextSize + mBarBottomGrabSpacePadding;
+
+ mConfig = MasterConfigControl.getInstance(mContext);
+ mEqManager = mConfig.getEqualizerManager();
+
+ mBarViews = new ArrayList<>();
+ mBandInfo = new ArrayList<>();
+ mSelectedBands = new ArrayList<>();
+
+ setWillNotDraw(false);
+
+ mSelectedBandColor = r.getColor(R.color.band_bar_color_selected);
+
+ mTextPaint = new Paint();
+ mTextPaint.setAntiAlias(true);
+ mTextPaint.setColor(Color.WHITE);
+ mTextPaint.setTextAlign(Paint.Align.CENTER);
+ mTextPaint.setElegantTextHeight(true);
+ mTextPaint.setTextSize(selectedBoxTextSize);
+
+ mFreqPaint = new Paint();
+ mFreqPaint.setAntiAlias(true);
+ mFreqPaint.setColor(Color.WHITE);
+ mFreqPaint.setTextAlign(Paint.Align.CENTER);
+ mFreqPaint.setTextSize(freqTextSize);
+
+ mSelectedFreqPaint = new Paint(mFreqPaint);
+ mSelectedFreqPaint.setAntiAlias(true);
+ mSelectedFreqPaint.setTextSize(selectedBoxTextSize);
+
+ mCenterLinePaint = new Paint();
+ mCenterLinePaint.setColor(Color.WHITE);
+ mCenterLinePaint.setAntiAlias(true);
+ mCenterLinePaint.setPathEffect(new DashPathEffect(new float[]{6, 6}, 0));
+ mCenterLinePaint.setStyle(Paint.Style.STROKE);
+ mCenterLinePaint.setAntiAlias(true);
+
+ getViewTreeObserver().addOnGlobalLayoutListener(
+ new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ generateAndAddBars();
+ }
+ });
+ }
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ return true;
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ mControls = (ViewGroup) findViewById(R.id.eq_controls);
+
+ mLockBox = (CheckBox) findViewById(R.id.lock);
+ mLockBox.setOnCheckedChangeListener(mEqManager.getLockChangeListener());
+
+ mRenameControl = (ImageView) findViewById(R.id.rename);
+ mRemoveControl = (ImageView) findViewById(R.id.remove);
+ mSaveControl = (ImageView) findViewById(R.id.save);
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ if (DEBUG) Log.d(TAG, "onAttachedToWindow()");
+ super.onAttachedToWindow();
+
+ mConfig.getCallbacks().addEqControlStateCallback(this);
+ onPresetChanged(mEqManager.getCurrentPresetIndex()); // update initial state
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ if (DEBUG) Log.d(TAG, "onDetachedFromWindow()");
+ mConfig.getCallbacks().removeEqControlStateCallback(this);
+ super.onDetachedFromWindow();
+ }
+
+ @Override
+ public boolean shouldDelayChildPressedState() {
+ return false;
+ }
+
+ private void generateAndAddBars() {
+ if (mFirstLayout) {
+ mFirstLayout = false;
+ mBarViews.clear();
+
+ for (int i = 0; i < mEqManager.getNumBands(); i++) {
+ final EqBandInfo band = new EqBandInfo();
+ band.mIndex = i;
+ mBandInfo.add(band);
+
+ final EqBarView bar = new EqBarView(mContext);
+ band.mBar = bar;
+ bar.setTag(band);
+ bar.setOnTouchListener(new OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ if (mEqManager.isEqualizerLocked()) {
+ return false;
+ }
+ switch (event.getActionMasked()) {
+
+ case MotionEvent.ACTION_DOWN:
+ startBarInteraction(bar);
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ stopBarInteraction(bar);
+ break;
+ }
+
+ return false;
+ }
+ });
+
+ // set correct initial alpha
+ if (i % 2 == 0) {
+ bar.setAlpha(0.6f);
+ } else {
+ bar.setAlpha(0.8f);
+ }
+ bar.setBackgroundColor(Color.WHITE);
+ bar.setElevation(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2,
+ getResources().getDisplayMetrics()));
+
+ addView(bar, getFrameParams(i));
+ bar.setParentHeight(mHeight, getTop());
+
+ final float freq = mEqManager.getCenterFreq(i);
+ String frequencyText = String.format(freq < 1000 ? "%.0f" : "%.0fk",
+ freq < 1000 ? freq : freq / 1000);
+ band.mFreq = frequencyText;
+ mBarViews.add(bar);
+ }
+ updateSelectedBands();
+ } else {
+ for (EqBarView barView : mBarViews) {
+ barView.setParentHeight(mHeight, getTop());
+ }
+ }
+ }
+
+ public EqBarView startTouchingBarUnder(MotionEvent event) {
+ EqBarView foundBar = findBar(event.getX(), event.getY(), mBarViews);
+ if (foundBar != null) {
+ foundBar.updateHeight();
+
+ foundBar.startInteraction(event.getRawX(), event.getRawY());
+ startBarInteraction(foundBar);
+ }
+ return foundBar;
+ }
+
+ public void startBarInteraction(EqBarView bar) {
+ setControlsVisible(false, false);
+ EqBandInfo band = (EqBandInfo) bar.getTag();
+ mSelectedBands.add(band.mIndex);
+ updateSelectedBands();
+ AsyncTask.execute(mVibrateRunnable);
+ }
+
+ public void stopBarInteraction(EqBarView bar) {
+ EqBandInfo band = (EqBandInfo) bar.getTag();
+ mSelectedBands.remove((Integer) band.mIndex);
+ updateSelectedBands();
+ setControlsVisible(mControlsVisible, true);
+ }
+
+ private EqBarView findBar(float x, float y, List<EqBarView> targets) {
+ final int count = targets.size();
+ for (int i = 0; i < count; i++) {
+ final EqBarView target = targets.get(i);
+ if (target.getRight() > x && target.getTop() < y
+ && target.getBottom() > y && target.getLeft() < x) {
+ return target;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ mWidth = w;
+ mHeight = h - mPaddingTop - mPaddingBottom;
+ generateAndAddBars();
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ //---------------------------------------------------
+
+ if (mFirstLayout)
+ return;
+
+ int dashY = bottom - mPaddingBottom - (mHeight / 2);
+
+ final int widthOfBars = (mEqManager.getNumBands() * mBarWidth)
+ + ((mEqManager.getNumBands() - 1) * mBarSeparation);
+ final int freeSpace = mWidth - widthOfBars;
+
+ int mCurLeft = (freeSpace / 2);
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final View child = getChildAt(i);
+
+ if (child instanceof EqBarView) {
+ final int childWidth = child.getMeasuredWidth();
+ final int childHeight = child.getMeasuredHeight();
+
+ int l = mCurLeft;
+ int r = l + mBarWidth;
+
+ mCurLeft += mBarWidth + mBarSeparation;
+
+ if (((EqBarView) child).isUserInteracting()) {
+ l -= childWidth / 4;
+ r += childWidth / 4;
+ }
+
+ final int layoutTop = top + mHeight - childHeight + mPaddingTop;
+ final int layoutBottom = layoutTop + childHeight
+ + mPaddingBottom - (mPaddingBottom - mBarBottomGrabSpacePadding);
+ child.layout(l, layoutTop, r, layoutBottom);
+ }
+ }
+
+ if (changed || mDashPath == null) {
+ mDashPath = new Path();
+ mDashPath.reset();
+ mDashPath.moveTo(freeSpace / 2, dashY);
+ mDashPath.lineTo(widthOfBars + (freeSpace / 2), dashY);
+ }
+
+ mControls.layout(
+ right - mControls.getMeasuredWidth() - mControls.getPaddingLeft(),
+ top + mControls.getPaddingTop(),
+ right - mControls.getPaddingRight(),
+ top + mControls.getMeasuredHeight() + mControls.getPaddingTop()
+ + mControls.getPaddingBottom()
+ );
+ }
+
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ canvas.drawPath(mDashPath, mCenterLinePaint);
+
+ for (int i = 0; i < mBandInfo.size(); i++) {
+ EqBandInfo info = mBandInfo.get(i);
+
+ final float x = info.mBar.getX() + (info.mBar.getWidth() / 2);
+ final boolean userInteracting = info.mBar.isUserInteracting();
+ if (userInteracting) {
+ canvas.drawText(
+ info.mDb,
+ x,
+ info.mBar.getY() - (mTextPaint.getTextSize() / 2),
+ mTextPaint);
+ }
+
+ Paint drawPaint = userInteracting ? mSelectedFreqPaint : mFreqPaint;
+
+ canvas.drawText(info.mFreq, x,
+ info.mBar.getBottom() + drawPaint.getTextSize(),
+ drawPaint);
+ }
+ }
+
+ private void updateSelectedBands() {
+ for (int i = 0; i < mEqManager.getNumBands(); i++) {
+ EqBandInfo tag = mBandInfo.get(i);
+ final EqBarView bar = (EqBarView) findViewWithTag(tag);
+ if (bar != null) {
+ final ViewPropertyAnimator barAnimation = bar.animate().withLayer();
+ if (mSelectedBands.isEmpty()) {
+ if (i % 2 == 0) {
+ barAnimation.alpha(0.6f);
+ } else {
+ barAnimation.alpha(0.8f);
+ }
+ } else if (mSelectedBands.contains(i)) {
+ barAnimation.alpha(1f);
+ bar.setBackgroundColor(mSelectedBandColor);
+ } else {
+ barAnimation.alpha(0.40f);
+ }
+ }
+ }
+ }
+
+ private FrameLayout.LayoutParams getFrameParams(int index) {
+ int width = getResources().getDimensionPixelSize(R.dimen.eq_bar_width);
+ int height = Math.round((1 - mEqManager.projectY(mEqManager.getLevel(index))) * mHeight);
+ FrameLayout.LayoutParams ll = new FrameLayout.LayoutParams(width, height);
+ ll.gravity = Gravity.TOP;
+ return ll;
+ }
+
+ @Override
+ public void onBandLevelChange(int band, float dB, boolean fromSystem) {
+ if (mFirstLayout) return;
+ mBandInfo.get(band).mDb = dB != 0 ? String.format("%+1.1f", dB) : "0.0";
+ invalidate();
+ }
+
+ @Override
+ public void onPresetChanged(int newPresetIndex) {
+ updateEqState();
+ if (mEqManager.isUserPreset()) {
+ mLockBox.setChecked(mEqManager.isEqualizerLocked());
+ }
+ }
+
+ @Override
+ public void updateEqState(boolean saveVisible, boolean removeVisible,
+ boolean renameVisible, boolean unlockVisible) {
+ mControlsVisible = mEqManager.isUserPreset() || mEqManager.isCustomPreset();
+ mSaveVisible = saveVisible;
+ mRemoveVisible = removeVisible;
+ mRenameVisible = renameVisible;
+ mUnlockVisible = unlockVisible;
+ updateEqState();
+ }
+
+ public void updateEqState() {
+ setControlsVisible(mControlsVisible && mSelectedBands.isEmpty(), false);
+
+ animateControl(mLockBox, mUnlockVisible);
+ animateControl(mRemoveControl, mRemoveVisible);
+ animateControl(mRenameControl, mRenameVisible);
+ animateControl(mSaveControl, mSaveVisible);
+ }
+
+ private void animateControl(final View v, boolean visible) {
+ if (visible) {
+ v.setVisibility(View.VISIBLE);
+ v.animate()
+ .alpha(1f)
+ .setDuration(350)
+ .withEndAction(null);
+ } else {
+ v.animate()
+ .alpha(0f)
+ .setDuration(350)
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ v.setVisibility(View.INVISIBLE);
+ }
+ });
+ }
+ }
+
+ @Override
+ public void onPresetsChanged() {
+ }
+
+ public void setControlsVisible(boolean visible, boolean keepChange) {
+ if (keepChange) {
+ mControlsVisible = visible;
+ }
+
+ if (mControls != null) {
+ animateControl(mControls, visible);
+ }
+ }
+
+}