PageRenderTime 48ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/core/java/android/hardware/CameraSound.java

http://github.com/android/platform_frameworks_base
Java | 223 lines | 141 code | 19 blank | 63 comment | 22 complexity | 7a23e08f98bf6337dcb84d7383f2b10d MD5 | raw file
Possible License(s): BitTorrent-1.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, CC0-1.0
  1. /*
  2. * Copyright (C) 2011 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package android.hardware;
  17. import android.media.AudioManager;
  18. import android.media.MediaPlayer;
  19. import android.os.SystemProperties;
  20. import android.util.Log;
  21. import java.io.IOException;
  22. /**
  23. * <p>Use this class to play an appropriate sound when implementing a custom
  24. * still or video recording mechanism through the preview callbacks.</p>
  25. *
  26. * <p>There is no need to play sounds when using {@link #android.hardware.Camera#takePicture}
  27. * or {@link android.media.MediaRecorder} for still images or video,
  28. * respectively, as these play their own sounds when needed.</p>
  29. *
  30. * @hide
  31. */
  32. public class CameraSound {
  33. private static final String TAG = "CameraSound";
  34. /**
  35. * The sound used by {@link android.hardware.Camera#takePicture} to
  36. * indicate still image capture.
  37. */
  38. public static final int SHUTTER_CLICK = 0;
  39. /**
  40. * A sound to indicate that focusing has completed. Because deciding
  41. * when this occurs is application-dependent, this sound is not used by
  42. * any methods in the Camera class.
  43. */
  44. public static final int FOCUS_COMPLETE = 1;
  45. /**
  46. * The sound used by {@link android.media.MediaRecorder#start} to
  47. * indicate the start of video recording.
  48. */
  49. public static final int START_VIDEO_RECORDING = 2;
  50. /**
  51. * The sound used by {@link android.media.MediaRecorder#stop} to
  52. * indicate the end of video recording.
  53. */
  54. public static final int STOP_VIDEO_RECORDING = 3;
  55. private static final int NUM_SOUNDS = 4;
  56. private CameraSoundPlayer[] mCameraSoundPlayers;
  57. public CameraSound() {
  58. }
  59. /**
  60. * <p>Play one of the predefined platform sounds for camera actions.</p>
  61. *
  62. * <p>Use this method to play a platform-specific sound for various camera
  63. * actions. The sound playing is done asynchronously, with the same behavior
  64. * and content as the sounds played by {@link #takePicture takePicture},
  65. * {@link android.media.MediaRecorder#start MediaRecorder.start}, and
  66. * {@link android.media.MediaRecorder#stop MediaRecorder.stop}.</p>
  67. *
  68. * <p>Using this method makes it easy to match the default device sounds
  69. * when recording or capturing data through the preview callbacks.</p>
  70. *
  71. * @param soundId The type of sound to play, selected from SHUTTER_CLICK,
  72. * FOCUS_COMPLETE, START_VIDEO_RECORDING, or STOP_VIDEO_RECORDING.
  73. * @see android.hardware#takePicture
  74. * @see android.media.MediaRecorder
  75. * @see #SHUTTER_CLICK
  76. * @see #FOCUS_COMPLETE
  77. * @see #START_VIDEO_RECORDING
  78. * @see #STOP_VIDEO_RECORDING
  79. */
  80. public void playSound(int soundId) {
  81. if (mCameraSoundPlayers == null) {
  82. mCameraSoundPlayers = new CameraSoundPlayer[NUM_SOUNDS];
  83. }
  84. if (mCameraSoundPlayers[soundId] == null) {
  85. mCameraSoundPlayers[soundId] = new CameraSoundPlayer(soundId);
  86. }
  87. mCameraSoundPlayers[soundId].play();
  88. }
  89. public void release() {
  90. if (mCameraSoundPlayers != null) {
  91. for (CameraSoundPlayer csp: mCameraSoundPlayers) {
  92. if (csp != null) {
  93. csp.release();
  94. }
  95. }
  96. mCameraSoundPlayers = null;
  97. }
  98. }
  99. private static class CameraSoundPlayer implements Runnable {
  100. private int mSoundId;
  101. private int mAudioStreamType;
  102. private MediaPlayer mPlayer;
  103. private Thread mThread;
  104. private boolean mExit;
  105. private int mPlayCount;
  106. private static final String mShutterSound =
  107. "/system/media/audio/ui/camera_click.ogg";
  108. private static final String mFocusSound =
  109. "/system/media/audio/ui/camera_focus.ogg";
  110. private static final String mVideoStartSound =
  111. "/system/media/audio/ui/VideoRecord.ogg";
  112. private static final String mVideoStopSound =
  113. "/system/media/audio/ui/VideoRecord.ogg";
  114. @Override
  115. public void run() {
  116. String soundFilePath;
  117. switch (mSoundId) {
  118. case SHUTTER_CLICK:
  119. soundFilePath = mShutterSound;
  120. break;
  121. case FOCUS_COMPLETE:
  122. soundFilePath = mFocusSound;
  123. break;
  124. case START_VIDEO_RECORDING:
  125. soundFilePath = mVideoStartSound;
  126. break;
  127. case STOP_VIDEO_RECORDING:
  128. soundFilePath = mVideoStopSound;
  129. break;
  130. default:
  131. Log.e(TAG, "Unknown sound " + mSoundId + " requested.");
  132. return;
  133. }
  134. mPlayer = new MediaPlayer();
  135. try {
  136. mPlayer.setAudioStreamType(mAudioStreamType);
  137. mPlayer.setDataSource(soundFilePath);
  138. mPlayer.setLooping(false);
  139. mPlayer.prepare();
  140. } catch(IOException e) {
  141. Log.e(TAG, "Error setting up sound " + mSoundId, e);
  142. return;
  143. }
  144. while(true) {
  145. try {
  146. synchronized (this) {
  147. while(true) {
  148. if (mExit) {
  149. return;
  150. } else if (mPlayCount <= 0) {
  151. wait();
  152. } else {
  153. mPlayCount--;
  154. break;
  155. }
  156. }
  157. }
  158. mPlayer.start();
  159. } catch (Exception e) {
  160. Log.e(TAG, "Error playing sound " + mSoundId, e);
  161. }
  162. }
  163. }
  164. public CameraSoundPlayer(int soundId) {
  165. mSoundId = soundId;
  166. if (SystemProperties.get("ro.camera.sound.forced", "0").equals("0")) {
  167. mAudioStreamType = AudioManager.STREAM_MUSIC;
  168. } else {
  169. mAudioStreamType = AudioManager.STREAM_SYSTEM_ENFORCED;
  170. }
  171. }
  172. public void play() {
  173. if (mThread == null) {
  174. mThread = new Thread(this);
  175. mThread.start();
  176. }
  177. synchronized (this) {
  178. mPlayCount++;
  179. notifyAll();
  180. }
  181. }
  182. public void release() {
  183. if (mThread != null) {
  184. synchronized (this) {
  185. mExit = true;
  186. notifyAll();
  187. }
  188. try {
  189. mThread.join();
  190. } catch (InterruptedException e) {
  191. }
  192. mThread = null;
  193. }
  194. if (mPlayer != null) {
  195. mPlayer.release();
  196. mPlayer = null;
  197. }
  198. }
  199. @Override
  200. protected void finalize() {
  201. release();
  202. }
  203. }
  204. }