blob: b9654cd8bf5e75aa7135326bee07108e6c79b232 [file] [log] [blame]
/*
* Copyright (C) 2011 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.android.soundrecorder;
import java.io.File;
import java.io.IOException;
import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
public class Recorder implements OnCompletionListener, OnErrorListener {
static final String SAMPLE_PREFIX = "recording";
static final String SAMPLE_PATH_KEY = "sample_path";
static final String SAMPLE_LENGTH_KEY = "sample_length";
public static final int IDLE_STATE = 0;
public static final int RECORDING_STATE = 1;
public static final int PLAYING_STATE = 2;
int mState = IDLE_STATE;
public static final int NO_ERROR = 0;
public static final int SDCARD_ACCESS_ERROR = 1;
public static final int INTERNAL_ERROR = 2;
public static final int IN_CALL_RECORD_ERROR = 3;
public interface OnStateChangedListener {
public void onStateChanged(int state);
public void onError(int error);
}
OnStateChangedListener mOnStateChangedListener = null;
long mSampleStart = 0; // time at which latest record or play operation started
int mSampleLength = 0; // length of current sample
File mSampleFile = null;
MediaRecorder mRecorder = null;
MediaPlayer mPlayer = null;
public Recorder() {
}
public void saveState(Bundle recorderState) {
recorderState.putString(SAMPLE_PATH_KEY, mSampleFile.getAbsolutePath());
recorderState.putInt(SAMPLE_LENGTH_KEY, mSampleLength);
}
public int getMaxAmplitude() {
if (mState != RECORDING_STATE)
return 0;
return mRecorder.getMaxAmplitude();
}
public void restoreState(Bundle recorderState) {
String samplePath = recorderState.getString(SAMPLE_PATH_KEY);
if (samplePath == null)
return;
int sampleLength = recorderState.getInt(SAMPLE_LENGTH_KEY, -1);
if (sampleLength == -1)
return;
File file = new File(samplePath);
if (!file.exists())
return;
if (mSampleFile != null
&& mSampleFile.getAbsolutePath().compareTo(file.getAbsolutePath()) == 0)
return;
delete();
mSampleFile = file;
mSampleLength = sampleLength;
signalStateChanged(IDLE_STATE);
}
public void setOnStateChangedListener(OnStateChangedListener listener) {
mOnStateChangedListener = listener;
}
public int state() {
return mState;
}
public int progress() {
if (mState == RECORDING_STATE || mState == PLAYING_STATE)
return (int) ((System.currentTimeMillis() - mSampleStart)/1000);
return 0;
}
public int sampleLength() {
return mSampleLength;
}
public File sampleFile() {
return mSampleFile;
}
/**
* Resets the recorder state. If a sample was recorded, the file is deleted.
*/
public void delete() {
stop();
if (mSampleFile != null)
mSampleFile.delete();
mSampleFile = null;
mSampleLength = 0;
signalStateChanged(IDLE_STATE);
}
/**
* Resets the recorder state. If a sample was recorded, the file is left on disk and will
* be reused for a new recording.
*/
public void clear() {
stop();
mSampleLength = 0;
signalStateChanged(IDLE_STATE);
}
public void startRecording(int outputfileformat, String extension, Context context) {
stop();
if (mSampleFile == null) {
File sampleDir = Environment.getExternalStorageDirectory();
if (!sampleDir.canWrite()) // Workaround for broken sdcard support on the device.
sampleDir = new File("/sdcard/sdcard");
try {
mSampleFile = File.createTempFile(SAMPLE_PREFIX, extension, sampleDir);
} catch (IOException e) {
setError(SDCARD_ACCESS_ERROR);
return;
}
}
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(outputfileformat);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mRecorder.setOutputFile(mSampleFile.getAbsolutePath());
// Handle IOException
try {
mRecorder.prepare();
} catch(IOException exception) {
setError(INTERNAL_ERROR);
mRecorder.reset();
mRecorder.release();
mRecorder = null;
return;
}
// Handle RuntimeException if the recording couldn't start
try {
mRecorder.start();
} catch (RuntimeException exception) {
AudioManager audioMngr = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
boolean isInCall = ((audioMngr.getMode() == AudioManager.MODE_IN_CALL) ||
(audioMngr.getMode() == AudioManager.MODE_IN_COMMUNICATION));
if (isInCall) {
setError(IN_CALL_RECORD_ERROR);
} else {
setError(INTERNAL_ERROR);
}
mRecorder.reset();
mRecorder.release();
mRecorder = null;
return;
}
mSampleStart = System.currentTimeMillis();
setState(RECORDING_STATE);
}
public void stopRecording() {
if (mRecorder == null)
return;
mRecorder.stop();
mRecorder.release();
mRecorder = null;
mSampleLength = (int)( (System.currentTimeMillis() - mSampleStart)/1000 );
setState(IDLE_STATE);
}
public void startPlayback() {
stop();
mPlayer = new MediaPlayer();
try {
mPlayer.setDataSource(mSampleFile.getAbsolutePath());
mPlayer.setOnCompletionListener(this);
mPlayer.setOnErrorListener(this);
mPlayer.prepare();
mPlayer.start();
} catch (IllegalArgumentException e) {
setError(INTERNAL_ERROR);
mPlayer = null;
return;
} catch (IOException e) {
setError(SDCARD_ACCESS_ERROR);
mPlayer = null;
return;
}
mSampleStart = System.currentTimeMillis();
setState(PLAYING_STATE);
}
public void stopPlayback() {
if (mPlayer == null) // we were not in playback
return;
mPlayer.stop();
mPlayer.release();
mPlayer = null;
setState(IDLE_STATE);
}
public void stop() {
stopRecording();
stopPlayback();
}
public boolean onError(MediaPlayer mp, int what, int extra) {
stop();
setError(SDCARD_ACCESS_ERROR);
return true;
}
public void onCompletion(MediaPlayer mp) {
stop();
}
private void setState(int state) {
if (state == mState)
return;
mState = state;
signalStateChanged(mState);
}
private void signalStateChanged(int state) {
if (mOnStateChangedListener != null)
mOnStateChangedListener.onStateChanged(state);
}
private void setError(int error) {
if (mOnStateChangedListener != null)
mOnStateChangedListener.onError(error);
}
}