mirror of
https://github.com/Myzel394/Alibi.git
synced 2025-06-19 07:15:25 +02:00
feat: Add cameraID and enableAudio pass from UI to VideoRecorderService
This commit is contained in:
parent
60f53f3649
commit
add9c8cde5
@ -1,8 +1,10 @@
|
|||||||
package app.myzel394.alibi.services
|
package app.myzel394.alibi.services
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Intent
|
||||||
import android.util.Range
|
import android.util.Range
|
||||||
import androidx.camera.core.Camera
|
import androidx.camera.core.Camera
|
||||||
|
import androidx.camera.core.CameraControl
|
||||||
import androidx.camera.core.CameraSelector
|
import androidx.camera.core.CameraSelector
|
||||||
import androidx.camera.core.TorchState
|
import androidx.camera.core.TorchState
|
||||||
import androidx.camera.lifecycle.ProcessCameraProvider
|
import androidx.camera.lifecycle.ProcessCameraProvider
|
||||||
@ -27,6 +29,7 @@ import kotlinx.coroutines.delay
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
const val CAMERA_CLOSE_TIMEOUT = 20000L
|
const val CAMERA_CLOSE_TIMEOUT = 20000L
|
||||||
|
|
||||||
@ -49,11 +52,23 @@ class VideoRecorderService :
|
|||||||
// Absolute last completer that can be awaited to ensure that the camera is closed
|
// Absolute last completer that can be awaited to ensure that the camera is closed
|
||||||
private var _cameraCloserListener = CompletableDeferred<Unit>()
|
private var _cameraCloserListener = CompletableDeferred<Unit>()
|
||||||
|
|
||||||
private var selectedCamera: CameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
|
private lateinit var selectedCamera: CameraSelector
|
||||||
|
private var enableAudio by Delegates.notNull<Boolean>()
|
||||||
|
|
||||||
var cameraControl: CameraControl? = null
|
var cameraControl: CameraControl? = null
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
|
if (intent?.action == "init") {
|
||||||
|
selectedCamera = CameraSelector.Builder().requireLensFacing(
|
||||||
|
intent.getIntExtra("cameraID", CameraSelector.LENS_FACING_BACK)
|
||||||
|
).build()
|
||||||
|
enableAudio = intent.getBooleanExtra("enableAudio", true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.onStartCommand(intent, flags, startId)
|
||||||
|
}
|
||||||
|
|
||||||
override fun start() {
|
override fun start() {
|
||||||
super.start()
|
super.start()
|
||||||
|
|
||||||
@ -189,7 +204,13 @@ class VideoRecorderService :
|
|||||||
private fun prepareVideoRecording() =
|
private fun prepareVideoRecording() =
|
||||||
videoCapture!!.output
|
videoCapture!!.output
|
||||||
.prepareRecording(this, settings.getOutputOptions(this))
|
.prepareRecording(this, settings.getOutputOptions(this))
|
||||||
.withAudioEnabled()
|
.run {
|
||||||
|
if (enableAudio) {
|
||||||
|
return@run withAudioEnabled()
|
||||||
|
}
|
||||||
|
|
||||||
|
this
|
||||||
|
}
|
||||||
|
|
||||||
override fun getRecordingInformation(): RecordingInformation = RecordingInformation(
|
override fun getRecordingInformation(): RecordingInformation = RecordingInformation(
|
||||||
folderPath = batchesFolder.exportFolderForSettings(),
|
folderPath = batchesFolder.exportFolderForSettings(),
|
||||||
|
@ -8,13 +8,13 @@ import androidx.compose.foundation.layout.Column
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import app.myzel394.alibi.R
|
import app.myzel394.alibi.R
|
||||||
import app.myzel394.alibi.ui.models.VideoRecorderSettingsModel
|
import app.myzel394.alibi.ui.models.VideoRecorderModel
|
||||||
import app.myzel394.alibi.ui.utils.CameraInfo
|
import app.myzel394.alibi.ui.utils.CameraInfo
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CamerasSelection(
|
fun CamerasSelection(
|
||||||
cameras: Iterable<CameraInfo>,
|
cameras: Iterable<CameraInfo>,
|
||||||
videoSettings: VideoRecorderSettingsModel
|
videoSettings: VideoRecorderModel,
|
||||||
) {
|
) {
|
||||||
val CAMERA_LENS_TEXT_MAP = mapOf(
|
val CAMERA_LENS_TEXT_MAP = mapOf(
|
||||||
CameraInfo.Lens.BACK to stringResource(R.string.ui_videoRecorder_action_start_settings_cameraLens_back_label),
|
CameraInfo.Lens.BACK to stringResource(R.string.ui_videoRecorder_action_start_settings_cameraLens_back_label),
|
||||||
|
@ -38,7 +38,9 @@ import androidx.compose.ui.ExperimentalComposeUiApi
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.alpha
|
import androidx.compose.ui.draw.alpha
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.input.pointer.PointerEventPass
|
||||||
import androidx.compose.ui.input.pointer.pointerInput
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
|
import androidx.compose.ui.input.pointer.positionChange
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.semantics.contentDescription
|
import androidx.compose.ui.semantics.contentDescription
|
||||||
@ -53,19 +55,20 @@ import app.myzel394.alibi.ui.components.RecorderScreen.atoms.CameraPreview
|
|||||||
import app.myzel394.alibi.ui.components.atoms.GlobalSwitch
|
import app.myzel394.alibi.ui.components.atoms.GlobalSwitch
|
||||||
import app.myzel394.alibi.ui.components.atoms.PermissionRequester
|
import app.myzel394.alibi.ui.components.atoms.PermissionRequester
|
||||||
import app.myzel394.alibi.ui.effects.rememberPrevious
|
import app.myzel394.alibi.ui.effects.rememberPrevious
|
||||||
import app.myzel394.alibi.ui.models.VideoRecorderSettingsModel
|
import app.myzel394.alibi.ui.models.VideoRecorderModel
|
||||||
import app.myzel394.alibi.ui.utils.CameraInfo
|
import app.myzel394.alibi.ui.utils.CameraInfo
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
@OptIn(
|
@OptIn(
|
||||||
ExperimentalMaterial3Api::class,
|
ExperimentalMaterial3Api::class,
|
||||||
)
|
)
|
||||||
@Composable
|
@Composable
|
||||||
fun VideoRecorderPreparationSheet(
|
fun VideoRecorderPreparationSheet(
|
||||||
|
showPreview: Boolean,
|
||||||
|
videoSettings: VideoRecorderModel,
|
||||||
onDismiss: () -> Unit,
|
onDismiss: () -> Unit,
|
||||||
videoSettings: VideoRecorderSettingsModel = viewModel(),
|
|
||||||
onPreviewVisible: () -> Unit,
|
onPreviewVisible: () -> Unit,
|
||||||
onPreviewHidden: () -> Unit,
|
onPreviewHidden: () -> Unit,
|
||||||
showPreview: Boolean,
|
|
||||||
onStartRecording: () -> Unit,
|
onStartRecording: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val sheetState = rememberModalBottomSheetState(true) { sheetValue ->
|
val sheetState = rememberModalBottomSheetState(true) { sheetValue ->
|
||||||
@ -87,7 +90,7 @@ fun VideoRecorderPreparationSheet(
|
|||||||
Unit
|
Unit
|
||||||
else
|
else
|
||||||
BottomSheetDefaults.DragHandle()
|
BottomSheetDefaults.DragHandle()
|
||||||
}
|
},
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@ -184,6 +187,9 @@ fun VideoRecorderPreparationSheet(
|
|||||||
onLongPress = {
|
onLongPress = {
|
||||||
onPreviewVisible()
|
onPreviewVisible()
|
||||||
},
|
},
|
||||||
|
onTap = {
|
||||||
|
onStartRecording()
|
||||||
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
horizontalArrangement = Arrangement.Center,
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.size
|
|||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.CameraAlt
|
import androidx.compose.material.icons.filled.CameraAlt
|
||||||
import androidx.compose.material.icons.filled.Mic
|
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.ButtonDefaults
|
import androidx.compose.material3.ButtonDefaults
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
@ -27,6 +26,7 @@ import androidx.compose.ui.res.stringResource
|
|||||||
import androidx.compose.ui.semantics.contentDescription
|
import androidx.compose.ui.semantics.contentDescription
|
||||||
import androidx.compose.ui.semantics.semantics
|
import androidx.compose.ui.semantics.semantics
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import app.myzel394.alibi.R
|
import app.myzel394.alibi.R
|
||||||
import app.myzel394.alibi.db.AppSettings
|
import app.myzel394.alibi.db.AppSettings
|
||||||
import app.myzel394.alibi.ui.components.atoms.PermissionRequester
|
import app.myzel394.alibi.ui.components.atoms.PermissionRequester
|
||||||
@ -48,12 +48,13 @@ fun VideoRecordingStart(
|
|||||||
|
|
||||||
if (showSheet) {
|
if (showSheet) {
|
||||||
VideoRecorderPreparationSheet(
|
VideoRecorderPreparationSheet(
|
||||||
|
showPreview = showPreview,
|
||||||
|
videoSettings = videoRecorder,
|
||||||
onDismiss = {
|
onDismiss = {
|
||||||
showSheet = false
|
showSheet = false
|
||||||
},
|
},
|
||||||
onPreviewVisible = onHideAudioRecording,
|
onPreviewVisible = onHideAudioRecording,
|
||||||
onPreviewHidden = onShowAudioRecording,
|
onPreviewHidden = onShowAudioRecording,
|
||||||
showPreview = showPreview,
|
|
||||||
onStartRecording = {
|
onStartRecording = {
|
||||||
videoRecorder.startRecording(context, appSettings)
|
videoRecorder.startRecording(context, appSettings)
|
||||||
},
|
},
|
||||||
|
@ -90,8 +90,13 @@ abstract class BaseRecorderModel<S : IntervalRecorderService.Settings, I, T : In
|
|||||||
recordingTime = null
|
recordingTime = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected open fun handleIntent(intent: Intent) = intent
|
||||||
|
|
||||||
// If override, call `super` AFTER setting the settings
|
// If override, call `super` AFTER setting the settings
|
||||||
open fun startRecording(context: Context, settings: AppSettings) {
|
open fun startRecording(
|
||||||
|
context: Context,
|
||||||
|
settings: AppSettings,
|
||||||
|
) {
|
||||||
this.settings = settings
|
this.settings = settings
|
||||||
|
|
||||||
runCatching {
|
runCatching {
|
||||||
@ -121,7 +126,7 @@ abstract class BaseRecorderModel<S : IntervalRecorderService.Settings, I, T : In
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}.let(::handleIntent)
|
||||||
ContextCompat.startForegroundService(context, intent)
|
ContextCompat.startForegroundService(context, intent)
|
||||||
context.bindService(intent, connection, Context.BIND_AUTO_CREATE)
|
context.bindService(intent, connection, Context.BIND_AUTO_CREATE)
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,36 @@
|
|||||||
package app.myzel394.alibi.ui.models
|
package app.myzel394.alibi.ui.models
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import androidx.camera.core.CameraSelector
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import app.myzel394.alibi.db.AppSettings
|
||||||
import app.myzel394.alibi.db.RecordingInformation
|
import app.myzel394.alibi.db.RecordingInformation
|
||||||
import app.myzel394.alibi.helpers.VideoBatchesFolder
|
import app.myzel394.alibi.helpers.VideoBatchesFolder
|
||||||
import app.myzel394.alibi.services.VideoRecorderService
|
import app.myzel394.alibi.services.VideoRecorderService
|
||||||
|
import app.myzel394.alibi.ui.utils.CameraInfo
|
||||||
|
import app.myzel394.alibi.ui.utils.PermissionHelper
|
||||||
|
|
||||||
class VideoRecorderModel :
|
class VideoRecorderModel :
|
||||||
BaseRecorderModel<VideoRecorderService.Settings, RecordingInformation, VideoRecorderService, VideoBatchesFolder?>() {
|
BaseRecorderModel<VideoRecorderService.Settings, RecordingInformation, VideoRecorderService, VideoBatchesFolder?>() {
|
||||||
override var batchesFolder: VideoBatchesFolder? = null
|
override var batchesFolder: VideoBatchesFolder? = null
|
||||||
override val intentClass = VideoRecorderService::class.java
|
override val intentClass = VideoRecorderService::class.java
|
||||||
|
|
||||||
|
var enableAudio by mutableStateOf(true)
|
||||||
|
var cameraID by mutableIntStateOf(CameraInfo.Lens.BACK.androidValue)
|
||||||
|
|
||||||
|
val cameraSelector: CameraSelector
|
||||||
|
get() = CameraSelector.Builder().requireLensFacing(cameraID).build()
|
||||||
|
|
||||||
|
fun init(context: Context) {
|
||||||
|
enableAudio = PermissionHelper.hasGranted(context, Manifest.permission.RECORD_AUDIO)
|
||||||
|
cameraID = CameraInfo.Lens.BACK.androidValue
|
||||||
|
}
|
||||||
|
|
||||||
override fun onServiceConnected(service: VideoRecorderService) {
|
override fun onServiceConnected(service: VideoRecorderService) {
|
||||||
service.settings = VideoRecorderService.Settings.from(settings)
|
service.settings = VideoRecorderService.Settings.from(settings)
|
||||||
|
|
||||||
@ -18,4 +40,15 @@ class VideoRecorderModel :
|
|||||||
recorderState = service.state
|
recorderState = service.state
|
||||||
recordingTime = service.recordingTime
|
recordingTime = service.recordingTime
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun handleIntent(intent: Intent) =
|
||||||
|
intent.apply {
|
||||||
|
putExtra("cameraID", cameraID)
|
||||||
|
putExtra("enableAudio", enableAudio)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun startRecording(context: Context, settings: AppSettings) {
|
||||||
|
super.startRecording(context, settings)
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,28 +0,0 @@
|
|||||||
package app.myzel394.alibi.ui.models
|
|
||||||
|
|
||||||
import android.Manifest
|
|
||||||
import android.Manifest.permission.RECORD_AUDIO
|
|
||||||
import android.content.Context
|
|
||||||
import android.graphics.Camera
|
|
||||||
import android.hardware.camera2.CameraManager
|
|
||||||
import androidx.camera.core.CameraSelector
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import app.myzel394.alibi.ui.utils.CameraInfo
|
|
||||||
import app.myzel394.alibi.ui.utils.PermissionHelper
|
|
||||||
|
|
||||||
class VideoRecorderSettingsModel : ViewModel() {
|
|
||||||
var enableAudio by mutableStateOf(true)
|
|
||||||
var cameraID by mutableIntStateOf(CameraInfo.Lens.BACK.androidValue)
|
|
||||||
|
|
||||||
val cameraSelector: CameraSelector
|
|
||||||
get() = CameraSelector.Builder().requireLensFacing(cameraID).build()
|
|
||||||
|
|
||||||
fun init(context: Context) {
|
|
||||||
enableAudio = PermissionHelper.hasGranted(context, Manifest.permission.RECORD_AUDIO)
|
|
||||||
cameraID = CameraInfo.Lens.BACK.androidValue
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user