1/*
2 * Copyright (C) 2009 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
17package com.android.effectstest;
18
19import android.app.Activity;
20import android.content.Context;
21import android.content.Intent;
22import android.os.Bundle;
23import android.util.Log;
24import android.view.KeyEvent;
25import android.view.Menu;
26import android.view.View.OnClickListener;
27import android.view.View;
28import android.view.ViewGroup;
29import android.widget.Button;
30import android.widget.TextView;
31import android.widget.EditText;
32import android.widget.SeekBar;
33import android.widget.ToggleButton;
34import android.widget.CompoundButton;
35import android.widget.CompoundButton.OnCheckedChangeListener;
36import java.nio.ByteOrder;
37import java.nio.ByteBuffer;
38import java.util.HashMap;
39import java.util.Map;
40
41import android.media.audiofx.BassBoost;
42import android.media.audiofx.AudioEffect;
43
44public class BassBoostTest extends Activity implements OnCheckedChangeListener {
45
46    private final static String TAG = "BassBoostTest";
47
48    private static int NUM_PARAMS = 1;
49
50    private EffectParameter mStrength;
51    private BassBoost mBassBoost = null;
52    ToggleButton mOnOffButton;
53    ToggleButton mReleaseButton;
54    EditText mSessionText;
55    static int sSession = 0;
56    EffectListner mEffectListener = new EffectListner();
57    private static HashMap<Integer, BassBoost> sInstances = new HashMap<Integer, BassBoost>(10);
58    String mSettings = "";
59
60    public BassBoostTest() {
61        Log.d(TAG, "contructor");
62    }
63
64    @Override
65    public void onCreate(Bundle icicle) {
66        super.onCreate(icicle);
67
68        SeekBar seekBar;
69        TextView textView;
70
71        setContentView(R.layout.bassboosttest);
72
73        mSessionText = (EditText) findViewById(R.id.sessionEdit);
74        mSessionText.setOnKeyListener(mSessionKeyListener);
75
76        mSessionText.setText(Integer.toString(sSession));
77
78        mReleaseButton = (ToggleButton)findViewById(R.id.bbReleaseButton);
79        mOnOffButton = (ToggleButton)findViewById(R.id.bassboostOnOff);
80
81        getEffect(sSession);
82
83        if (mBassBoost != null) {
84            mReleaseButton.setOnCheckedChangeListener(this);
85            mOnOffButton.setOnCheckedChangeListener(this);
86
87            textView = (TextView)findViewById(R.id.bbStrengthMin);
88            textView.setText("0");
89            textView = (TextView)findViewById(R.id.bbStrengthMax);
90            textView.setText("1000");
91            seekBar = (SeekBar)findViewById(R.id.bbStrengthSeekBar);
92            textView = (TextView)findViewById(R.id.bbStrengthValue);
93            mStrength = new BassBoostParam(mBassBoost, 0, 1000, seekBar, textView);
94            seekBar.setOnSeekBarChangeListener(mStrength);
95            mStrength.setEnabled(mBassBoost.getStrengthSupported());
96        }
97    }
98
99    @Override
100    public void onResume() {
101        super.onResume();
102    }
103
104    @Override
105    public void onPause() {
106        super.onPause();
107    }
108
109    private View.OnKeyListener mSessionKeyListener
110    = new View.OnKeyListener() {
111        public boolean onKey(View v, int keyCode, KeyEvent event) {
112            Log.d(TAG, "onKey() keyCode: "+keyCode+" event.getAction(): "+event.getAction());
113            if (event.getAction() == KeyEvent.ACTION_DOWN) {
114                switch (keyCode) {
115                    case KeyEvent.KEYCODE_DPAD_CENTER:
116                    case KeyEvent.KEYCODE_ENTER:
117                        try {
118                            sSession = Integer.parseInt(mSessionText.getText().toString());
119                            getEffect(sSession);
120                            if (mBassBoost != null) {
121                                mStrength.setEffect(mBassBoost);
122                                mStrength.setEnabled(mBassBoost.getStrengthSupported());
123                            }
124                        } catch (NumberFormatException e) {
125                            Log.d(TAG, "Invalid session #: "+mSessionText.getText().toString());
126                        }
127                        return true;
128                }
129            }
130            return false;
131        }
132    };
133
134    // OnCheckedChangeListener
135    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
136        if (buttonView.getId() == R.id.bassboostOnOff) {
137            if (mBassBoost != null) {
138                mBassBoost.setEnabled(isChecked);
139                mStrength.updateDisplay();
140            }
141        }
142        if (buttonView.getId() == R.id.bbReleaseButton) {
143            if (isChecked) {
144                if (mBassBoost == null) {
145                    getEffect(sSession);
146                    if (mBassBoost != null) {
147                        mStrength.setEffect(mBassBoost);
148                        mStrength.setEnabled(mBassBoost.getStrengthSupported());
149                    }
150                }
151            } else {
152                if (mBassBoost != null) {
153                    mStrength.setEnabled(false);
154                    putEffect(sSession);
155                }
156            }
157        }
158    }
159
160    private class BassBoostParam extends EffectParameter {
161        private BassBoost mBassBoost;
162
163        public BassBoostParam(BassBoost bassboost, int min, int max, SeekBar seekBar, TextView textView) {
164            super (min, max, seekBar, textView, "o/oo");
165
166            mBassBoost = bassboost;
167            updateDisplay();
168        }
169
170        @Override
171        public void setParameter(Integer value) {
172            if (mBassBoost != null) {
173                mBassBoost.setStrength(value.shortValue());
174            }
175        }
176
177        @Override
178        public Integer getParameter() {
179            if (mBassBoost != null) {
180                return new Integer(mBassBoost.getRoundedStrength());
181            }
182            return new Integer(0);
183        }
184
185        @Override
186        public void setEffect(Object effect) {
187            mBassBoost = (BassBoost)effect;
188        }
189    }
190
191    public class EffectListner implements AudioEffect.OnEnableStatusChangeListener,
192        AudioEffect.OnControlStatusChangeListener, AudioEffect.OnParameterChangeListener
193   {
194        public EffectListner() {
195        }
196        public void onEnableStatusChange(AudioEffect effect, boolean enabled) {
197            Log.d(TAG,"onEnableStatusChange: "+ enabled);
198        }
199        public void onControlStatusChange(AudioEffect effect, boolean controlGranted) {
200            Log.d(TAG,"onControlStatusChange: "+ controlGranted);
201        }
202        public void onParameterChange(AudioEffect effect, int status, byte[] param, byte[] value) {
203            int p = byteArrayToInt(param, 0);
204            short v = byteArrayToShort(value, 0);
205
206            Log.d(TAG,"onParameterChange, status: "+status+" p: "+p+" v: "+v);
207        }
208
209        private int byteArrayToInt(byte[] valueBuf, int offset) {
210            ByteBuffer converter = ByteBuffer.wrap(valueBuf);
211            converter.order(ByteOrder.nativeOrder());
212            return converter.getInt(offset);
213
214        }
215        private short byteArrayToShort(byte[] valueBuf, int offset) {
216            ByteBuffer converter = ByteBuffer.wrap(valueBuf);
217            converter.order(ByteOrder.nativeOrder());
218            return converter.getShort(offset);
219
220        }
221
222    }
223
224    private void getEffect(int session) {
225        synchronized (sInstances) {
226            if (sInstances.containsKey(session)) {
227                mBassBoost = sInstances.get(session);
228            } else {
229                try{
230                    mBassBoost = new BassBoost(0, session);
231                } catch (IllegalArgumentException e) {
232                    Log.e(TAG,"BassBoost effect not supported");
233                } catch (IllegalStateException e) {
234                    Log.e(TAG,"BassBoost cannot get strength supported");
235                } catch (UnsupportedOperationException e) {
236                    Log.e(TAG,"BassBoost library not loaded");
237                } catch (RuntimeException e) {
238                    Log.e(TAG,"BassBoost effect not found");
239                }
240                sInstances.put(session, mBassBoost);
241            }
242            mReleaseButton.setEnabled(false);
243            mOnOffButton.setEnabled(false);
244
245            if (mBassBoost != null) {
246                if (mSettings != "") {
247                    mBassBoost.setProperties(new BassBoost.Settings(mSettings));
248                }
249                mBassBoost.setEnableStatusListener(mEffectListener);
250                mBassBoost.setControlStatusListener(mEffectListener);
251                mBassBoost.setParameterListener(mEffectListener);
252
253                mReleaseButton.setChecked(true);
254                mReleaseButton.setEnabled(true);
255
256                mOnOffButton.setChecked(mBassBoost.getEnabled());
257                mOnOffButton.setEnabled(true);
258            }
259        }
260    }
261
262    private void putEffect(int session) {
263        mOnOffButton.setChecked(false);
264        mOnOffButton.setEnabled(false);
265        synchronized (sInstances) {
266            if (mBassBoost != null) {
267                mSettings = mBassBoost.getProperties().toString();
268                mBassBoost.release();
269                Log.d(TAG,"BassBoost released");
270                mBassBoost = null;
271                sInstances.remove(session);
272            }
273        }
274    }
275
276}
277