Skip to content

Commit 5575ed8

Browse files
add filters to CodecMod SettingsActivity
1 parent b713a3a commit 5575ed8

7 files changed

Lines changed: 218 additions & 79 deletions

File tree

‎CodecMod/src/main/kotlin/com/programminghoch10/CodecMod/CodecStore.kt‎

Lines changed: 30 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,65 @@
11
package com.programminghoch10.CodecMod
22

3-
import java.util.*
43
import android.content.Context
54
import android.content.SharedPreferences
6-
import android.os.Build
5+
import androidx.core.content.edit
6+
import androidx.preference.PreferenceDataStore
77
import de.robv.android.xposed.XSharedPreferences
88

9-
class CodecStore {
9+
class CodecStore : PreferenceDataStore {
1010
private val sharedPreferences: SharedPreferences
11-
private val receivers: MutableList<OnCodecPreferenceChangedListenerMeta> = LinkedList<OnCodecPreferenceChangedListenerMeta>()
11+
private val receivers: MutableList<OnCodecPreferenceChangedListenerMeta> = mutableListOf()
1212

13-
internal constructor(context: Context) {
14-
this.sharedPreferences = context.getSharedPreferences(PREFERENCES, Context.MODE_WORLD_READABLE)
13+
constructor(context: Context) {
14+
sharedPreferences = context.getSharedPreferences(PREFERENCES, Context.MODE_WORLD_READABLE)
1515
}
1616

17-
internal constructor() {
18-
this.sharedPreferences = XSharedPreferences(BuildConfig.APPLICATION_ID, PREFERENCES)
17+
constructor() {
18+
sharedPreferences = XSharedPreferences(BuildConfig.APPLICATION_ID, PREFERENCES)
1919
}
2020

2121
fun getCodecPreference(mediaCodecInfo: MediaCodecInfoWrapper): Boolean {
22-
return sharedPreferences.getBoolean(getKey(mediaCodecInfo), DEFAULT_VALUE)
22+
return getBoolean(getKey(mediaCodecInfo), DEFAULT_VALUE)
2323
}
2424

25-
fun setCodecPreference(mediaCodecInfo: MediaCodecInfoWrapper, enabled: Boolean): Boolean {
26-
val success = sharedPreferences.edit().apply {
27-
if (REMOVE_DEFAULT_VALUE_FROM_CONFIG && enabled == DEFAULT_VALUE) {
28-
remove(getKey(mediaCodecInfo))
25+
override fun getBoolean(key: String, defValue: Boolean): Boolean {
26+
return sharedPreferences.getBoolean(key, defValue)
27+
}
28+
29+
override fun putBoolean(key: String, value: Boolean) {
30+
sharedPreferences.edit(commit = true) {
31+
if (REMOVE_DEFAULT_VALUE_FROM_CONFIG && value == DEFAULT_VALUE) {
32+
remove(key)
2933
} else {
30-
putBoolean(getKey(mediaCodecInfo), enabled)
34+
putBoolean(key, value)
3135
}
32-
}.commit()
33-
if (!success) return false
34-
dispatchOnCodecPreferenceChanged(mediaCodecInfo, enabled)
35-
return true
36+
}
37+
dispatchOnCodecPreferenceChanged(key, value)
3638
}
3739

3840
fun registerOnCodecPreferenceChangedListener(
3941
mediaCodecInfo: MediaCodecInfoWrapper,
4042
onCodecPreferenceChangedListener: OnCodecPreferenceChangedListener,
4143
) {
42-
val listener = OnCodecPreferenceChangedListenerMeta()
43-
listener.mediaCodecInfo = mediaCodecInfo
44-
listener.callback = onCodecPreferenceChangedListener
44+
val listener = OnCodecPreferenceChangedListenerMeta(
45+
mediaCodecInfo,
46+
onCodecPreferenceChangedListener,
47+
)
4548
receivers.add(listener)
4649
}
4750

48-
private fun dispatchOnCodecPreferenceChanged(mediaCodecInfo: MediaCodecInfoWrapper, enabled: Boolean) {
49-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
50-
receivers.stream().filter { r: OnCodecPreferenceChangedListenerMeta? ->
51-
getKey(r!!.mediaCodecInfo!!) == getKey(mediaCodecInfo)
52-
}.forEach { r: OnCodecPreferenceChangedListenerMeta? -> r!!.callback!!.onCodecPreferenceChanged(enabled) }
53-
} else {
54-
for (receiver in receivers) {
55-
if (getKey(receiver.mediaCodecInfo!!) == getKey(mediaCodecInfo)) receiver.callback!!.onCodecPreferenceChanged(
56-
enabled
57-
)
58-
}
59-
}
51+
private fun dispatchOnCodecPreferenceChanged(key: String, enabled: Boolean) {
52+
receivers.filter { getKey(it.mediaCodecInfo) == key }.forEach { it.callback.onCodecPreferenceChanged(enabled) }
6053
}
6154

6255
fun interface OnCodecPreferenceChangedListener {
6356
fun onCodecPreferenceChanged(value: Boolean)
6457
}
6558

66-
private class OnCodecPreferenceChangedListenerMeta {
67-
var mediaCodecInfo: MediaCodecInfoWrapper? = null
68-
var callback: OnCodecPreferenceChangedListener? = null
69-
}
59+
private data class OnCodecPreferenceChangedListenerMeta(
60+
val mediaCodecInfo: MediaCodecInfoWrapper,
61+
val callback: OnCodecPreferenceChangedListener,
62+
)
7063

7164
companion object {
7265
const val DEFAULT_VALUE: Boolean = true

‎CodecMod/src/main/kotlin/com/programminghoch10/CodecMod/MediaCodecInfoWrapper.kt‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ class MediaCodecInfoWrapper internal constructor(val originalMediaCodecInfo: Med
4444
val isDecoder: Boolean
4545
get() = !this.isEncoder
4646

47-
val supportedTypes: Array<String?>?
47+
val supportedTypes: Array<String>
4848
get() = originalMediaCodecInfo.getSupportedTypes()
49+
50+
val isVideoCodec get() = supportedTypes.any { it.startsWith("video") }
51+
val isAudioCodec get() = supportedTypes.any { it.startsWith("audio") }
4952
}
Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,59 @@
11
package com.programminghoch10.CodecMod
22

3-
import java.lang.String
4-
import kotlin.Boolean
5-
import kotlin.CharSequence
6-
import kotlin.text.StringBuilder
7-
import kotlin.toString
83
import android.content.Context
94
import android.media.MediaCodecInfo
105
import android.os.Build
6+
import androidx.annotation.RequiresApi
117
import androidx.preference.SwitchPreference
12-
import com.programminghoch10.CodecMod.SettingsActivity.SettingsFragment.Companion.SHOW_ALIASES
138

149
class MediaCodecPreference(context: Context, codecStore: CodecStore, val mediaCodecInfoWrapper: MediaCodecInfoWrapper) : SwitchPreference(context) {
1510

1611
constructor(context: Context, codecStore: CodecStore, mediaCodecInfo: MediaCodecInfo) : this(
1712
context, codecStore, MediaCodecInfoWrapper(mediaCodecInfo)
1813
)
1914

15+
private lateinit var filterSpec: FilterSpec
16+
fun setFilterSpec(filterSpec: FilterSpec) {
17+
this.filterSpec = filterSpec
18+
isVisible = when {
19+
!filterSpec.showAliases && mediaCodecInfoWrapper.isAlias -> false
20+
!filterSpec.showVideoCodecs && mediaCodecInfoWrapper.isVideoCodec -> false
21+
!filterSpec.showAudioCodecs && mediaCodecInfoWrapper.isAudioCodec -> false
22+
Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && !filterSpec.showHardwareCodecs && mediaCodecInfoWrapper.isHardwareAccelerated -> false
23+
Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && !filterSpec.showSoftwareCodecs && mediaCodecInfoWrapper.isSoftwareOnly -> false
24+
else -> true
25+
}
26+
notifyChanged() // to update summary
27+
}
28+
2029
init {
21-
isPersistent = false
30+
preferenceDataStore = codecStore
2231
setDefaultValue(CodecStore.DEFAULT_VALUE)
2332
key = CodecStore.getKey(mediaCodecInfoWrapper)
24-
25-
setOnPreferenceChangeListener { _, newValue ->
26-
codecStore.setCodecPreference(
27-
mediaCodecInfoWrapper, newValue as Boolean
28-
)
29-
}
30-
31-
codecStore.registerOnCodecPreferenceChangedListener(
32-
mediaCodecInfoWrapper, { value ->
33-
if (isChecked != value) setChecked(value)
34-
})
35-
36-
title = mediaCodecInfoWrapper.name
37-
if (mediaCodecInfoWrapper.name != mediaCodecInfoWrapper.canonicalName) title = title.toString() + "(${mediaCodecInfoWrapper.canonicalName})"
38-
39-
isChecked = codecStore.getCodecPreference(mediaCodecInfoWrapper)
33+
codecStore.registerOnCodecPreferenceChangedListener(mediaCodecInfoWrapper) { value -> isChecked = value }
34+
}
35+
36+
override fun getTitle(): CharSequence {
37+
val stringBuilder = StringBuilder()
38+
stringBuilder.append(mediaCodecInfoWrapper.name)
39+
if (mediaCodecInfoWrapper.name != mediaCodecInfoWrapper.canonicalName) stringBuilder.append(" (${mediaCodecInfoWrapper.canonicalName})")
40+
return stringBuilder
4041
}
4142

4243
override fun getSummary(): CharSequence {
44+
if (!this::filterSpec.isInitialized) return "awaiting ${FilterSpec::class.simpleName}"
4345
val summaryBuilder = StringBuilder()
4446
summaryBuilder.append(
4547
String.format(context.getString(R.string.supported_types), mediaCodecInfoWrapper.supportedTypes.contentToString())
4648
)
4749
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
48-
summaryBuilder.append("\n")
49-
summaryBuilder.append(
50-
String.format(context.getString(R.string.hardware_accelerated), mediaCodecInfoWrapper.isHardwareAccelerated)
51-
)
52-
summaryBuilder.append("\n")
53-
summaryBuilder.append(String.format(context.getString(R.string.software_only), mediaCodecInfoWrapper.isSoftwareOnly))
54-
if (SHOW_ALIASES) {
50+
if (filterSpec.showHardwareCodecs && filterSpec.showSoftwareCodecs) {
51+
summaryBuilder.append("\n")
52+
summaryBuilder.append(String.format(context.getString(R.string.hardware_accelerated), mediaCodecInfoWrapper.isHardwareAccelerated))
53+
summaryBuilder.append("\n")
54+
summaryBuilder.append(String.format(context.getString(R.string.software_only), mediaCodecInfoWrapper.isSoftwareOnly))
55+
}
56+
if (filterSpec.showAliases) {
5557
summaryBuilder.append("\n")
5658
summaryBuilder.append(String.format(context.getString(R.string.alias), mediaCodecInfoWrapper.isAlias))
5759
}
@@ -60,4 +62,12 @@ class MediaCodecPreference(context: Context, codecStore: CodecStore, val mediaCo
6062
}
6163
return summaryBuilder
6264
}
65+
66+
data class FilterSpec(
67+
val showAliases: Boolean,
68+
val showVideoCodecs: Boolean,
69+
val showAudioCodecs: Boolean,
70+
@RequiresApi(Build.VERSION_CODES.Q) val showHardwareCodecs: Boolean,
71+
@RequiresApi(Build.VERSION_CODES.Q) val showSoftwareCodecs: Boolean,
72+
)
6373
}

‎CodecMod/src/main/kotlin/com/programminghoch10/CodecMod/SettingsActivity.kt‎

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,16 @@ package com.programminghoch10.CodecMod
33
import android.media.MediaCodecList
44
import android.os.Build
55
import android.os.Bundle
6+
import android.util.Log
7+
import android.view.Menu
8+
import android.view.MenuInflater
9+
import android.view.MenuItem
610
import androidx.fragment.app.FragmentActivity
11+
import androidx.preference.Preference
712
import androidx.preference.PreferenceCategory
813
import androidx.preference.PreferenceFragmentCompat
14+
import androidx.preference.children
15+
import com.programminghoch10.CodecMod.CodecStore.Companion.DEFAULT_VALUE
916

1017
class SettingsActivity : FragmentActivity() {
1118
override fun onCreate(savedInstanceState: Bundle?) {
@@ -18,12 +25,64 @@ class SettingsActivity : FragmentActivity() {
1825
}
1926

2027
class SettingsFragment : PreferenceFragmentCompat() {
28+
lateinit var menu: Menu
29+
30+
val decodersPreferenceCategory get() = findPreference<PreferenceCategory>("category_decoders")!!
31+
val encodersPreferenceCategory get() = findPreference<PreferenceCategory>("category_encoders")!!
32+
val allHiddenByFiltersPreference get() = findPreference<Preference>("allHiddenByFilters")!!
33+
34+
val allPreferences get() = (encodersPreferenceCategory.children + decodersPreferenceCategory.children).filterIsInstance(MediaCodecPreference::class.java)
35+
36+
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
37+
inflater.inflate(R.menu.settings_options, menu)
38+
this.menu = menu
39+
reevaluateFilters()
40+
super.onCreateOptionsMenu(menu, inflater)
41+
}
42+
43+
override fun onOptionsItemSelected(item: MenuItem): Boolean {
44+
if (item.itemId in listOf(
45+
R.id.show_aliases,
46+
R.id.show_video_codecs,
47+
R.id.show_audio_codecs,
48+
R.id.show_hardware_codecs,
49+
R.id.show_software_codecs,
50+
)
51+
) {
52+
item.isChecked = !item.isChecked
53+
reevaluateFilters()
54+
return true
55+
}
56+
if (item.itemId in listOf(R.id.enable_all_visible, R.id.disable_all_visible)) {
57+
val checked = item.itemId == R.id.enable_all_visible
58+
allPreferences.forEach { it.isChecked = checked }
59+
return true
60+
}
61+
if (item.itemId == R.id.reset_configuration) {
62+
allPreferences.forEach { it.isChecked = DEFAULT_VALUE }
63+
return true
64+
}
65+
return super.onOptionsItemSelected(item)
66+
}
67+
68+
fun reevaluateFilters() {
69+
val filterSpec = MediaCodecPreference.FilterSpec(
70+
menu.findItem(R.id.show_aliases).isChecked,
71+
menu.findItem(R.id.show_video_codecs).isChecked,
72+
menu.findItem(R.id.show_audio_codecs).isChecked,
73+
menu.findItem(R.id.show_hardware_codecs).isChecked,
74+
menu.findItem(R.id.show_software_codecs).isChecked,
75+
)
76+
Log.d(this::class.java.simpleName, "reevaluateFilters: $filterSpec")
77+
allPreferences.forEach { it.setFilterSpec(filterSpec) }
78+
allHiddenByFiltersPreference.isVisible = allPreferences.all { !it.isVisible }
79+
}
80+
2181
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
2282
setPreferencesFromResource(R.xml.root_preferences, rootKey)
83+
setHasOptionsMenu(true)
2384
//getPreferenceManager().setSharedPreferencesName("codecs");
2485
val codecStore = CodecStore(requireContext())
25-
val decodersPreferenceCategory = findPreference<PreferenceCategory>("category_decoders")!!
26-
val encodersPreferenceCategory = findPreference<PreferenceCategory>("category_encoders")!!
2786

2887
var mediaCodecs: List<MediaCodecInfoWrapper>
2988
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
@@ -40,15 +99,11 @@ class SettingsActivity : FragmentActivity() {
4099
)
41100
}
42101
for (mediaCodecInfo in mediaCodecs) {
43-
if (mediaCodecInfo.isAlias && !SHOW_ALIASES) continue
44102
val preference = MediaCodecPreference(requireContext(), codecStore, mediaCodecInfo)
103+
preference.isIconSpaceReserved = false
45104
val preferenceCategory = if (mediaCodecInfo.isEncoder) encodersPreferenceCategory else decodersPreferenceCategory
46105
preferenceCategory.addPreference(preference)
47106
}
48107
}
49-
50-
companion object {
51-
const val SHOW_ALIASES = true
52-
}
53108
}
54109
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<menu
3+
xmlns:android="http://schemas.android.com/apk/res/android"
4+
xmlns:app="http://schemas.android.com/apk/res-auto"
5+
>
6+
<item
7+
android:id="@+id/show_video_codecs"
8+
android:checkable="true"
9+
android:checked="true"
10+
android:title="@string/show_video_codecs"
11+
app:showAsAction="never"
12+
/>
13+
<item
14+
android:id="@+id/show_audio_codecs"
15+
android:checkable="true"
16+
android:checked="true"
17+
android:title="@string/show_audio_codecs"
18+
app:showAsAction="never"
19+
/>
20+
<item
21+
android:id="@+id/show_hardware_codecs"
22+
android:checkable="true"
23+
android:checked="true"
24+
android:title="@string/show_hardware_codecs"
25+
app:showAsAction="never"
26+
/>
27+
<item
28+
android:id="@+id/show_software_codecs"
29+
android:checkable="true"
30+
android:checked="true"
31+
android:title="@string/show_software_codecs"
32+
app:showAsAction="never"
33+
/>
34+
<item
35+
android:id="@+id/show_aliases"
36+
android:checkable="true"
37+
android:checked="false"
38+
android:title="@string/show_aliases"
39+
app:showAsAction="never"
40+
/>
41+
<item
42+
android:id="@+id/enable_all_visible"
43+
android:title="@string/enable_all_visible"
44+
app:showAsAction="never"
45+
/>
46+
<item
47+
android:id="@+id/disable_all_visible"
48+
android:title="@string/disable_all_visible"
49+
app:showAsAction="never"
50+
/>
51+
<item
52+
android:id="@+id/reset_configuration"
53+
android:title="@string/reset_configuration"
54+
app:showAsAction="never"
55+
/>
56+
</menu>
Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
<resources>
22
<string name="app_name">CodecMod</string>
3-
<string name="description">This Module allows you to selectively disable audio/video hardware/software encoders/decoders.
4-
</string>
3+
<string name="description">Selectively disable audio/video hardware/software encoders/decoders.</string>
54
<string name="title_activity_settings">CodecMod Settings</string>
65
<string name="hardware_accelerated">Hardware-accelerated: %b</string>
76
<string name="software_only">Software-only: %b</string>
87
<string name="supported_types">Supported MIME-Types: %s</string>
98
<string name="alias">Alias: %b</string>
109
<string name="vendor">Vendor: %b</string>
10+
<string name="show_video_codecs">Show Video Codecs</string>
11+
<string name="show_audio_codecs">Show Audio Codecs</string>
12+
<string name="show_hardware_codecs">Show Hardware Codecs</string>
13+
<string name="show_software_codecs">Show Software Codecs</string>
14+
<string name="show_aliases">Show Aliases</string>
15+
<string name="enable_all_visible">Enable all visible codecs</string>
16+
<string name="disable_all_visible">Disable all visible codecs</string>
17+
<string name="reset_configuration">Reset Configuration</string>
18+
<string name="all_hidden_by_filters">All Codecs are hidden by the current filter settings.</string>
19+
<string name="category_decoders_title">Decoders</string>
20+
<string name="category_encoders_title">Encoders</string>
1121
</resources>

0 commit comments

Comments
 (0)