1 /*
<lambda>null2  * Copyright (C) 2023 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 com.google.jetpackcamera.settings
17 
18 import androidx.datastore.core.DataStore
19 import com.google.jetpackcamera.settings.AspectRatio as AspectRatioProto
20 import com.google.jetpackcamera.settings.CaptureMode as CaptureModeProto
21 import com.google.jetpackcamera.settings.DarkMode as DarkModeProto
22 import com.google.jetpackcamera.settings.FlashMode as FlashModeProto
23 import com.google.jetpackcamera.settings.PreviewStabilization as PreviewStabilizationProto
24 import com.google.jetpackcamera.settings.VideoStabilization as VideoStabilizationProto
25 import com.google.jetpackcamera.settings.model.AspectRatio
26 import com.google.jetpackcamera.settings.model.CameraAppSettings
27 import com.google.jetpackcamera.settings.model.CaptureMode
28 import com.google.jetpackcamera.settings.model.DarkMode
29 import com.google.jetpackcamera.settings.model.DynamicRange
30 import com.google.jetpackcamera.settings.model.DynamicRange.Companion.toProto
31 import com.google.jetpackcamera.settings.model.FlashMode
32 import com.google.jetpackcamera.settings.model.ImageOutputFormat
33 import com.google.jetpackcamera.settings.model.ImageOutputFormat.Companion.toProto
34 import com.google.jetpackcamera.settings.model.LensFacing
35 import com.google.jetpackcamera.settings.model.LensFacing.Companion.toProto
36 import com.google.jetpackcamera.settings.model.Stabilization
37 import javax.inject.Inject
38 import kotlinx.coroutines.flow.first
39 import kotlinx.coroutines.flow.map
40 
41 const val TARGET_FPS_15 = 15
42 const val TARGET_FPS_60 = 60
43 
44 /**
45  * Implementation of [SettingsRepository] with locally stored settings.
46  */
47 class LocalSettingsRepository @Inject constructor(
48     private val jcaSettings: DataStore<JcaSettings>
49 ) : SettingsRepository {
50 
51     override val defaultCameraAppSettings = jcaSettings.data
52         .map {
53             CameraAppSettings(
54                 cameraLensFacing = LensFacing.fromProto(it.defaultLensFacing),
55                 darkMode = when (it.darkModeStatus) {
56                     DarkModeProto.DARK_MODE_DARK -> DarkMode.DARK
57                     DarkModeProto.DARK_MODE_LIGHT -> DarkMode.LIGHT
58                     DarkModeProto.DARK_MODE_SYSTEM -> DarkMode.SYSTEM
59                     else -> DarkMode.SYSTEM
60                 },
61                 flashMode = when (it.flashModeStatus) {
62                     FlashModeProto.FLASH_MODE_AUTO -> FlashMode.AUTO
63                     FlashModeProto.FLASH_MODE_ON -> FlashMode.ON
64                     FlashModeProto.FLASH_MODE_OFF -> FlashMode.OFF
65                     else -> FlashMode.OFF
66                 },
67                 aspectRatio = AspectRatio.fromProto(it.aspectRatioStatus),
68                 previewStabilization = Stabilization.fromProto(it.stabilizePreview),
69                 videoCaptureStabilization = Stabilization.fromProto(it.stabilizeVideo),
70                 targetFrameRate = it.targetFrameRate,
71                 captureMode = when (it.captureModeStatus) {
72                     CaptureModeProto.CAPTURE_MODE_SINGLE_STREAM -> CaptureMode.SINGLE_STREAM
73                     CaptureModeProto.CAPTURE_MODE_MULTI_STREAM -> CaptureMode.MULTI_STREAM
74                     else -> CaptureMode.MULTI_STREAM
75                 },
76                 dynamicRange = DynamicRange.fromProto(it.dynamicRangeStatus),
77                 imageFormat = ImageOutputFormat.fromProto(it.imageFormatStatus)
78             )
79         }
80 
81     override suspend fun getCurrentDefaultCameraAppSettings(): CameraAppSettings =
82         defaultCameraAppSettings.first()
83 
84     override suspend fun updateDefaultLensFacing(lensFacing: LensFacing) {
85         jcaSettings.updateData { currentSettings ->
86             currentSettings.toBuilder()
87                 .setDefaultLensFacing(lensFacing.toProto())
88                 .build()
89         }
90     }
91 
92     override suspend fun updateDarkModeStatus(darkMode: DarkMode) {
93         val newStatus = when (darkMode) {
94             DarkMode.DARK -> DarkModeProto.DARK_MODE_DARK
95             DarkMode.LIGHT -> DarkModeProto.DARK_MODE_LIGHT
96             DarkMode.SYSTEM -> DarkModeProto.DARK_MODE_SYSTEM
97         }
98         jcaSettings.updateData { currentSettings ->
99             currentSettings.toBuilder()
100                 .setDarkModeStatus(newStatus)
101                 .build()
102         }
103     }
104 
105     override suspend fun updateFlashModeStatus(flashMode: FlashMode) {
106         val newStatus = when (flashMode) {
107             FlashMode.AUTO -> FlashModeProto.FLASH_MODE_AUTO
108             FlashMode.ON -> FlashModeProto.FLASH_MODE_ON
109             FlashMode.OFF -> FlashModeProto.FLASH_MODE_OFF
110         }
111         jcaSettings.updateData { currentSettings ->
112             currentSettings.toBuilder()
113                 .setFlashModeStatus(newStatus)
114                 .build()
115         }
116     }
117 
118     override suspend fun updateTargetFrameRate(targetFrameRate: Int) {
119         jcaSettings.updateData { currentSettings ->
120             currentSettings.toBuilder()
121                 .setTargetFrameRate(targetFrameRate)
122                 .build()
123         }
124     }
125 
126     override suspend fun updateAspectRatio(aspectRatio: AspectRatio) {
127         val newStatus = when (aspectRatio) {
128             AspectRatio.NINE_SIXTEEN -> AspectRatioProto.ASPECT_RATIO_NINE_SIXTEEN
129             AspectRatio.THREE_FOUR -> AspectRatioProto.ASPECT_RATIO_THREE_FOUR
130             AspectRatio.ONE_ONE -> AspectRatioProto.ASPECT_RATIO_ONE_ONE
131         }
132         jcaSettings.updateData { currentSettings ->
133             currentSettings.toBuilder()
134                 .setAspectRatioStatus(newStatus)
135                 .build()
136         }
137     }
138 
139     override suspend fun updateCaptureMode(captureMode: CaptureMode) {
140         val newStatus = when (captureMode) {
141             CaptureMode.MULTI_STREAM -> CaptureModeProto.CAPTURE_MODE_MULTI_STREAM
142             CaptureMode.SINGLE_STREAM -> CaptureModeProto.CAPTURE_MODE_SINGLE_STREAM
143         }
144         jcaSettings.updateData { currentSettings ->
145             currentSettings.toBuilder()
146                 .setCaptureModeStatus(newStatus)
147                 .build()
148         }
149     }
150 
151     override suspend fun updatePreviewStabilization(stabilization: Stabilization) {
152         val newStatus = when (stabilization) {
153             Stabilization.ON -> PreviewStabilizationProto.PREVIEW_STABILIZATION_ON
154             Stabilization.OFF -> PreviewStabilizationProto.PREVIEW_STABILIZATION_OFF
155             else -> PreviewStabilizationProto.PREVIEW_STABILIZATION_UNDEFINED
156         }
157         jcaSettings.updateData { currentSettings ->
158             currentSettings.toBuilder()
159                 .setStabilizePreview(newStatus)
160                 .build()
161         }
162     }
163 
164     override suspend fun updateVideoStabilization(stabilization: Stabilization) {
165         val newStatus = when (stabilization) {
166             Stabilization.ON -> VideoStabilizationProto.VIDEO_STABILIZATION_ON
167             Stabilization.OFF -> VideoStabilizationProto.VIDEO_STABILIZATION_OFF
168             else -> VideoStabilizationProto.VIDEO_STABILIZATION_UNDEFINED
169         }
170         jcaSettings.updateData { currentSettings ->
171             currentSettings.toBuilder()
172                 .setStabilizeVideo(newStatus)
173                 .build()
174         }
175     }
176 
177     override suspend fun updateDynamicRange(dynamicRange: DynamicRange) {
178         jcaSettings.updateData { currentSettings ->
179             currentSettings.toBuilder()
180                 .setDynamicRangeStatus(dynamicRange.toProto())
181                 .build()
182         }
183     }
184 
185     override suspend fun updateImageFormat(imageFormat: ImageOutputFormat) {
186         jcaSettings.updateData { currentSettings ->
187             currentSettings.toBuilder()
188                 .setImageFormatStatus(imageFormat.toProto())
189                 .build()
190         }
191     }
192 }
193