Browse Source

Add the new equalizer settings activity

merge-requests/2298/head
Nicolas Pomepuy 1 year ago
parent
commit
433df905ab
  1. 9
      application/resources/src/main/res/drawable/ic_export.xml
  2. 9
      application/resources/src/main/res/drawable/ic_invisible.xml
  3. 9
      application/resources/src/main/res/drawable/ic_visible.xml
  4. 4
      application/resources/src/main/res/values/strings.xml
  5. 3
      application/vlc-android/AndroidManifest.xml
  6. 137
      application/vlc-android/res/layout/equalizer_setting_item.xml
  7. 40
      application/vlc-android/res/layout/equalizer_settings_activity.xml
  8. 4
      application/vlc-android/res/xml/preferences.xml
  9. 229
      application/vlc-android/src/org/videolan/vlc/gui/EqualizerSettingsActivity.kt
  10. 2
      application/vlc-android/src/org/videolan/vlc/gui/preferences/PreferencesFragment.kt
  11. 4
      application/vlc-android/src/org/videolan/vlc/repository/EqualizerRepository.kt

9
application/resources/src/main/res/drawable/ic_export.xml

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:pathData="M480,624 L288,432l51,-51 105,105v-342h72v342l105,-105 51,51 -192,192ZM263.72,768Q234,768 213,746.85T192,696v-72h72v72h432v-72h72v72q0,29.7 -21.16,50.85Q725.68,768 695.96,768L263.72,768Z"
android:fillColor="#e8eaed"/>
</vector>

9
application/resources/src/main/res/drawable/ic_invisible.xml

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M12,6c3.79,0 7.17,2.13 8.82,5.5 -0.59,1.22 -1.42,2.27 -2.41,3.12l1.41,1.41c1.39,-1.23 2.49,-2.77 3.18,-4.53C21.27,7.11 17,4 12,4c-1.27,0 -2.49,0.2 -3.64,0.57l1.65,1.65C10.66,6.09 11.32,6 12,6zM10.93,7.14L13,9.21c0.57,0.25 1.03,0.71 1.28,1.28l2.07,2.07c0.08,-0.34 0.14,-0.7 0.14,-1.07C16.5,9.01 14.48,7 12,7c-0.37,0 -0.72,0.05 -1.07,0.14zM2.01,3.87l2.68,2.68C3.06,7.83 1.77,9.53 1,11.5 2.73,15.89 7,19 12,19c1.52,0 2.98,-0.29 4.32,-0.82l3.42,3.42 1.41,-1.41L3.42,2.45 2.01,3.87zM9.51,11.37l2.61,2.61c-0.04,0.01 -0.08,0.02 -0.12,0.02 -1.38,0 -2.5,-1.12 -2.5,-2.5 0,-0.05 0.01,-0.08 0.01,-0.13zM6.11,7.97l1.75,1.75c-0.23,0.55 -0.36,1.15 -0.36,1.78 0,2.48 2.02,4.5 4.5,4.5 0.63,0 1.23,-0.13 1.77,-0.36l0.98,0.98c-0.88,0.24 -1.8,0.38 -2.75,0.38 -3.79,0 -7.17,-2.13 -8.82,-5.5 0.7,-1.43 1.72,-2.61 2.93,-3.53z"
android:fillColor="#e8eaed"/>
</vector>

9
application/resources/src/main/res/drawable/ic_visible.xml

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M12,6c3.79,0 7.17,2.13 8.82,5.5C19.17,14.87 15.79,17 12,17s-7.17,-2.13 -8.82,-5.5C4.83,8.13 8.21,6 12,6m0,-2C7,4 2.73,7.11 1,11.5 2.73,15.89 7,19 12,19s9.27,-3.11 11,-7.5C21.27,7.11 17,4 12,4zM12,9c1.38,0 2.5,1.12 2.5,2.5S13.38,14 12,14s-2.5,-1.12 -2.5,-2.5S10.62,9 12,9m0,-2c-2.48,0 -4.5,2.02 -4.5,4.5S9.52,16 12,16s4.5,-2.02 4.5,-4.5S14.48,7 12,7z"
android:fillColor="#e8eaed"/>
</vector>

4
application/resources/src/main/res/values/strings.xml

@ -67,6 +67,7 @@
<string name="set_song_question">Set \'%1$s\' as ringtone?</string>
<string name="info">Information</string>
<string name="confirm_delete">Delete the file \'%1$s\'?</string>
<string name="equalizer_deleted">The equalizer has been deleted</string>
<string name="confirm_delete_eq">Are you sure you want to delete this preset?</string>
<string name="confirm_delete_vlc_eq">Are you sure you want to hide this preset?\nYou can restore it in the equalizer settings.</string>
<string name="confirm_replace_playlist">Are you sure you want to replace the playlist \'%1$s\'?</string>
@ -1148,6 +1149,9 @@
<string name="play_media">Play %s</string>
<string name="edit_eq_preset">Edit equalizer preset</string>
<string name="edit_eq_name_not_allowed">This name is not allowed</string>
<string name="export_equalizer">Export equalizer</string>
<string name="hide_equalizer">Hide equalizer</string>
<string name="show_equalizer">Show equalizer</string>
<!-- Duplication Warning Dialog -->
<string name="message_primary_default">Add duplicated item(s)?</string>

3
application/vlc-android/AndroidManifest.xml

@ -990,6 +990,9 @@
<activity
android:name=".gui.LibrariesActivity"
android:theme="@style/Theme.VLC"/>
<activity
android:name=".gui.EqualizerSettingsActivity"
android:theme="@style/Theme.VLC"/>
<activity
android:name=".gui.PinCodeActivity"
android:theme="@style/Theme.VLC"

137
application/vlc-android/res/layout/equalizer_setting_item.xml

@ -0,0 +1,137 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View" />
<variable
name="equalizer"
type="org.videolan.vlc.mediadb.models.EqualizerWithBands" />
<variable
name="holder"
type="org.videolan.vlc.gui.EqualizerSettingsAdapter.ViewHolder" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:clickable="true"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical"
android:focusable="true">
<ImageView
android:id="@+id/imageView22"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
app:equalizerImage="@{equalizer}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:srcCompat="@tools:sample/avatars" />
<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="8dp"
android:text="@{equalizer.equalizerEntry.name}"
android:textColor="?attr/font_default"
app:equalizerNameColor="@{equalizer}"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/export"
app:layout_constraintStart_toEndOf="@+id/imageView22"
app:layout_constraintTop_toTopOf="parent"
tools:text="Classical" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/enable"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:background="?attr/actionBarItemBackground"
android:clickable="true"
android:contentDescription="@string/show_equalizer"
android:focusable="true"
android:onClick="@{holder::onClickEnable}"
android:padding="12dp"
android:visibility="@{equalizer.equalizerEntry.presetIndex != -1 &amp;&amp; equalizer.equalizerEntry.isDisabled ? View.VISIBLE : View.GONE}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/disable"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_invisible"
app:tint="?attr/colorControlNormal" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/disable"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:background="?attr/actionBarItemBackground"
android:onClick="@{holder::onClickDisable}"
android:clickable="true"
android:contentDescription="@string/hide_equalizer"
android:focusable="true"
android:padding="12dp"
android:visibility="@{equalizer.equalizerEntry.presetIndex == -1 || equalizer.equalizerEntry.isDisabled ? View.GONE : View.VISIBLE}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_visible"
app:tint="?attr/colorControlNormal" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:background="?attr/actionBarItemBackground"
android:clickable="true"
android:contentDescription="@string/delete"
android:onClick="@{holder::onClickDelete}"
android:focusable="true"
android:padding="12dp"
android:visibility="@{equalizer.equalizerEntry.presetIndex == -1 ? View.VISIBLE : View.GONE}"
app:layout_constraintBottom_toBottomOf="@+id/enable"
app:layout_constraintEnd_toStartOf="@+id/enable"
app:layout_constraintTop_toTopOf="@+id/enable"
app:srcCompat="@drawable/ic_delete"
app:tint="?attr/colorControlNormal" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/export"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:background="?attr/actionBarItemBackground"
android:clickable="true"
android:contentDescription="@string/export_equalizer"
android:onClick="@{holder::onClickExport}"
android:focusable="true"
android:padding="12dp"
android:visibility="@{equalizer.equalizerEntry.presetIndex == -1 ? View.VISIBLE : View.GONE}"
app:layout_constraintBottom_toBottomOf="@+id/delete"
app:layout_constraintEnd_toStartOf="@+id/delete"
app:layout_constraintTop_toTopOf="@+id/delete"
app:srcCompat="@drawable/ic_export"
app:tint="?attr/colorControlNormal" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

40
application/vlc-android/res/layout/equalizer_settings_activity.xml

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:vlc="http://schemas.android.com/apk/res-auto">
<data>
</data>
<merge
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
layout="@layout/toolbar"
android:nextFocusLeft="@+id/ml_menu_search"
android:nextFocusRight="@+id/ml_menu_search"
android:nextFocusUp="@+id/ml_menu_search"
android:nextFocusDown="@+id/ml_menu_search"
android:nextFocusForward="@+id/ml_menu_search" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/equalizers"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal|top"
android:background="?attr/background_default"
android:clipToPadding="false"
android:paddingBottom="48dp"
android:fastScrollEnabled="true"
android:scrollbars="vertical"
vlc:layout_behavior="@string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</merge>
</layout>

4
application/vlc-android/res/xml/preferences.xml

@ -100,6 +100,10 @@
android:title="@string/audio_prefs_category"
android:key="audio_category"
android:fragment="org.videolan.television.ui.preferences.PreferencesAudio"/>
<Preference
android:title="@string/equalizer"
android:key="equalizer"/>
<Preference
android:title="@string/casting_category"
android:key="casting_category"/>

229
application/vlc-android/src/org/videolan/vlc/gui/EqualizerSettingsActivity.kt

@ -0,0 +1,229 @@
package org.videolan.vlc.gui
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Path
import android.graphics.Rect
import android.graphics.RectF
import android.os.Bundle
import android.util.Log
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.activity.viewModels
import androidx.annotation.ColorInt
import androidx.core.content.ContextCompat
import androidx.core.graphics.createBitmap
import androidx.databinding.BindingAdapter
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.appbar.MaterialToolbar
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.videolan.resources.AndroidDevices
import org.videolan.resources.util.applyOverscanMargin
import org.videolan.tools.dp
import org.videolan.vlc.BuildConfig
import org.videolan.vlc.R
import org.videolan.vlc.databinding.EqualizerSettingItemBinding
import org.videolan.vlc.databinding.EqualizerSettingsActivityBinding
import org.videolan.vlc.gui.helpers.SelectorViewHolder
import org.videolan.vlc.gui.helpers.UiTools
import org.videolan.vlc.mediadb.models.EqualizerWithBands
import org.videolan.vlc.repository.EqualizerRepository
/**
* Equalizer settings activity allowing to enable/disable/delete/export/import the presets
*
* @constructor Create empty Equalizer settings activity
*/
class EqualizerSettingsActivity : BaseActivity() {
private lateinit var adapter: EqualizerSettingsAdapter
private val model: EqualizerSettingsModel by viewModels {
EqualizerSettingsModelFactory(this, EqualizerRepository.getInstance(application))
}
internal lateinit var binding: EqualizerSettingsActivityBinding
override fun getSnackAnchorView(overAudioPlayer: Boolean) = binding.root
override val displayTitle = true
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.equalizer_settings_activity)
val toolbar = findViewById<MaterialToolbar>(R.id.main_toolbar)
setSupportActionBar(toolbar)
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setHomeAsUpIndicator(R.drawable.ic_close_up)
title = getString(R.string.equalizer)
binding.equalizers.layoutManager = LinearLayoutManager(this)
adapter = EqualizerSettingsAdapter { equalizer, type ->
when (type) {
ClickType.EQUALIZER_ENABLE -> model.enable(this, equalizer)
ClickType.EQUALIZER_DISABLE -> model.disable(this, equalizer)
ClickType.EQUALIZER_DELETE -> {
model.delete(this, equalizer)
UiTools.snackerConfirm(this, getString(R.string.equalizer_deleted), confirmMessage = R.string.undo) {
model.restore(this)
}
}
ClickType.EQUALIZER_EXPORT -> model.export(this, equalizer)
}
}
binding.equalizers.adapter = adapter
model.equalizerEntries.observe(this, Observer {
adapter.update(it)
})
if (AndroidDevices.isTv) applyOverscanMargin(this)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> finish()
}
return super.onOptionsItemSelected(item)
}
}
class EqualizerSettingsModel(private val equalizerRepository: EqualizerRepository) : ViewModel() {
private var oldEqualizer: EqualizerWithBands? = null
fun enable(context: Context, equalizer: EqualizerWithBands) = viewModelScope.launch(Dispatchers.IO) {
equalizerRepository.addOrUpdateEqualizerWithBands(context, equalizer.copy(equalizerEntry = equalizer.equalizerEntry.copy(isDisabled = false).apply { id = equalizer.equalizerEntry.id }))
}
fun disable(context: Context, equalizer: EqualizerWithBands) = viewModelScope.launch(Dispatchers.IO) {
equalizerRepository.addOrUpdateEqualizerWithBands(context, equalizer.copy(equalizerEntry = equalizer.equalizerEntry.copy(isDisabled = true).apply { id = equalizer.equalizerEntry.id }))
}
fun delete(context: Context, equalizer: EqualizerWithBands) = viewModelScope.launch(Dispatchers.IO) {
oldEqualizer = equalizer
equalizerRepository.delete(equalizer.equalizerEntry)
}
fun restore(context: Context) = viewModelScope.launch(Dispatchers.IO) {
equalizerRepository.addOrUpdateEqualizerWithBands(context, oldEqualizer!!)
}
fun export(context: Context, equalizer: EqualizerWithBands) = viewModelScope.launch(Dispatchers.IO) {
//todo add export
}
val equalizerEntries = equalizerRepository.equalizerEntriesUnfiltered.asLiveData()
}
class EqualizerSettingsModelFactory(private val context: Context, private val repository: EqualizerRepository) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(EqualizerSettingsModel::class.java)) {
@Suppress("UNCHECKED_CAST")
return EqualizerSettingsModel(repository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
class EqualizerSettingsAdapter(private val itemClickHandler: (equalizer: EqualizerWithBands, ClickType) -> Unit) : DiffUtilAdapter<EqualizerWithBands, EqualizerSettingsAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(EqualizerSettingItemBinding.inflate(LayoutInflater.from(parent.context), parent, false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.binding.equalizer = dataset[position]
}
override fun getItemCount() = dataset.size
inner class ViewHolder(vdb: EqualizerSettingItemBinding) : SelectorViewHolder<EqualizerSettingItemBinding>(vdb) {
init {
binding.holder = this
}
fun onClickEnable(@Suppress("UNUSED_PARAMETER") v: View) {
itemClickHandler.invoke(dataset[layoutPosition], ClickType.EQUALIZER_ENABLE)
}
fun onClickDisable(@Suppress("UNUSED_PARAMETER") v: View) {
itemClickHandler.invoke(dataset[layoutPosition], ClickType.EQUALIZER_DISABLE)
}
fun onClickDelete(@Suppress("UNUSED_PARAMETER") v: View) {
itemClickHandler.invoke(dataset[layoutPosition], ClickType.EQUALIZER_DELETE)
}
fun onClickExport(@Suppress("UNUSED_PARAMETER") v: View) {
itemClickHandler.invoke(dataset[layoutPosition], ClickType.EQUALIZER_EXPORT)
}
}
}
enum class ClickType {
EQUALIZER_DISABLE, EQUALIZER_ENABLE, EQUALIZER_DELETE, EQUALIZER_EXPORT
}
fun EqualizerWithBands.getBitmap(context: Context): Bitmap {
val imageSize = 72.dp
val step = 8.dp
val typedValue = TypedValue()
val theme = context.theme
theme.resolveAttribute(R.attr.default_divider, typedValue, true)
@ColorInt val color: Int = typedValue.data
val bitmap = createBitmap(imageSize, imageSize)
val canvas = Canvas(bitmap)
val paint = Paint()
val path = Path()
path.addRoundRect(RectF(0F, 0F, imageSize.toFloat(), imageSize.toFloat()), step.toFloat(), step.toFloat(), Path.Direction.CCW)
canvas.clipPath(path)
paint.color = if (equalizerEntry.presetIndex == -1) ContextCompat.getColor(context, R.color.orange500focus) else color
var x = 0
bands.sortedBy { it.index }.forEach {
val heightPc = (it.bandValue + 20) / 40
if (BuildConfig.DEBUG) Log.d("BandBitmap", "band value is ${it.bandValue} and height is ${heightPc * 38}")
canvas.drawRect(Rect(x, imageSize, x + step, imageSize - (66 * heightPc).toInt().dp), paint)
x += step
}
paint.color = color
canvas.drawPath(path, paint)
return bitmap
}
@BindingAdapter("equalizerImage")
fun equalizerImage(view: ImageView, item: EqualizerWithBands) {
view.setImageBitmap(item.getBitmap(view.context))
}
@BindingAdapter("equalizerNameColor")
fun equalizerNameColor(view: TextView, item: EqualizerWithBands) {
val typedValue = TypedValue()
val theme = view.context.theme
theme.resolveAttribute(if (item.equalizerEntry.isDisabled)R.attr.font_disabled else R.attr.font_default, typedValue, true)
@ColorInt val color: Int = typedValue.data
view.setTextColor(color)
}

2
application/vlc-android/src/org/videolan/vlc/gui/preferences/PreferencesFragment.kt

@ -53,6 +53,7 @@ import org.videolan.tools.Settings
import org.videolan.tools.Settings.isPinCodeSet
import org.videolan.tools.VIDEO_RESUME_PLAYBACK
import org.videolan.vlc.R
import org.videolan.vlc.gui.EqualizerSettingsActivity
import org.videolan.vlc.gui.PinCodeActivity
import org.videolan.vlc.gui.PinCodeReason
import org.videolan.vlc.gui.SecondaryActivity
@ -160,6 +161,7 @@ class PreferencesFragment : BasePreferenceFragment(), SharedPreferences.OnShared
"video_category" -> loadFragment(PreferencesVideo())
"subtitles_category" -> loadFragment(PreferencesSubtitles())
"audio_category" -> loadFragment(PreferencesAudio())
"equalizer" -> startActivity(Intent(requireActivity().applicationContext, EqualizerSettingsActivity::class.java))
"adv_category" -> loadFragment(PreferencesAdvanced())
"casting_category" -> loadFragment(PreferencesCasting())
"parental_control" -> {

4
application/vlc-android/src/org/videolan/vlc/repository/EqualizerRepository.kt

@ -41,6 +41,10 @@ class EqualizerRepository(private val equalizerDao: EqualizerDao, private val co
equalizerDao.getEnabledEqualizerEntries()
}
val equalizerEntriesUnfiltered by lazy {
equalizerDao.getAllEqualizerEntries()
}
fun getCurrentEqualizer(context: Context) = equalizerDao.getCurrentEqualizer(Settings.getInstance(context).getLong(KEY_CURRENT_EQUALIZER_ID, 1L))
/**

Loading…
Cancel
Save