Merge "Move Camera.Sound to a stand-alone class CameraSound." into ics-mr1
This commit is contained in:
@@ -22,12 +22,9 @@ import android.graphics.ImageFormat;
|
|||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.SurfaceTexture;
|
import android.graphics.SurfaceTexture;
|
||||||
import android.media.AudioManager;
|
|
||||||
import android.media.MediaPlayer;
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.SystemProperties;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import android.view.SurfaceHolder;
|
import android.view.SurfaceHolder;
|
||||||
@@ -157,7 +154,6 @@ public class Camera {
|
|||||||
private boolean mOneShot;
|
private boolean mOneShot;
|
||||||
private boolean mWithBuffer;
|
private boolean mWithBuffer;
|
||||||
private boolean mFaceDetectionRunning = false;
|
private boolean mFaceDetectionRunning = false;
|
||||||
private boolean mReleased = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Broadcast Action: A new picture is taken by the camera, and the entry of
|
* Broadcast Action: A new picture is taken by the camera, and the entry of
|
||||||
@@ -322,15 +318,6 @@ public class Camera {
|
|||||||
public final void release() {
|
public final void release() {
|
||||||
native_release();
|
native_release();
|
||||||
mFaceDetectionRunning = false;
|
mFaceDetectionRunning = false;
|
||||||
if (mCameraSoundPlayers != null) {
|
|
||||||
for (CameraSoundPlayer csp: mCameraSoundPlayers) {
|
|
||||||
if (csp != null) {
|
|
||||||
csp.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mCameraSoundPlayers = null;
|
|
||||||
}
|
|
||||||
mReleased = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -3503,194 +3490,4 @@ public class Camera {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>The set of default system sounds for camera actions. Use this with
|
|
||||||
* {@link #playSound} to play an appropriate sound when implementing a
|
|
||||||
* custom still or video recording mechanism through the preview
|
|
||||||
* callbacks.</p>
|
|
||||||
*
|
|
||||||
* <p>There is no need to play sounds when using {@link #takePicture} or
|
|
||||||
* {@link android.media.MediaRecorder} for still images or video,
|
|
||||||
* respectively, as these play their own sounds when needed.</p>
|
|
||||||
*
|
|
||||||
* @see #playSound
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public static class Sound {
|
|
||||||
/**
|
|
||||||
* The sound used by {@link android.hardware.Camera#takePicture} to
|
|
||||||
* indicate still image capture.
|
|
||||||
*/
|
|
||||||
public static final int SHUTTER_CLICK = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A sound to indicate that focusing has completed. Because deciding
|
|
||||||
* when this occurs is application-dependent, this sound is not used by
|
|
||||||
* any methods in the Camera class.
|
|
||||||
*/
|
|
||||||
public static final int FOCUS_COMPLETE = 1;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The sound used by {@link android.media.MediaRecorder#start} to
|
|
||||||
* indicate the start of video recording.
|
|
||||||
*/
|
|
||||||
public static final int START_VIDEO_RECORDING = 2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The sound used by {@link android.media.MediaRecorder#stop} to
|
|
||||||
* indicate the end of video recording.
|
|
||||||
*/
|
|
||||||
public static final int STOP_VIDEO_RECORDING = 3;
|
|
||||||
|
|
||||||
private static final int NUM_SOUNDS = 4;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Play one of the predefined platform sounds for camera actions.</p>
|
|
||||||
*
|
|
||||||
* <p>Use this method to play a platform-specific sound for various camera
|
|
||||||
* actions. The sound playing is done asynchronously, with the same behavior
|
|
||||||
* and content as the sounds played by {@link #takePicture takePicture},
|
|
||||||
* {@link android.media.MediaRecorder#start MediaRecorder.start}, and
|
|
||||||
* {@link android.media.MediaRecorder#stop MediaRecorder.stop}.</p>
|
|
||||||
*
|
|
||||||
* <p>Using this method makes it easy to match the default device sounds
|
|
||||||
* when recording or capturing data through the preview callbacks
|
|
||||||
* ({@link #setPreviewCallback setPreviewCallback},
|
|
||||||
* {@link #setPreviewTexture setPreviewTexture}).</p>
|
|
||||||
*
|
|
||||||
* @param soundId The type of sound to play, selected from the options in
|
|
||||||
* {@link android.hardware.Camera.Sound}
|
|
||||||
* @see android.hardware.Camera.Sound
|
|
||||||
* @see #takePicture
|
|
||||||
* @see android.media.MediaRecorder
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public void playSound(int soundId) {
|
|
||||||
if (mReleased) return;
|
|
||||||
if (mCameraSoundPlayers == null) {
|
|
||||||
mCameraSoundPlayers = new CameraSoundPlayer[Sound.NUM_SOUNDS];
|
|
||||||
}
|
|
||||||
if (mCameraSoundPlayers[soundId] == null) {
|
|
||||||
mCameraSoundPlayers[soundId] = new CameraSoundPlayer(soundId);
|
|
||||||
}
|
|
||||||
mCameraSoundPlayers[soundId].play();
|
|
||||||
}
|
|
||||||
|
|
||||||
private CameraSoundPlayer[] mCameraSoundPlayers;
|
|
||||||
|
|
||||||
private static class CameraSoundPlayer implements Runnable {
|
|
||||||
private int mSoundId;
|
|
||||||
private int mAudioStreamType;
|
|
||||||
private MediaPlayer mPlayer;
|
|
||||||
private Thread mThread;
|
|
||||||
private boolean mExit;
|
|
||||||
private int mPlayCount;
|
|
||||||
|
|
||||||
private static final String mShutterSound =
|
|
||||||
"/system/media/audio/ui/camera_click.ogg";
|
|
||||||
private static final String mFocusSound =
|
|
||||||
"/system/media/audio/ui/camera_focus.ogg";
|
|
||||||
private static final String mVideoStartSound =
|
|
||||||
"/system/media/audio/ui/VideoRecord.ogg";
|
|
||||||
private static final String mVideoStopSound =
|
|
||||||
"/system/media/audio/ui/VideoRecord.ogg";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
String soundFilePath;
|
|
||||||
switch (mSoundId) {
|
|
||||||
case Sound.SHUTTER_CLICK:
|
|
||||||
soundFilePath = mShutterSound;
|
|
||||||
break;
|
|
||||||
case Sound.FOCUS_COMPLETE:
|
|
||||||
soundFilePath = mFocusSound;
|
|
||||||
break;
|
|
||||||
case Sound.START_VIDEO_RECORDING:
|
|
||||||
soundFilePath = mVideoStartSound;
|
|
||||||
break;
|
|
||||||
case Sound.STOP_VIDEO_RECORDING:
|
|
||||||
soundFilePath = mVideoStopSound;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Log.e(TAG, "Unknown sound " + mSoundId + " requested.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mPlayer = new MediaPlayer();
|
|
||||||
try {
|
|
||||||
mPlayer.setAudioStreamType(mAudioStreamType);
|
|
||||||
mPlayer.setDataSource(soundFilePath);
|
|
||||||
mPlayer.setLooping(false);
|
|
||||||
mPlayer.prepare();
|
|
||||||
} catch(IOException e) {
|
|
||||||
Log.e(TAG, "Error setting up sound " + mSoundId, e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while(true) {
|
|
||||||
try {
|
|
||||||
synchronized (this) {
|
|
||||||
while(true) {
|
|
||||||
if (mExit) {
|
|
||||||
return;
|
|
||||||
} else if (mPlayCount <= 0) {
|
|
||||||
wait();
|
|
||||||
} else {
|
|
||||||
mPlayCount--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mPlayer.start();
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "Error playing sound " + mSoundId, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public CameraSoundPlayer(int soundId) {
|
|
||||||
mSoundId = soundId;
|
|
||||||
if (SystemProperties.get("ro.camera.sound.forced", "0").equals("0")) {
|
|
||||||
mAudioStreamType = AudioManager.STREAM_MUSIC;
|
|
||||||
} else {
|
|
||||||
mAudioStreamType = AudioManager.STREAM_SYSTEM_ENFORCED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void play() {
|
|
||||||
if (mThread == null) {
|
|
||||||
mThread = new Thread(this);
|
|
||||||
mThread.start();
|
|
||||||
}
|
|
||||||
synchronized (this) {
|
|
||||||
mPlayCount++;
|
|
||||||
notifyAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void release() {
|
|
||||||
if (mThread != null) {
|
|
||||||
synchronized (this) {
|
|
||||||
mExit = true;
|
|
||||||
notifyAll();
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
mThread.join();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
}
|
|
||||||
mThread = null;
|
|
||||||
}
|
|
||||||
if (mPlayer != null) {
|
|
||||||
mPlayer.release();
|
|
||||||
mPlayer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void finalize() {
|
|
||||||
release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
223
core/java/android/hardware/CameraSound.java
Normal file
223
core/java/android/hardware/CameraSound.java
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
/*
|
||||||
|
* 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 android.hardware;
|
||||||
|
|
||||||
|
import android.media.AudioManager;
|
||||||
|
import android.media.MediaPlayer;
|
||||||
|
import android.os.SystemProperties;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Use this class to play an appropriate sound when implementing a custom
|
||||||
|
* still or video recording mechanism through the preview callbacks.</p>
|
||||||
|
*
|
||||||
|
* <p>There is no need to play sounds when using {@link #android.hardware.Camera#takePicture}
|
||||||
|
* or {@link android.media.MediaRecorder} for still images or video,
|
||||||
|
* respectively, as these play their own sounds when needed.</p>
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public class CameraSound {
|
||||||
|
private static final String TAG = "CameraSound";
|
||||||
|
/**
|
||||||
|
* The sound used by {@link android.hardware.Camera#takePicture} to
|
||||||
|
* indicate still image capture.
|
||||||
|
*/
|
||||||
|
public static final int SHUTTER_CLICK = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A sound to indicate that focusing has completed. Because deciding
|
||||||
|
* when this occurs is application-dependent, this sound is not used by
|
||||||
|
* any methods in the Camera class.
|
||||||
|
*/
|
||||||
|
public static final int FOCUS_COMPLETE = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sound used by {@link android.media.MediaRecorder#start} to
|
||||||
|
* indicate the start of video recording.
|
||||||
|
*/
|
||||||
|
public static final int START_VIDEO_RECORDING = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sound used by {@link android.media.MediaRecorder#stop} to
|
||||||
|
* indicate the end of video recording.
|
||||||
|
*/
|
||||||
|
public static final int STOP_VIDEO_RECORDING = 3;
|
||||||
|
|
||||||
|
private static final int NUM_SOUNDS = 4;
|
||||||
|
private CameraSoundPlayer[] mCameraSoundPlayers;
|
||||||
|
|
||||||
|
public CameraSound() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Play one of the predefined platform sounds for camera actions.</p>
|
||||||
|
*
|
||||||
|
* <p>Use this method to play a platform-specific sound for various camera
|
||||||
|
* actions. The sound playing is done asynchronously, with the same behavior
|
||||||
|
* and content as the sounds played by {@link #takePicture takePicture},
|
||||||
|
* {@link android.media.MediaRecorder#start MediaRecorder.start}, and
|
||||||
|
* {@link android.media.MediaRecorder#stop MediaRecorder.stop}.</p>
|
||||||
|
*
|
||||||
|
* <p>Using this method makes it easy to match the default device sounds
|
||||||
|
* when recording or capturing data through the preview callbacks.</p>
|
||||||
|
*
|
||||||
|
* @param soundId The type of sound to play, selected from SHUTTER_CLICK,
|
||||||
|
* FOCUS_COMPLETE, START_VIDEO_RECORDING, or STOP_VIDEO_RECORDING.
|
||||||
|
* @see android.hardware#takePicture
|
||||||
|
* @see android.media.MediaRecorder
|
||||||
|
* @see #SHUTTER_CLICK
|
||||||
|
* @see #FOCUS_COMPLETE
|
||||||
|
* @see #START_VIDEO_RECORDING
|
||||||
|
* @see #STOP_VIDEO_RECORDING
|
||||||
|
*/
|
||||||
|
public void playSound(int soundId) {
|
||||||
|
if (mCameraSoundPlayers == null) {
|
||||||
|
mCameraSoundPlayers = new CameraSoundPlayer[NUM_SOUNDS];
|
||||||
|
}
|
||||||
|
if (mCameraSoundPlayers[soundId] == null) {
|
||||||
|
mCameraSoundPlayers[soundId] = new CameraSoundPlayer(soundId);
|
||||||
|
}
|
||||||
|
mCameraSoundPlayers[soundId].play();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void release() {
|
||||||
|
if (mCameraSoundPlayers != null) {
|
||||||
|
for (CameraSoundPlayer csp: mCameraSoundPlayers) {
|
||||||
|
if (csp != null) {
|
||||||
|
csp.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mCameraSoundPlayers = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class CameraSoundPlayer implements Runnable {
|
||||||
|
private int mSoundId;
|
||||||
|
private int mAudioStreamType;
|
||||||
|
private MediaPlayer mPlayer;
|
||||||
|
private Thread mThread;
|
||||||
|
private boolean mExit;
|
||||||
|
private int mPlayCount;
|
||||||
|
|
||||||
|
private static final String mShutterSound =
|
||||||
|
"/system/media/audio/ui/camera_click.ogg";
|
||||||
|
private static final String mFocusSound =
|
||||||
|
"/system/media/audio/ui/camera_focus.ogg";
|
||||||
|
private static final String mVideoStartSound =
|
||||||
|
"/system/media/audio/ui/VideoRecord.ogg";
|
||||||
|
private static final String mVideoStopSound =
|
||||||
|
"/system/media/audio/ui/VideoRecord.ogg";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
String soundFilePath;
|
||||||
|
switch (mSoundId) {
|
||||||
|
case SHUTTER_CLICK:
|
||||||
|
soundFilePath = mShutterSound;
|
||||||
|
break;
|
||||||
|
case FOCUS_COMPLETE:
|
||||||
|
soundFilePath = mFocusSound;
|
||||||
|
break;
|
||||||
|
case START_VIDEO_RECORDING:
|
||||||
|
soundFilePath = mVideoStartSound;
|
||||||
|
break;
|
||||||
|
case STOP_VIDEO_RECORDING:
|
||||||
|
soundFilePath = mVideoStopSound;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log.e(TAG, "Unknown sound " + mSoundId + " requested.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mPlayer = new MediaPlayer();
|
||||||
|
try {
|
||||||
|
mPlayer.setAudioStreamType(mAudioStreamType);
|
||||||
|
mPlayer.setDataSource(soundFilePath);
|
||||||
|
mPlayer.setLooping(false);
|
||||||
|
mPlayer.prepare();
|
||||||
|
} catch(IOException e) {
|
||||||
|
Log.e(TAG, "Error setting up sound " + mSoundId, e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
try {
|
||||||
|
synchronized (this) {
|
||||||
|
while(true) {
|
||||||
|
if (mExit) {
|
||||||
|
return;
|
||||||
|
} else if (mPlayCount <= 0) {
|
||||||
|
wait();
|
||||||
|
} else {
|
||||||
|
mPlayCount--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mPlayer.start();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error playing sound " + mSoundId, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public CameraSoundPlayer(int soundId) {
|
||||||
|
mSoundId = soundId;
|
||||||
|
if (SystemProperties.get("ro.camera.sound.forced", "0").equals("0")) {
|
||||||
|
mAudioStreamType = AudioManager.STREAM_MUSIC;
|
||||||
|
} else {
|
||||||
|
mAudioStreamType = AudioManager.STREAM_SYSTEM_ENFORCED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void play() {
|
||||||
|
if (mThread == null) {
|
||||||
|
mThread = new Thread(this);
|
||||||
|
mThread.start();
|
||||||
|
}
|
||||||
|
synchronized (this) {
|
||||||
|
mPlayCount++;
|
||||||
|
notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void release() {
|
||||||
|
if (mThread != null) {
|
||||||
|
synchronized (this) {
|
||||||
|
mExit = true;
|
||||||
|
notifyAll();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
mThread.join();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
mThread = null;
|
||||||
|
}
|
||||||
|
if (mPlayer != null) {
|
||||||
|
mPlayer.release();
|
||||||
|
mPlayer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void finalize() {
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user