blob: 6388fec56305542f1b0968a4b92b1a2d11cc34fe [file] [log] [blame]
/*
* Copyright (C) 2012 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.camera;
import android.annotation.TargetApi;
import android.content.Context;
import android.media.AudioManager;
import android.media.MediaActionSound;
import android.media.SoundPool;
import android.util.Log;
import com.android.gallery3d.R;
import com.android.gallery3d.common.ApiHelper;
/*
* This class controls the sound playback according to the API level.
*/
public class SoundClips {
// Sound actions.
public static final int FOCUS_COMPLETE = 0;
public static final int START_VIDEO_RECORDING = 1;
public static final int STOP_VIDEO_RECORDING = 2;
public interface Player {
public void release();
public void play(int action);
}
public static Player getPlayer(Context context) {
if (ApiHelper.HAS_MEDIA_ACTION_SOUND) {
return new MediaActionSoundPlayer();
} else {
return new SoundPoolPlayer(context);
}
}
/**
* This class implements SoundClips.Player using MediaActionSound,
* which exists since API level 16.
*/
@TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN)
private static class MediaActionSoundPlayer implements Player {
private static final String TAG = "MediaActionSoundPlayer";
private MediaActionSound mSound;
@Override
public void release() {
if (mSound != null) {
mSound.release();
mSound = null;
}
}
public MediaActionSoundPlayer() {
mSound = new MediaActionSound();
mSound.load(MediaActionSound.START_VIDEO_RECORDING);
mSound.load(MediaActionSound.STOP_VIDEO_RECORDING);
mSound.load(MediaActionSound.FOCUS_COMPLETE);
}
@Override
public synchronized void play(int action) {
switch(action) {
case FOCUS_COMPLETE:
mSound.play(MediaActionSound.FOCUS_COMPLETE);
break;
case START_VIDEO_RECORDING:
mSound.play(MediaActionSound.START_VIDEO_RECORDING);
break;
case STOP_VIDEO_RECORDING:
mSound.play(MediaActionSound.STOP_VIDEO_RECORDING);
break;
default:
Log.w(TAG, "Unrecognized action:" + action);
}
}
}
/**
* This class implements SoundClips.Player using SoundPool, which
* exists since API level 1.
*/
private static class SoundPoolPlayer implements
Player, SoundPool.OnLoadCompleteListener {
private static final String TAG = "SoundPoolPlayer";
private static final int NUM_SOUND_STREAMS = 1;
private static final int[] SOUND_RES = { // Soundtrack res IDs.
R.raw.focus_complete,
R.raw.video_record
};
// ID returned by load() should be non-zero.
private static final int ID_NOT_LOADED = 0;
// Maps a sound action to the id;
private final int[] mSoundRes = {0, 1, 1};
// Store the context for lazy loading.
private Context mContext;
// mSoundPool is created every time load() is called and cleared every
// time release() is called.
private SoundPool mSoundPool;
// Sound ID of each sound resources. Given when the sound is loaded.
private final int[] mSoundIDs;
private final boolean[] mSoundIDReady;
private int mSoundIDToPlay;
public SoundPoolPlayer(Context context) {
mContext = context;
int audioType = ApiHelper.getIntFieldIfExists(AudioManager.class,
"STREAM_SYSTEM_ENFORCED", null, AudioManager.STREAM_RING);
mSoundIDToPlay = ID_NOT_LOADED;
mSoundPool = new SoundPool(NUM_SOUND_STREAMS, audioType, 0);
mSoundPool.setOnLoadCompleteListener(this);
mSoundIDs = new int[SOUND_RES.length];
mSoundIDReady = new boolean[SOUND_RES.length];
for (int i = 0; i < SOUND_RES.length; i++) {
mSoundIDs[i] = mSoundPool.load(mContext, SOUND_RES[i], 1);
mSoundIDReady[i] = false;
}
}
@Override
public synchronized void release() {
if (mSoundPool != null) {
mSoundPool.release();
mSoundPool = null;
}
}
@Override
public synchronized void play(int action) {
if (action < 0 || action >= mSoundRes.length) {
Log.e(TAG, "Resource ID not found for action:" + action + " in play().");
return;
}
int index = mSoundRes[action];
if (mSoundIDs[index] == ID_NOT_LOADED) {
// Not loaded yet, load first and then play when the loading is complete.
mSoundIDs[index] = mSoundPool.load(mContext, SOUND_RES[index], 1);
mSoundIDToPlay = mSoundIDs[index];
} else if (!mSoundIDReady[index]) {
// Loading and not ready yet.
mSoundIDToPlay = mSoundIDs[index];
} else {
mSoundPool.play(mSoundIDs[index], 1f, 1f, 0, 0, 1f);
}
}
@Override
public void onLoadComplete(SoundPool pool, int soundID, int status) {
if (status != 0) {
Log.e(TAG, "loading sound tracks failed (status=" + status + ")");
for (int i = 0; i < mSoundIDs.length; i++ ) {
if (mSoundIDs[i] == soundID) {
mSoundIDs[i] = ID_NOT_LOADED;
break;
}
}
return;
}
for (int i = 0; i < mSoundIDs.length; i++ ) {
if (mSoundIDs[i] == soundID) {
mSoundIDReady[i] = true;
break;
}
}
if (soundID == mSoundIDToPlay) {
mSoundIDToPlay = ID_NOT_LOADED;
mSoundPool.play(soundID, 1f, 1f, 0, 0, 1f);
}
}
}
}