mirror of
				https://github.com/SimpleMobileTools/Simple-Camera.git
				synced 2025-06-27 09:02:59 +02:00 
			
		
		
		
	handle playing media sounds
- add MediaSoundHelper to separate logic for playing media action sounds - add support for playing media action sounds (shutter, start and stop recording) in CameraXPreview
This commit is contained in:
		| @@ -39,6 +39,7 @@ import com.simplemobiletools.commons.helpers.PERMISSION_RECORD_AUDIO | |||||||
| import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE | import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE | ||||||
| import com.simplemobiletools.commons.helpers.REFRESH_PATH | import com.simplemobiletools.commons.helpers.REFRESH_PATH | ||||||
| import com.simplemobiletools.commons.models.Release | import com.simplemobiletools.commons.models.Release | ||||||
|  | import java.util.concurrent.TimeUnit | ||||||
| import kotlinx.android.synthetic.main.activity_main.btn_holder | import kotlinx.android.synthetic.main.activity_main.btn_holder | ||||||
| import kotlinx.android.synthetic.main.activity_main.capture_black_screen | import kotlinx.android.synthetic.main.activity_main.capture_black_screen | ||||||
| import kotlinx.android.synthetic.main.activity_main.change_resolution | import kotlinx.android.synthetic.main.activity_main.change_resolution | ||||||
| @@ -549,6 +550,24 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera | |||||||
|         updateFlashlightState(flashMode) |         updateFlashlightState(flashMode) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     override fun onVideoRecordingStarted() { | ||||||
|  |         shutter.setImageResource(R.drawable.ic_video_stop) | ||||||
|  |         toggle_camera.beInvisible() | ||||||
|  |         video_rec_curr_timer.beVisible() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun onVideoRecordingStopped() { | ||||||
|  |         shutter.setImageResource(R.drawable.ic_video_rec) | ||||||
|  |         video_rec_curr_timer.text = 0.getFormattedDuration() | ||||||
|  |         video_rec_curr_timer.beGone() | ||||||
|  |         toggle_camera.beVisible() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun onVideoDurationChanged(durationNanos: Long) { | ||||||
|  |         val seconds = TimeUnit.NANOSECONDS.toSeconds(durationNanos).toInt() | ||||||
|  |         video_rec_curr_timer.text = seconds.getFormattedDuration() | ||||||
|  |     } | ||||||
|  |  | ||||||
|     fun setRecordingState(isRecording: Boolean) { |     fun setRecordingState(isRecording: Boolean) { | ||||||
|         runOnUiThread { |         runOnUiThread { | ||||||
|             if (isRecording) { |             if (isRecording) { | ||||||
|   | |||||||
| @@ -0,0 +1,25 @@ | |||||||
|  | package com.simplemobiletools.camera.helpers | ||||||
|  |  | ||||||
|  | import android.media.MediaActionSound | ||||||
|  |  | ||||||
|  | class MediaSoundHelper { | ||||||
|  |     private val mediaActionSound = MediaActionSound() | ||||||
|  |  | ||||||
|  |     fun loadSounds() { | ||||||
|  |         mediaActionSound.load(MediaActionSound.START_VIDEO_RECORDING) | ||||||
|  |         mediaActionSound.load(MediaActionSound.STOP_VIDEO_RECORDING) | ||||||
|  |         mediaActionSound.load(MediaActionSound.SHUTTER_CLICK) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun playShutterSound() { | ||||||
|  |         mediaActionSound.play(MediaActionSound.SHUTTER_CLICK) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun playStartVideoRecordingSound() { | ||||||
|  |         mediaActionSound.play(MediaActionSound.START_VIDEO_RECORDING) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun playStopVideoRecordingSound() { | ||||||
|  |         mediaActionSound.play(MediaActionSound.STOP_VIDEO_RECORDING) | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -37,6 +37,7 @@ import com.simplemobiletools.camera.R | |||||||
| import com.simplemobiletools.camera.extensions.config | import com.simplemobiletools.camera.extensions.config | ||||||
| import com.simplemobiletools.camera.extensions.toAppFlashMode | import com.simplemobiletools.camera.extensions.toAppFlashMode | ||||||
| import com.simplemobiletools.camera.extensions.toCameraXFlashMode | import com.simplemobiletools.camera.extensions.toCameraXFlashMode | ||||||
|  | import com.simplemobiletools.camera.helpers.MediaSoundHelper | ||||||
| import com.simplemobiletools.camera.interfaces.MyPreview | import com.simplemobiletools.camera.interfaces.MyPreview | ||||||
| import com.simplemobiletools.commons.extensions.showErrorToast | import com.simplemobiletools.commons.extensions.showErrorToast | ||||||
| import com.simplemobiletools.commons.extensions.toast | import com.simplemobiletools.commons.extensions.toast | ||||||
| @@ -63,6 +64,7 @@ class CameraXPreview( | |||||||
|     private val config = activity.config |     private val config = activity.config | ||||||
|     private val contentResolver = activity.contentResolver |     private val contentResolver = activity.contentResolver | ||||||
|     private val mainExecutor = activity.mainExecutor |     private val mainExecutor = activity.mainExecutor | ||||||
|  |     private val mediaSoundHelper = MediaSoundHelper() | ||||||
|     private val windowMetricsCalculator = WindowMetricsCalculator.getOrCreate() |     private val windowMetricsCalculator = WindowMetricsCalculator.getOrCreate() | ||||||
|     private val orientationEventListener = object : OrientationEventListener(activity, SensorManager.SENSOR_DELAY_NORMAL) { |     private val orientationEventListener = object : OrientationEventListener(activity, SensorManager.SENSOR_DELAY_NORMAL) { | ||||||
|         @SuppressLint("RestrictedApi") |         @SuppressLint("RestrictedApi") | ||||||
| @@ -109,6 +111,7 @@ class CameraXPreview( | |||||||
|  |  | ||||||
|     init { |     init { | ||||||
|         bindToLifeCycle() |         bindToLifeCycle() | ||||||
|  |         mediaSoundHelper.loadSounds() | ||||||
|         viewFinder.doOnLayout { |         viewFinder.doOnLayout { | ||||||
|             startCamera() |             startCamera() | ||||||
|         } |         } | ||||||
| @@ -315,6 +318,7 @@ class CameraXPreview( | |||||||
|             .setMetadata(metadata) |             .setMetadata(metadata) | ||||||
|             .build() |             .build() | ||||||
|  |  | ||||||
|  |  | ||||||
|         imageCapture.takePicture(outputOptions, mainExecutor, object : OnImageSavedCallback { |         imageCapture.takePicture(outputOptions, mainExecutor, object : OnImageSavedCallback { | ||||||
|             override fun onImageSaved(outputFileResults: OutputFileResults) { |             override fun onImageSaved(outputFileResults: OutputFileResults) { | ||||||
|                 listener.toggleBottomButtons(false) |                 listener.toggleBottomButtons(false) | ||||||
| @@ -327,6 +331,7 @@ class CameraXPreview( | |||||||
|                 Log.e(TAG, "Error", exception) |                 Log.e(TAG, "Error", exception) | ||||||
|             } |             } | ||||||
|         }) |         }) | ||||||
|  |         playShutterSoundIfEnabled() | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     override fun initPhotoMode() { |     override fun initPhotoMode() { | ||||||
| @@ -368,11 +373,20 @@ class CameraXPreview( | |||||||
|             .withAudioEnabled() |             .withAudioEnabled() | ||||||
|             .start(mainExecutor) { recordEvent -> |             .start(mainExecutor) { recordEvent -> | ||||||
|                 Log.d(TAG, "recordEvent=$recordEvent ") |                 Log.d(TAG, "recordEvent=$recordEvent ") | ||||||
|                 if (recordEvent !is VideoRecordEvent.Status) { |  | ||||||
|                 recordingState = recordEvent |                 recordingState = recordEvent | ||||||
|  |                 when(recordEvent){ | ||||||
|  |                     is VideoRecordEvent.Start -> { | ||||||
|  |                         playStartVideoRecordingSoundIfEnabled() | ||||||
|  |                         listener.onVideoRecordingStarted() | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                 if (recordEvent is VideoRecordEvent.Finalize) { |                     is VideoRecordEvent.Status -> { | ||||||
|  |                         listener.onVideoDurationChanged(recordEvent.recordingStats.recordedDurationNanos) | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                     is VideoRecordEvent.Finalize -> { | ||||||
|  |                         playStopVideoRecordingSoundIfEnabled() | ||||||
|  |                         listener.onVideoRecordingStopped() | ||||||
|                         if (recordEvent.hasError()) { |                         if (recordEvent.hasError()) { | ||||||
|                             // TODO: Handle errors |                             // TODO: Handle errors | ||||||
|                         } else { |                         } else { | ||||||
| @@ -380,6 +394,7 @@ class CameraXPreview( | |||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |             } | ||||||
|         Log.d(TAG, "Recording started") |         Log.d(TAG, "Recording started") | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -391,4 +406,22 @@ class CameraXPreview( | |||||||
|             "VID_$timestamp" |             "VID_$timestamp" | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     private fun playShutterSoundIfEnabled(){ | ||||||
|  |         if(config.isSoundEnabled){ | ||||||
|  |             mediaSoundHelper.playShutterSound() | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private fun playStartVideoRecordingSoundIfEnabled(){ | ||||||
|  |         if(config.isSoundEnabled){ | ||||||
|  |             mediaSoundHelper.playStartVideoRecordingSound() | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private fun playStopVideoRecordingSoundIfEnabled(){ | ||||||
|  |         if(config.isSoundEnabled){ | ||||||
|  |             mediaSoundHelper.playStopVideoRecordingSound() | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -10,4 +10,7 @@ interface CameraXPreviewListener { | |||||||
|     fun toggleBottomButtons(hide:Boolean) |     fun toggleBottomButtons(hide:Boolean) | ||||||
|     fun onMediaCaptured(uri: Uri) |     fun onMediaCaptured(uri: Uri) | ||||||
|     fun onChangeFlashMode(flashMode: Int) |     fun onChangeFlashMode(flashMode: Int) | ||||||
|  |     fun onVideoRecordingStarted() | ||||||
|  |     fun onVideoRecordingStopped() | ||||||
|  |     fun onVideoDurationChanged(durationNanos: Long) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -96,7 +96,7 @@ class CameraPreview : ViewGroup, TextureView.SurfaceTextureListener, MyPreview { | |||||||
|     private val mCameraToPreviewMatrix = Matrix() |     private val mCameraToPreviewMatrix = Matrix() | ||||||
|     private val mPreviewToCameraMatrix = Matrix() |     private val mPreviewToCameraMatrix = Matrix() | ||||||
|     private val mCameraOpenCloseLock = Semaphore(1) |     private val mCameraOpenCloseLock = Semaphore(1) | ||||||
|     private val mMediaActionSound = MediaActionSound() |     private val mediaSoundHelper = MediaSoundHelper() | ||||||
|     private var mZoomRect: Rect? = null |     private var mZoomRect: Rect? = null | ||||||
|  |  | ||||||
|     constructor(context: Context) : super(context) |     constructor(context: Context) : super(context) | ||||||
| @@ -114,7 +114,7 @@ class CameraPreview : ViewGroup, TextureView.SurfaceTextureListener, MyPreview { | |||||||
|  |  | ||||||
|         mUseFrontCamera = false |         mUseFrontCamera = false | ||||||
|         mIsInVideoMode = !initPhotoMode |         mIsInVideoMode = !initPhotoMode | ||||||
|         loadSounds() |         mediaSoundHelper.loadSounds() | ||||||
|  |  | ||||||
|         val gestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() { |         val gestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() { | ||||||
|             override fun onSingleTapConfirmed(e: MotionEvent?): Boolean { |             override fun onSingleTapConfirmed(e: MotionEvent?): Boolean { | ||||||
| @@ -182,12 +182,6 @@ class CameraPreview : ViewGroup, TextureView.SurfaceTextureListener, MyPreview { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private fun loadSounds() { |  | ||||||
|         mMediaActionSound.load(MediaActionSound.START_VIDEO_RECORDING) |  | ||||||
|         mMediaActionSound.load(MediaActionSound.STOP_VIDEO_RECORDING) |  | ||||||
|         mMediaActionSound.load(MediaActionSound.SHUTTER_CLICK) |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @SuppressLint("MissingPermission") |     @SuppressLint("MissingPermission") | ||||||
|     private fun openCamera(width: Int, height: Int) { |     private fun openCamera(width: Int, height: Int) { | ||||||
|         try { |         try { | ||||||
| @@ -576,7 +570,7 @@ class CameraPreview : ViewGroup, TextureView.SurfaceTextureListener, MyPreview { | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (mActivity.config.isSoundEnabled) { |             if (mActivity.config.isSoundEnabled) { | ||||||
|                 mMediaActionSound.play(MediaActionSound.SHUTTER_CLICK) |                 mediaSoundHelper.playShutterSound() | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             mCameraState = STATE_PICTURE_TAKEN |             mCameraState = STATE_PICTURE_TAKEN | ||||||
| @@ -824,7 +818,7 @@ class CameraPreview : ViewGroup, TextureView.SurfaceTextureListener, MyPreview { | |||||||
|         closeCaptureSession() |         closeCaptureSession() | ||||||
|         setupMediaRecorder() |         setupMediaRecorder() | ||||||
|         if (mActivity.config.isSoundEnabled) { |         if (mActivity.config.isSoundEnabled) { | ||||||
|             mMediaActionSound.play(MediaActionSound.START_VIDEO_RECORDING) |             mediaSoundHelper.playStartVideoRecordingSound() | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         try { |         try { | ||||||
| @@ -853,7 +847,7 @@ class CameraPreview : ViewGroup, TextureView.SurfaceTextureListener, MyPreview { | |||||||
|     private fun stopRecording() { |     private fun stopRecording() { | ||||||
|         mCameraState = STATE_STOPING_RECORDING |         mCameraState = STATE_STOPING_RECORDING | ||||||
|         if (mActivity.config.isSoundEnabled) { |         if (mActivity.config.isSoundEnabled) { | ||||||
|             mMediaActionSound.play(MediaActionSound.STOP_VIDEO_RECORDING) |             mediaSoundHelper.playStopVideoRecordingSound() | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         mIsRecording = false |         mIsRecording = false | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user