blob: e8501f5e8cbb804add91eab670e74e85dcd19541 [file] [log] [blame]
/*
* Copyright 2017 The Android Open Source 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.google.sample.oboe.manualtest;
import android.app.Activity;
import android.content.Context;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.Toast;
import java.io.IOException;
import java.util.ArrayList;
/**
* Base class for other Activities.
*/
abstract class TestAudioActivity extends Activity {
public static final String TAG = "TestOboe";
protected static final int FADER_THRESHOLD_MAX = 1000;
public static final int STATE_OPEN = 0;
public static final int STATE_STARTED = 1;
public static final int STATE_PAUSED = 2;
public static final int STATE_STOPPED = 3;
public static final int STATE_CLOSED = 4;
public static final int COLOR_ACTIVE = 0xFFD0D0A0;
public static final int COLOR_IDLE = 0xFFD0D0D0;
private int mState = STATE_CLOSED;
protected String audioManagerSampleRate;
protected int audioManagerFramesPerBurst;
protected ArrayList<StreamContext> mStreamContexts;
private Button mOpenButton;
private Button mStartButton;
private Button mPauseButton;
private Button mStopButton;
private Button mCloseButton;
private MyStreamSniffer mStreamSniffer;
private CheckBox mCallbackReturnStopBox;
public static class StreamContext {
StreamConfigurationView configurationView;
AudioStreamTester tester;
}
// Periodically query the status of the stream.
protected class MyStreamSniffer {
public static final int SNIFFER_UPDATE_PERIOD_MSEC = 150;
public static final int SNIFFER_UPDATE_DELAY_MSEC = 300;
private Handler mHandler;
// Display status info for the stream.
private Runnable runnableCode = new Runnable() {
@Override
public void run() {
for (StreamContext streamContext : mStreamContexts) {
// Handler runs this on the main UI thread.
AudioStreamBase.StreamStatus status = streamContext.tester.getCurrentAudioStream().getStreamStatus();
int framesPerBurst = streamContext.tester.getCurrentAudioStream().getFramesPerBurst();
final String msg = status.dump(framesPerBurst);
mStreamContexts.get(0).configurationView.setStatusText(msg);
updateStreamDisplay();
}
// Repeat this runnable code block again.
mHandler.postDelayed(runnableCode, SNIFFER_UPDATE_PERIOD_MSEC);
}
};
private void startStreamSniffer() {
stopStreamSniffer();
mHandler = new Handler(Looper.getMainLooper());
// Start the initial runnable task by posting through the handler
mHandler.postDelayed(runnableCode, SNIFFER_UPDATE_DELAY_MSEC);
}
private void stopStreamSniffer() {
if (mHandler != null) {
mHandler.removeCallbacks(runnableCode);
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
inflateActivity();
findAudioCommon();
}
protected abstract void inflateActivity();
void updateStreamDisplay() {
}
@Override
protected void onDestroy() {
try {
for (StreamContext streamContext : mStreamContexts) {
streamContext.tester.stop();
}
} catch (IOException e) {
e.printStackTrace();
}
mState = STATE_CLOSED;
super.onDestroy();
}
int getState() {
return mState;
}
protected void updateEnabledWidgets() {
if (mOpenButton != null) {
mOpenButton.setBackgroundColor(mState == STATE_OPEN ? COLOR_ACTIVE : COLOR_IDLE);
mStartButton.setBackgroundColor(mState == STATE_STARTED ? COLOR_ACTIVE : COLOR_IDLE);
mPauseButton.setBackgroundColor(mState == STATE_PAUSED ? COLOR_ACTIVE : COLOR_IDLE);
mStopButton.setBackgroundColor(mState == STATE_STOPPED ? COLOR_ACTIVE : COLOR_IDLE);
mCloseButton.setBackgroundColor(mState == STATE_CLOSED ? COLOR_ACTIVE : COLOR_IDLE);
}
setConfigViewsEnabled(mState == STATE_CLOSED);
}
private void setConfigViewsEnabled(boolean b) {
for (StreamContext streamContext : mStreamContexts) {
streamContext.configurationView.setChildrenEnabled(b);
}
}
abstract boolean isOutput();
public AudioOutputTester addAudioOutputTester() {
StreamContext streamContext = new StreamContext();
streamContext.configurationView =(StreamConfigurationView)
findViewById(R.id.outputStreamConfiguration);
if (streamContext.configurationView == null) {
streamContext.configurationView =(StreamConfigurationView)
findViewById(R.id.streamConfiguration);
}
streamContext.configurationView.setOutput(true);
streamContext.tester = AudioOutputTester.getInstance();
mStreamContexts.add(streamContext);
return (AudioOutputTester) streamContext.tester;
}
public AudioInputTester addAudioInputTester() {
StreamContext streamContext = new StreamContext();
streamContext.configurationView =(StreamConfigurationView)
findViewById(R.id.inputStreamConfiguration);
if (streamContext.configurationView == null) {
streamContext.configurationView =(StreamConfigurationView)
findViewById(R.id.streamConfiguration);
}
streamContext.configurationView.setOutput(false);
streamContext.tester = AudioInputTester.getInstance();
mStreamContexts.add(streamContext);
return (AudioInputTester) streamContext.tester;
}
void updateStreamConfigurationViews() {
for (StreamContext streamContext : mStreamContexts) {
streamContext.configurationView.updateDisplay();
}
}
protected void findAudioCommon() {
mOpenButton = (Button) findViewById(R.id.button_open);
if (mOpenButton != null) {
mStartButton = (Button) findViewById(R.id.button_start);
mPauseButton = (Button) findViewById(R.id.button_pause);
mStopButton = (Button) findViewById(R.id.button_stop);
mCloseButton = (Button) findViewById(R.id.button_close);
}
mStreamContexts = new ArrayList<StreamContext>();
queryNativeAudioParameters();
mCallbackReturnStopBox = (CheckBox) findViewById(R.id.callbackReturnStop);
if (mCallbackReturnStopBox != null) {
mCallbackReturnStopBox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
OboeAudioStream.setCallbackReturnStop(mCallbackReturnStopBox.isChecked());
}
});
}
OboeAudioStream.setCallbackReturnStop(false);
mStreamSniffer = new MyStreamSniffer();
}
private void queryNativeAudioParameters() {
AudioManager myAudioMgr = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
audioManagerSampleRate = myAudioMgr.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
String audioManagerFramesPerBurstText = myAudioMgr.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
audioManagerFramesPerBurst = Integer.parseInt(audioManagerFramesPerBurstText);
}
abstract public void setupEffects(int sessionId);
protected void showToast(String message) {
Toast.makeText(this, "Error: " + message, Toast.LENGTH_SHORT).show();
}
@Override
protected void onStop() {
Log.i(TAG, "onStop() called so stopping audio =========================");
stopAudio();
closeAudio();
super.onStop();
}
public void openAudio(View view) {
openAudio();
}
public void startAudio(View view) {
Log.i(TAG, "startAudio() called =======================================");
startAudio();
}
public void stopAudio(View view) {
stopAudio();
}
public void pauseAudio(View view) {
pauseAudio();
}
public void closeAudio(View view) {
closeAudio();
}
public void openAudio() {
try {
for (StreamContext streamContext : mStreamContexts) {
StreamConfigurationView configView = streamContext.configurationView;
StreamConfiguration requestedConfig = configView.getRequestedConfiguration();
requestedConfig.setFramesPerBurst(audioManagerFramesPerBurst);
streamContext.tester.open(requestedConfig, configView.getActualConfiguration());
mState = STATE_OPEN;
int sessionId = configView.getActualConfiguration().getSessionId();
if (sessionId > 0) {
setupEffects(sessionId);
}
configView.updateDisplay();
}
updateEnabledWidgets();
mStreamSniffer.startStreamSniffer();
} catch (Exception e) {
e.printStackTrace();
showToast(e.getMessage());
}
}
public void startAudio() {
try {
mState = STATE_STARTED;
for (StreamContext streamContext : mStreamContexts) {
StreamConfigurationView configView = streamContext.configurationView;
streamContext.tester.start();
configView.updateDisplay();
}
updateEnabledWidgets();
} catch (Exception e) {
e.printStackTrace();
showToast(e.getMessage());
}
}
public void pauseAudio() {
try {
for (StreamContext streamContext : mStreamContexts) {
streamContext.tester.pause();
}
mState = STATE_PAUSED;
updateEnabledWidgets();
} catch (Exception e) {
e.printStackTrace();
showToast(e.getMessage());
}
}
public void stopAudio() {
try {
for (StreamContext streamContext : mStreamContexts) {
streamContext.tester.stop();
}
mState = STATE_STOPPED;
updateEnabledWidgets();
} catch (Exception e) {
e.printStackTrace();
showToast(e.getMessage());
}
}
public void closeAudio() {
mStreamSniffer.stopStreamSniffer();
for (StreamContext streamContext : mStreamContexts) {
streamContext.tester.close();
}
mState = STATE_CLOSED;
updateEnabledWidgets();
}
}