diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:52 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:52 -0800 |
commit | c308fa194a7b899cc7706429c3ea44b09966a2b1 (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /src/com | |
parent | 81ddfee16eb3d64ede19eeb8d5d9ca2e7d692ec0 (diff) | |
download | SoundRecorder-c308fa194a7b899cc7706429c3ea44b09966a2b1.tar.gz |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'src/com')
-rw-r--r-- | src/com/android/soundrecorder/Recorder.java | 243 | ||||
-rw-r--r-- | src/com/android/soundrecorder/SoundRecorder.java | 830 | ||||
-rw-r--r-- | src/com/android/soundrecorder/VUMeter.java | 90 |
3 files changed, 0 insertions, 1163 deletions
diff --git a/src/com/android/soundrecorder/Recorder.java b/src/com/android/soundrecorder/Recorder.java deleted file mode 100644 index 5fe41b0..0000000 --- a/src/com/android/soundrecorder/Recorder.java +++ /dev/null @@ -1,243 +0,0 @@ -package com.android.soundrecorder; - -import java.io.File; -import java.io.IOException; - -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 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) { - 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; - } - mRecorder.start(); - - 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); - } -} diff --git a/src/com/android/soundrecorder/SoundRecorder.java b/src/com/android/soundrecorder/SoundRecorder.java deleted file mode 100644 index 2338362..0000000 --- a/src/com/android/soundrecorder/SoundRecorder.java +++ /dev/null @@ -1,830 +0,0 @@ -package com.android.soundrecorder; - -import java.io.File; -import java.text.SimpleDateFormat; -import java.util.Date; - -import android.app.Activity; -import android.app.AlertDialog; -import android.content.ContentResolver; -import android.content.ContentValues; -import android.content.Intent; -import android.content.Context; -import android.content.IntentFilter; -import android.content.BroadcastReceiver; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.database.Cursor; -import android.media.MediaRecorder; -import android.net.Uri; -import android.os.Bundle; -import android.os.Environment; -import android.os.Handler; -import android.os.PowerManager; -import android.os.StatFs; -import android.os.PowerManager.WakeLock; -import android.provider.MediaStore; -import android.util.Log; -import android.view.KeyEvent; -import android.view.View; -import android.widget.Button; -import android.widget.ImageButton; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.ProgressBar; -import android.widget.TextView; - -/** - * Calculates remaining recording time based on available disk space and - * optionally a maximum recording file size. - * - * The reason why this is not trivial is that the file grows in blocks - * every few seconds or so, while we want a smooth countdown. - */ - -class RemainingTimeCalculator { - public static final int UNKNOWN_LIMIT = 0; - public static final int FILE_SIZE_LIMIT = 1; - public static final int DISK_SPACE_LIMIT = 2; - - // which of the two limits we will hit (or have fit) first - private int mCurrentLowerLimit = UNKNOWN_LIMIT; - - private File mSDCardDirectory; - - // State for tracking file size of recording. - private File mRecordingFile; - private long mMaxBytes; - - // Rate at which the file grows - private int mBytesPerSecond; - - // time at which number of free blocks last changed - private long mBlocksChangedTime; - // number of available blocks at that time - private long mLastBlocks; - - // time at which the size of the file has last changed - private long mFileSizeChangedTime; - // size of the file at that time - private long mLastFileSize; - - public RemainingTimeCalculator() { - mSDCardDirectory = Environment.getExternalStorageDirectory(); - } - - /** - * If called, the calculator will return the minimum of two estimates: - * how long until we run out of disk space and how long until the file - * reaches the specified size. - * - * @param file the file to watch - * @param maxBytes the limit - */ - - public void setFileSizeLimit(File file, long maxBytes) { - mRecordingFile = file; - mMaxBytes = maxBytes; - } - - /** - * Resets the interpolation. - */ - public void reset() { - mCurrentLowerLimit = UNKNOWN_LIMIT; - mBlocksChangedTime = -1; - mFileSizeChangedTime = -1; - } - - /** - * Returns how long (in seconds) we can continue recording. - */ - public long timeRemaining() { - // Calculate how long we can record based on free disk space - - StatFs fs = new StatFs(mSDCardDirectory.getAbsolutePath()); - long blocks = fs.getAvailableBlocks(); - long blockSize = fs.getBlockSize(); - long now = System.currentTimeMillis(); - - if (mBlocksChangedTime == -1 || blocks != mLastBlocks) { - mBlocksChangedTime = now; - mLastBlocks = blocks; - } - - /* The calculation below always leaves one free block, since free space - in the block we're currently writing to is not added. This - last block might get nibbled when we close and flush the file, but - we won't run out of disk. */ - - // at mBlocksChangedTime we had this much time - long result = mLastBlocks*blockSize/mBytesPerSecond; - // so now we have this much time - result -= (now - mBlocksChangedTime)/1000; - - if (mRecordingFile == null) { - mCurrentLowerLimit = DISK_SPACE_LIMIT; - return result; - } - - // If we have a recording file set, we calculate a second estimate - // based on how long it will take us to reach mMaxBytes. - - mRecordingFile = new File(mRecordingFile.getAbsolutePath()); - long fileSize = mRecordingFile.length(); - if (mFileSizeChangedTime == -1 || fileSize != mLastFileSize) { - mFileSizeChangedTime = now; - mLastFileSize = fileSize; - } - - long result2 = (mMaxBytes - fileSize)/mBytesPerSecond; - result2 -= (now - mFileSizeChangedTime)/1000; - result2 -= 1; // just for safety - - mCurrentLowerLimit = result < result2 - ? DISK_SPACE_LIMIT : FILE_SIZE_LIMIT; - - return Math.min(result, result2); - } - - /** - * Indicates which limit we will hit (or have hit) first, by returning one - * of FILE_SIZE_LIMIT or DISK_SPACE_LIMIT or UNKNOWN_LIMIT. We need this to - * display the correct message to the user when we hit one of the limits. - */ - public int currentLowerLimit() { - return mCurrentLowerLimit; - } - - /** - * Is there any point of trying to start recording? - */ - public boolean diskSpaceAvailable() { - StatFs fs = new StatFs(mSDCardDirectory.getAbsolutePath()); - // keep one free block - return fs.getAvailableBlocks() > 1; - } - - /** - * Sets the bit rate used in the interpolation. - * - * @param bitRate the bit rate to set in bits/sec. - */ - public void setBitRate(int bitRate) { - mBytesPerSecond = bitRate/8; - } -} - -public class SoundRecorder extends Activity - implements Button.OnClickListener, Recorder.OnStateChangedListener { - static final String TAG = "SoundRecorder"; - static final String STATE_FILE_NAME = "soundrecorder.state"; - static final String RECORDER_STATE_KEY = "recorder_state"; - static final String SAMPLE_INTERRUPTED_KEY = "sample_interrupted"; - static final String MAX_FILE_SIZE_KEY = "max_file_size"; - - static final String AUDIO_3GPP = "audio/3gpp"; - static final String AUDIO_AMR = "audio/amr"; - static final String AUDIO_ANY = "audio/*"; - - static final int BITRATE_AMR = 5900; // bits/sec - static final int BITRATE_3GPP = 5900; - - WakeLock mWakeLock; - String mRequestedType = AUDIO_ANY; - Recorder mRecorder; - boolean mSampleInterrupted = false; - String mErrorUiMessage = null; // Some error messages are displayed in the UI, - // not a dialog. This happens when a recording - // is interrupted for some reason. - - long mMaxFileSize = -1; // can be specified in the intent - RemainingTimeCalculator mRemainingTimeCalculator; - - String mTimerFormat; - final Handler mHandler = new Handler(); - Runnable mUpdateTimer = new Runnable() { - public void run() { updateTimerView(); } - }; - - ImageButton mRecordButton; - ImageButton mPlayButton; - ImageButton mStopButton; - - ImageView mStateLED; - TextView mStateMessage1; - TextView mStateMessage2; - ProgressBar mStateProgressBar; - TextView mTimerView; - - LinearLayout mExitButtons; - Button mAcceptButton; - Button mDiscardButton; - VUMeter mVUMeter; - private BroadcastReceiver mSDCardMountEventReceiver = null; - - @Override - public void onCreate(Bundle icycle) { - super.onCreate(icycle); - - Intent i = getIntent(); - if (i != null) { - String s = i.getType(); - if (AUDIO_AMR.equals(s) || AUDIO_3GPP.equals(s) || AUDIO_ANY.equals(s)) { - mRequestedType = s; - } else if (s != null) { - // we only support amr and 3gpp formats right now - setResult(RESULT_CANCELED); - finish(); - return; - } - - final String EXTRA_MAX_BYTES - = android.provider.MediaStore.Audio.Media.EXTRA_MAX_BYTES; - mMaxFileSize = i.getLongExtra(EXTRA_MAX_BYTES, -1); - } - - if (AUDIO_ANY.equals(mRequestedType)) { - mRequestedType = AUDIO_3GPP; - } - - setContentView(R.layout.main); - - mRecorder = new Recorder(); - mRecorder.setOnStateChangedListener(this); - mRemainingTimeCalculator = new RemainingTimeCalculator(); - - PowerManager pm - = (PowerManager) getSystemService(Context.POWER_SERVICE); - mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, - "SoundRecorder"); - - initResourceRefs(); - - setResult(RESULT_CANCELED); - registerExternalStorageListener(); - if (icycle != null) { - Bundle recorderState = icycle.getBundle(RECORDER_STATE_KEY); - if (recorderState != null) { - mRecorder.restoreState(recorderState); - mSampleInterrupted = recorderState.getBoolean(SAMPLE_INTERRUPTED_KEY, false); - mMaxFileSize = recorderState.getLong(MAX_FILE_SIZE_KEY, -1); - } - } - - updateUi(); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - - setContentView(R.layout.main); - initResourceRefs(); - updateUi(); - } - - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - - if (mRecorder.sampleLength() == 0) - return; - - Bundle recorderState = new Bundle(); - - mRecorder.saveState(recorderState); - recorderState.putBoolean(SAMPLE_INTERRUPTED_KEY, mSampleInterrupted); - recorderState.putLong(MAX_FILE_SIZE_KEY, mMaxFileSize); - - outState.putBundle(RECORDER_STATE_KEY, recorderState); - } - - /* - * Whenever the UI is re-created (due f.ex. to orientation change) we have - * to reinitialize references to the views. - */ - private void initResourceRefs() { - mRecordButton = (ImageButton) findViewById(R.id.recordButton); - mPlayButton = (ImageButton) findViewById(R.id.playButton); - mStopButton = (ImageButton) findViewById(R.id.stopButton); - - mStateLED = (ImageView) findViewById(R.id.stateLED); - mStateMessage1 = (TextView) findViewById(R.id.stateMessage1); - mStateMessage2 = (TextView) findViewById(R.id.stateMessage2); - mStateProgressBar = (ProgressBar) findViewById(R.id.stateProgressBar); - mTimerView = (TextView) findViewById(R.id.timerView); - - mExitButtons = (LinearLayout) findViewById(R.id.exitButtons); - mAcceptButton = (Button) findViewById(R.id.acceptButton); - mDiscardButton = (Button) findViewById(R.id.discardButton); - mVUMeter = (VUMeter) findViewById(R.id.uvMeter); - - mRecordButton.setOnClickListener(this); - mPlayButton.setOnClickListener(this); - mStopButton.setOnClickListener(this); - mAcceptButton.setOnClickListener(this); - mDiscardButton.setOnClickListener(this); - - mTimerFormat = getResources().getString(R.string.timer_format); - - mVUMeter.setRecorder(mRecorder); - } - - /* - * Handle the buttons. - */ - public void onClick(View button) { - if (!button.isEnabled()) - return; - - switch (button.getId()) { - case R.id.recordButton: - mRemainingTimeCalculator.reset(); - if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - mSampleInterrupted = true; - mErrorUiMessage = getResources().getString(R.string.insert_sd_card); - updateUi(); - } else if (!mRemainingTimeCalculator.diskSpaceAvailable()) { - mSampleInterrupted = true; - mErrorUiMessage = getResources().getString(R.string.storage_is_full); - updateUi(); - } else { - if (AUDIO_AMR.equals(mRequestedType)) { - mRemainingTimeCalculator.setBitRate(BITRATE_AMR); - mRecorder.startRecording(MediaRecorder.OutputFormat.RAW_AMR, ".amr"); - } else if (AUDIO_3GPP.equals(mRequestedType)) { - mRemainingTimeCalculator.setBitRate(BITRATE_3GPP); - mRecorder.startRecording(MediaRecorder.OutputFormat.THREE_GPP, ".3gpp"); - } else { - throw new IllegalArgumentException("Invalid output file type requested"); - } - - if (mMaxFileSize != -1) { - mRemainingTimeCalculator.setFileSizeLimit( - mRecorder.sampleFile(), mMaxFileSize); - } - } - break; - case R.id.playButton: - mRecorder.startPlayback(); - break; - case R.id.stopButton: - mRecorder.stop(); - break; - case R.id.acceptButton: - mRecorder.stop(); - saveSample(); - finish(); - break; - case R.id.discardButton: - mRecorder.delete(); - finish(); - break; - } - } - - /* - * Handle the "back" hardware key. - */ - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_BACK) { - switch (mRecorder.state()) { - case Recorder.IDLE_STATE: - if (mRecorder.sampleLength() > 0) - saveSample(); - finish(); - break; - case Recorder.PLAYING_STATE: - mRecorder.stop(); - saveSample(); - break; - case Recorder.RECORDING_STATE: - mRecorder.clear(); - break; - } - return true; - } else { - return super.onKeyDown(keyCode, event); - } - } - - @Override - public void onStop() { - mRecorder.stop(); - super.onStop(); - } - - @Override - protected void onPause() { - mSampleInterrupted = mRecorder.state() == Recorder.RECORDING_STATE; - mRecorder.stop(); - - super.onPause(); - } - - /* - * If we have just recorded a smaple, this adds it to the media data base - * and sets the result to the sample's URI. - */ - private void saveSample() { - if (mRecorder.sampleLength() == 0) - return; - Uri uri = null; - try { - uri = this.addToMediaDB(mRecorder.sampleFile()); - } catch(UnsupportedOperationException ex) { // Database manipulation failure - return; - } - if (uri == null) { - return; - } - setResult(RESULT_OK, new Intent().setData(uri)); - } - - /* - * Called on destroy to unregister the SD card mount event receiver. - */ - @Override - public void onDestroy() { - if (mSDCardMountEventReceiver != null) { - unregisterReceiver(mSDCardMountEventReceiver); - mSDCardMountEventReceiver = null; - } - super.onDestroy(); - } - - /* - * Registers an intent to listen for ACTION_MEDIA_EJECT/ACTION_MEDIA_MOUNTED - * notifications. - */ - private void registerExternalStorageListener() { - if (mSDCardMountEventReceiver == null) { - mSDCardMountEventReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (action.equals(Intent.ACTION_MEDIA_EJECT)) { - mRecorder.delete(); - } else if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) { - mSampleInterrupted = false; - updateUi(); - } - } - }; - IntentFilter iFilter = new IntentFilter(); - iFilter.addAction(Intent.ACTION_MEDIA_EJECT); - iFilter.addAction(Intent.ACTION_MEDIA_MOUNTED); - iFilter.addDataScheme("file"); - registerReceiver(mSDCardMountEventReceiver, iFilter); - } - } - - /* - * A simple utility to do a query into the databases. - */ - private Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { - try { - ContentResolver resolver = getContentResolver(); - if (resolver == null) { - return null; - } - return resolver.query(uri, projection, selection, selectionArgs, sortOrder); - } catch (UnsupportedOperationException ex) { - return null; - } - } - - /* - * Add the given audioId to the playlist with the given playlistId; and maintain the - * play_order in the playlist. - */ - private void addToPlaylist(ContentResolver resolver, int audioId, long playlistId) { - String[] cols = new String[] { - "count(*)" - }; - Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId); - Cursor cur = resolver.query(uri, cols, null, null, null); - cur.moveToFirst(); - final int base = cur.getInt(0); - cur.close(); - ContentValues values = new ContentValues(); - values.put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, Integer.valueOf(base + audioId)); - values.put(MediaStore.Audio.Playlists.Members.AUDIO_ID, audioId); - resolver.insert(uri, values); - } - - /* - * Obtain the id for the default play list from the audio_playlists table. - */ - private int getPlaylistId(Resources res) { - Uri uri = MediaStore.Audio.Playlists.getContentUri("external"); - final String[] ids = new String[] { MediaStore.Audio.Playlists._ID }; - final String where = MediaStore.Audio.Playlists.NAME + "=?"; - final String[] args = new String[] { res.getString(R.string.audio_db_playlist_name) }; - Cursor cursor = query(uri, ids, where, args, null); - if (cursor == null) { - Log.v(TAG, "query returns null"); - } - int id = -1; - if (cursor != null) { - cursor.moveToFirst(); - if (!cursor.isAfterLast()) { - id = cursor.getInt(0); - } - } - cursor.close(); - return id; - } - - /* - * Create a playlist with the given default playlist name, if no such playlist exists. - */ - private Uri createPlaylist(Resources res, ContentResolver resolver) { - ContentValues cv = new ContentValues(); - cv.put(MediaStore.Audio.Playlists.NAME, res.getString(R.string.audio_db_playlist_name)); - Uri uri = resolver.insert(MediaStore.Audio.Playlists.getContentUri("external"), cv); - if (uri == null) { - new AlertDialog.Builder(this) - .setTitle(R.string.app_name) - .setMessage(R.string.error_mediadb_new_record) - .setPositiveButton(R.string.button_ok, null) - .setCancelable(false) - .show(); - } - return uri; - } - - /* - * Adds file and returns content uri. - */ - private Uri addToMediaDB(File file) { - Resources res = getResources(); - ContentValues cv = new ContentValues(); - long current = System.currentTimeMillis(); - long modDate = file.lastModified(); - Date date = new Date(current); - SimpleDateFormat formatter = new SimpleDateFormat( - res.getString(R.string.audio_db_title_format)); - String title = formatter.format(date); - - // Lets label the recorded audio file as NON-MUSIC so that the file - // won't be displayed automatically, except for in the playlist. - cv.put(MediaStore.Audio.Media.IS_MUSIC, "0"); - - cv.put(MediaStore.Audio.Media.TITLE, title); - cv.put(MediaStore.Audio.Media.DATA, file.getAbsolutePath()); - cv.put(MediaStore.Audio.Media.DATE_ADDED, (int) (current / 1000)); - cv.put(MediaStore.Audio.Media.DATE_MODIFIED, (int) (modDate / 1000)); - cv.put(MediaStore.Audio.Media.MIME_TYPE, mRequestedType); - cv.put(MediaStore.Audio.Media.ARTIST, - res.getString(R.string.audio_db_artist_name)); - cv.put(MediaStore.Audio.Media.ALBUM, - res.getString(R.string.audio_db_album_name)); - Log.d(TAG, "Inserting audio record: " + cv.toString()); - ContentResolver resolver = getContentResolver(); - Uri base = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; - Log.d(TAG, "ContentURI: " + base); - Uri result = resolver.insert(base, cv); - if (result == null) { - new AlertDialog.Builder(this) - .setTitle(R.string.app_name) - .setMessage(R.string.error_mediadb_new_record) - .setPositiveButton(R.string.button_ok, null) - .setCancelable(false) - .show(); - return null; - } - if (getPlaylistId(res) == -1) { - createPlaylist(res, resolver); - } - int audioId = Integer.valueOf(result.getLastPathSegment()); - addToPlaylist(resolver, audioId, getPlaylistId(res)); - - // Notify those applications such as Music listening to the - // scanner events that a recorded audio file just created. - sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, result)); - return result; - } - - /** - * Update the big MM:SS timer. If we are in playback, also update the - * progress bar. - */ - private void updateTimerView() { - Resources res = getResources(); - int state = mRecorder.state(); - - boolean ongoing = state == Recorder.RECORDING_STATE || state == Recorder.PLAYING_STATE; - - long time = ongoing ? mRecorder.progress() : mRecorder.sampleLength(); - String timeStr = String.format(mTimerFormat, time/60, time%60); - mTimerView.setText(timeStr); - - if (state == Recorder.PLAYING_STATE) { - mStateProgressBar.setProgress((int)(100*time/mRecorder.sampleLength())); - } else if (state == Recorder.RECORDING_STATE) { - updateTimeRemaining(); - } - - if (ongoing) - mHandler.postDelayed(mUpdateTimer, 1000); - } - - /* - * Called when we're in recording state. Find out how much longer we can - * go on recording. If it's under 5 minutes, we display a count-down in - * the UI. If we've run out of time, stop the recording. - */ - private void updateTimeRemaining() { - long t = mRemainingTimeCalculator.timeRemaining(); - - if (t <= 0) { - mSampleInterrupted = true; - - int limit = mRemainingTimeCalculator.currentLowerLimit(); - switch (limit) { - case RemainingTimeCalculator.DISK_SPACE_LIMIT: - mErrorUiMessage - = getResources().getString(R.string.storage_is_full); - break; - case RemainingTimeCalculator.FILE_SIZE_LIMIT: - mErrorUiMessage - = getResources().getString(R.string.max_length_reached); - break; - default: - mErrorUiMessage = null; - break; - } - - mRecorder.stop(); - return; - } - - Resources res = getResources(); - String timeStr = ""; - - if (t < 60) - timeStr = String.format(res.getString(R.string.sec_available), t); - else if (t < 540) - timeStr = String.format(res.getString(R.string.min_available), t/60 + 1); - - mStateMessage1.setText(timeStr); - } - - /** - * Shows/hides the appropriate child views for the new state. - */ - private void updateUi() { - Resources res = getResources(); - - switch (mRecorder.state()) { - case Recorder.IDLE_STATE: - if (mRecorder.sampleLength() == 0) { - mRecordButton.setEnabled(true); - mRecordButton.setFocusable(true); - mPlayButton.setEnabled(false); - mPlayButton.setFocusable(false); - mStopButton.setEnabled(false); - mStopButton.setFocusable(false); - mRecordButton.requestFocus(); - - mStateMessage1.setVisibility(View.INVISIBLE); - mStateLED.setVisibility(View.VISIBLE); - mStateLED.setImageResource(R.drawable.idle_led); - mStateMessage2.setVisibility(View.VISIBLE); - mStateMessage2.setText(res.getString(R.string.press_record)); - - mExitButtons.setVisibility(View.INVISIBLE); - mVUMeter.setVisibility(View.VISIBLE); - - mStateProgressBar.setVisibility(View.INVISIBLE); - - setTitle(res.getString(R.string.record_your_message)); - } else { - mRecordButton.setEnabled(true); - mRecordButton.setFocusable(true); - mPlayButton.setEnabled(true); - mPlayButton.setFocusable(true); - mStopButton.setEnabled(false); - mStopButton.setFocusable(false); - - mStateMessage1.setVisibility(View.INVISIBLE); - mStateLED.setVisibility(View.INVISIBLE); - mStateMessage2.setVisibility(View.INVISIBLE); - - mExitButtons.setVisibility(View.VISIBLE); - mVUMeter.setVisibility(View.INVISIBLE); - - mStateProgressBar.setVisibility(View.INVISIBLE); - - setTitle(res.getString(R.string.message_recorded)); - } - - if (mSampleInterrupted) { - mStateMessage2.setVisibility(View.VISIBLE); - mStateMessage2.setText(res.getString(R.string.recording_stopped)); - mStateLED.setImageResource(R.drawable.idle_led); - mStateLED.setVisibility(View.VISIBLE); - } - - if (mErrorUiMessage != null) { - mStateMessage1.setText(mErrorUiMessage); - mStateMessage1.setVisibility(View.VISIBLE); - } - - break; - case Recorder.RECORDING_STATE: - mRecordButton.setEnabled(false); - mRecordButton.setFocusable(false); - mPlayButton.setEnabled(false); - mPlayButton.setFocusable(false); - mStopButton.setEnabled(true); - mStopButton.setFocusable(true); - - mStateMessage1.setVisibility(View.VISIBLE); - mStateLED.setVisibility(View.VISIBLE); - mStateLED.setImageResource(R.drawable.recording_led); - mStateMessage2.setVisibility(View.VISIBLE); - mStateMessage2.setText(res.getString(R.string.recording)); - - mExitButtons.setVisibility(View.INVISIBLE); - mVUMeter.setVisibility(View.VISIBLE); - - mStateProgressBar.setVisibility(View.INVISIBLE); - - setTitle(res.getString(R.string.record_your_message)); - - break; - - case Recorder.PLAYING_STATE: - mRecordButton.setEnabled(true); - mRecordButton.setFocusable(true); - mPlayButton.setEnabled(false); - mPlayButton.setFocusable(false); - mStopButton.setEnabled(true); - mStopButton.setFocusable(true); - - mStateMessage1.setVisibility(View.INVISIBLE); - mStateLED.setVisibility(View.INVISIBLE); - mStateMessage2.setVisibility(View.INVISIBLE); - - mExitButtons.setVisibility(View.VISIBLE); - mVUMeter.setVisibility(View.INVISIBLE); - - mStateProgressBar.setVisibility(View.VISIBLE); - - setTitle(res.getString(R.string.review_message)); - - break; - } - - updateTimerView(); - mVUMeter.invalidate(); - } - - /* - * Called when Recorder changed it's state. - */ - public void onStateChanged(int state) { - if (state == Recorder.PLAYING_STATE || state == Recorder.RECORDING_STATE) { - mSampleInterrupted = false; - mErrorUiMessage = null; - } - - if (state == Recorder.RECORDING_STATE) { - mWakeLock.acquire(); // we don't want to go to sleep while recording - } else { - if (mWakeLock.isHeld()) - mWakeLock.release(); - } - - updateUi(); - } - - /* - * Called when MediaPlayer encounters an error. - */ - public void onError(int error) { - Resources res = getResources(); - - String message = null; - switch (error) { - case Recorder.SDCARD_ACCESS_ERROR: - message = res.getString(R.string.error_sdcard_access); - break; - case Recorder.INTERNAL_ERROR: - message = res.getString(R.string.error_app_internal); - break; - } - if (message != null) { - new AlertDialog.Builder(this) - .setTitle(R.string.app_name) - .setMessage(message) - .setPositiveButton(R.string.button_ok, null) - .setCancelable(false) - .show(); - } - } -} diff --git a/src/com/android/soundrecorder/VUMeter.java b/src/com/android/soundrecorder/VUMeter.java deleted file mode 100644 index 6aee87d..0000000 --- a/src/com/android/soundrecorder/VUMeter.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.android.soundrecorder; - -import java.util.Map; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import android.view.View; - -public class VUMeter extends View { - static final float PIVOT_RADIUS = 3.5f; - static final float PIVOT_Y_OFFSET = 10f; - static final float SHADOW_OFFSET = 2.0f; - static final float DROPOFF_STEP = 0.18f; - static final float SURGE_STEP = 0.35f; - static final long ANIMATION_INTERVAL = 70; - - Paint mPaint, mShadow; - float mCurrentAngle; - - Recorder mRecorder; - - public VUMeter(Context context) { - super(context); - init(context); - } - - public VUMeter(Context context, AttributeSet attrs) { - super(context, attrs); - init(context); - } - - void init(Context context) { - Drawable background = context.getResources().getDrawable(R.drawable.vumeter); - setBackgroundDrawable(background); - - mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mPaint.setColor(Color.WHITE); - mShadow = new Paint(Paint.ANTI_ALIAS_FLAG); - mShadow.setColor(Color.argb(60, 0, 0, 0)); - - mRecorder = null; - - mCurrentAngle = 0; - } - - public void setRecorder(Recorder recorder) { - mRecorder = recorder; - invalidate(); - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - - final float minAngle = (float)Math.PI/8; - final float maxAngle = (float)Math.PI*7/8; - - float angle = minAngle; - if (mRecorder != null) - angle += (float)(maxAngle - minAngle)*mRecorder.getMaxAmplitude()/32768; - - if (angle > mCurrentAngle) - mCurrentAngle = angle; - else - mCurrentAngle = Math.max(angle, mCurrentAngle - DROPOFF_STEP); - - mCurrentAngle = Math.min(maxAngle, mCurrentAngle); - - float w = getWidth(); - float h = getHeight(); - float pivotX = w/2; - float pivotY = h - PIVOT_RADIUS - PIVOT_Y_OFFSET; - float l = h*4/5; - float sin = (float) Math.sin(mCurrentAngle); - float cos = (float) Math.cos(mCurrentAngle); - float x0 = pivotX - l*cos; - float y0 = pivotY - l*sin; - canvas.drawLine(x0 + SHADOW_OFFSET, y0 + SHADOW_OFFSET, pivotX + SHADOW_OFFSET, pivotY + SHADOW_OFFSET, mShadow); - canvas.drawCircle(pivotX + SHADOW_OFFSET, pivotY + SHADOW_OFFSET, PIVOT_RADIUS, mShadow); - canvas.drawLine(x0, y0, pivotX, pivotY, mPaint); - canvas.drawCircle(pivotX, pivotY, PIVOT_RADIUS, mPaint); - - if (mRecorder != null && mRecorder.state() == Recorder.RECORDING_STATE) - postInvalidateDelayed(ANIMATION_INTERVAL); - } -} |