Skip to content

Commit 0f01298

Browse files
committed
Make video bitrate setting UI functional
1 parent 7ad7b2c commit 0f01298

1 file changed

Lines changed: 140 additions & 35 deletions

File tree

app/src/main/java/app/grapheneos/camera/ui/activities/MoreSettings.kt

Lines changed: 140 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,30 @@ package app.grapheneos.camera.ui.activities
22

33
import android.content.Context
44
import android.content.Intent
5-
import android.graphics.Color
65
import android.graphics.Rect
76
import android.os.Bundle
87
import android.view.KeyEvent
98
import android.view.MotionEvent
109
import android.view.View
1110
import android.view.inputmethod.EditorInfo
1211
import android.view.inputmethod.InputMethodManager
12+
import android.widget.AdapterView
13+
import android.widget.ArrayAdapter
14+
import android.widget.AutoCompleteTextView
1315
import android.widget.Button
1416
import android.widget.EditText
1517
import android.widget.TextView
1618
import androidx.activity.enableEdgeToEdge
1719
import androidx.activity.result.contract.ActivityResultContracts
1820
import androidx.appcompat.app.AppCompatActivity
19-
import androidx.core.view.OnApplyWindowInsetsListener
2021
import androidx.core.view.ViewCompat
2122
import androidx.core.view.WindowInsetsCompat
2223
import app.grapheneos.camera.CamConfig
2324
import app.grapheneos.camera.CapturedItems
24-
import app.grapheneos.camera.NumInputFilter
25+
import app.grapheneos.camera.inputfilter.NumLimitFilter
2526
import app.grapheneos.camera.R
2627
import app.grapheneos.camera.databinding.MoreSettingsBinding
28+
import app.grapheneos.camera.inputfilter.CustomNumFilter
2729
import app.grapheneos.camera.util.storageLocationToUiString
2830
import com.google.android.material.dialog.MaterialAlertDialogBuilder
2931
import com.google.android.material.snackbar.Snackbar
@@ -44,6 +46,10 @@ open class MoreSettings : AppCompatActivity(), TextView.OnEditorActionListener {
4446
private lateinit var iFField: EditText
4547
private lateinit var vFField: EditText
4648

49+
private lateinit var videoBitRateValueField: EditText
50+
private lateinit var videoBitRateUnitField: AutoCompleteTextView
51+
private lateinit var videoBitRateUnitFieldAdapter: ArrayAdapter<String>
52+
4753
private val dirPickerHandler = registerForActivityResult(
4854
ActivityResultContracts.StartActivityForResult()
4955
) {
@@ -150,9 +156,130 @@ open class MoreSettings : AppCompatActivity(), TextView.OnEditorActionListener {
150156
pQField.setText(camConfig.photoQuality.toString())
151157
}
152158

153-
pQField.filters = arrayOf(NumInputFilter(this))
159+
pQField.filters = arrayOf(NumLimitFilter(
160+
min = PHOTO_QUALITY_MIN,
161+
max = PHOTO_QUALITY_MAX,
162+
onOutOfRange = {
163+
showMessage(getString(R.string.photo_quality_number_limit, PHOTO_QUALITY_MIN, PHOTO_QUALITY_MAX))
164+
}
165+
))
166+
pQField.onFocusChangeListener = object: View.OnFocusChangeListener {
167+
override fun onFocusChange(v: View, hasFocus: Boolean) {
168+
if (!hasFocus) {
169+
if (pQField.text.isEmpty()) {
170+
camConfig.photoQuality = 0
171+
172+
showMessage(
173+
getString(R.string.photo_quality_was_set_to_auto)
174+
)
175+
} else {
176+
try {
177+
camConfig.photoQuality =
178+
Integer.parseInt(pQField.text.toString())
179+
} catch (_: Exception) {
180+
camConfig.photoQuality = 0
181+
182+
}
183+
}
184+
}
185+
}
186+
}
154187
pQField.setOnEditorActionListener(this)
155188

189+
// Video bitrate value field
190+
videoBitRateValueField = binding.videoBitrateValueField
191+
192+
if (camConfig.videoBitRateValue != 0) {
193+
videoBitRateValueField.setText(camConfig.videoBitRateValue.toString())
194+
}
195+
196+
videoBitRateValueField.filters = arrayOf(
197+
CustomNumFilter(
198+
shouldAcceptNumber = { value ->
199+
val calculatedBitRate = value * camConfig.videoBitRateMultiplier
200+
if (calculatedBitRate >= VIDEO_BITRATE_MIN && calculatedBitRate <= VIDEO_BITRATE_MAX) {
201+
true
202+
} else {
203+
val minVideoBitrateInUnits = (VIDEO_BITRATE_MIN.toFloat() / camConfig.videoBitRateMultiplier).coerceAtLeast(1f).toInt()
204+
val maxVideoBitrateInUnits = VIDEO_BITRATE_MAX / camConfig.videoBitRateMultiplier
205+
206+
showMessage(getString(R.string.video_bitrate_number_limit, minVideoBitrateInUnits, camConfig.videoBitRateUnit, maxVideoBitrateInUnits, camConfig.videoBitRateUnit))
207+
false
208+
}
209+
}
210+
)
211+
)
212+
videoBitRateValueField.onFocusChangeListener = object: View.OnFocusChangeListener {
213+
override fun onFocusChange(v: View, hasFocus: Boolean) {
214+
if (!hasFocus) {
215+
if (videoBitRateValueField.text.isEmpty()) {
216+
camConfig.videoBitRateValue = 0
217+
218+
showMessage(
219+
getString(R.string.video_bitrate_was_set_to_auto)
220+
)
221+
} else {
222+
try {
223+
camConfig.videoBitRateValue =
224+
Integer.parseInt(videoBitRateValueField.text.toString())
225+
} catch (exception: Exception) {
226+
camConfig.videoBitRateValue = 0
227+
showMessage(
228+
getString(R.string.video_bitrate_was_set_to_auto)
229+
)
230+
}
231+
}
232+
}
233+
}
234+
}
235+
videoBitRateValueField.setOnEditorActionListener(this)
236+
237+
// Video bit rate unit field
238+
videoBitRateUnitField = binding.videoBitrateUnitSpinner
239+
240+
videoBitRateUnitFieldAdapter = ArrayAdapter<String>(
241+
this,
242+
android.R.layout.simple_spinner_item,
243+
CamConfig.VIDEO_BITRATE_UNITS
244+
)
245+
246+
videoBitRateUnitFieldAdapter.setDropDownViewResource(
247+
android.R.layout.simple_spinner_dropdown_item
248+
)
249+
250+
videoBitRateUnitField.setAdapter(videoBitRateUnitFieldAdapter)
251+
252+
videoBitRateUnitField.setText(camConfig.videoBitRateUnit, false)
253+
254+
videoBitRateUnitField.onItemClickListener = object : AdapterView.OnItemClickListener {
255+
override fun onItemClick(
256+
parent: AdapterView<*>?,
257+
view: View?,
258+
position: Int,
259+
id: Long
260+
) {
261+
val selectedBitRateUnit = CamConfig.VIDEO_BITRATE_UNITS[position]
262+
camConfig.videoBitRateUnit = selectedBitRateUnit
263+
264+
// Update bitrate value to highest possible valid value when it exceeds VIDEO_BITRATE_MAX
265+
// while switching to a higher value unit (as a fallback to prevent overflow while switching
266+
// from say MAX_INT b/s to MAX_INT mb/s (b/s --> mb/s) which would lead to unexpected behavior
267+
val maxVideoBitrateWithUnits = VIDEO_BITRATE_MAX / camConfig.videoBitRateMultiplier
268+
if (camConfig.videoBitRateValue > maxVideoBitrateWithUnits) {
269+
camConfig.videoBitRateValue = maxVideoBitrateWithUnits
270+
videoBitRateValueField.setText(maxVideoBitrateWithUnits.toString())
271+
}
272+
}
273+
}
274+
275+
binding.refreshVideoBitrate.setOnClickListener {
276+
camConfig.videoBitRateValue = 0
277+
videoBitRateValueField.setText("")
278+
showMessage(
279+
getString(R.string.video_bitrate_was_set_to_auto)
280+
)
281+
}
282+
156283
iFField = binding.imageFormatSettingField
157284
iFField.setOnEditorActionListener(this)
158285

@@ -267,7 +394,7 @@ open class MoreSettings : AppCompatActivity(), TextView.OnEditorActionListener {
267394
v.getGlobalVisibleRect(outRect)
268395
if (!outRect.contains(event.rawX.toInt(), event.rawY.toInt())) {
269396
clearFocus()
270-
dumpData()
397+
// dumpData()
271398
}
272399
}
273400
}
@@ -284,39 +411,10 @@ open class MoreSettings : AppCompatActivity(), TextView.OnEditorActionListener {
284411
}
285412
}
286413

287-
private fun dumpData() {
288-
289-
// Dump state of photo quality
290-
if (pQField.text.isEmpty()) {
291-
camConfig.photoQuality = 0
292-
293-
showMessage(
294-
getString(R.string.photo_quality_was_set_to_auto)
295-
)
296-
} else {
297-
try {
298-
299-
camConfig.photoQuality =
300-
Integer.parseInt(pQField.text.toString())
301-
302-
} catch (exception: Exception) {
303-
304-
camConfig.photoQuality = 0
305-
306-
}
307-
}
308-
309-
// // Dump state of image format
310-
// camConfig.imageFormat = iFField.text.toString()
311-
//
312-
// // Dump state of video format
313-
// camConfig.videoFormat = vFField.text.toString()
314-
}
315-
316414
override fun onEditorAction(p0: TextView?, id: Int, p2: KeyEvent?): Boolean {
317415
return if (id == EditorInfo.IME_ACTION_DONE) {
318416
clearFocus()
319-
dumpData()
417+
// dumpData()
320418
true
321419
} else false
322420
}
@@ -332,6 +430,13 @@ open class MoreSettings : AppCompatActivity(), TextView.OnEditorActionListener {
332430
}
333431

334432
companion object {
433+
const val PHOTO_QUALITY_MIN = 1
434+
const val PHOTO_QUALITY_MAX = 100
435+
436+
// Video bitrate in bs
437+
const val VIDEO_BITRATE_MIN = 1
438+
const val VIDEO_BITRATE_MAX = Integer.MAX_VALUE
439+
335440
private var camConfigId = 0L
336441
private var staticCamConfig: CamConfig? = null
337442

0 commit comments

Comments
 (0)