more stuff

This commit is contained in:
deniscerri 2023-06-10 10:43:17 +02:00
parent 1e95bc1c2d
commit 6bddd7b3a4
No known key found for this signature in database
GPG key ID: 95C43D517D830350
11 changed files with 498 additions and 46 deletions

View file

@ -0,0 +1,448 @@
{
"formatVersion": 1,
"database": {
"version": 7,
"identityHash": "d34711f8239a4a966885543cd5454eab",
"entities": [
{
"tableName": "results",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `duration` TEXT NOT NULL, `thumb` TEXT NOT NULL, `website` TEXT NOT NULL, `playlistTitle` TEXT NOT NULL, `formats` TEXT NOT NULL, `urls` TEXT NOT NULL DEFAULT '', `chapters` TEXT, `creationTime` INTEGER NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "url",
"columnName": "url",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "author",
"columnName": "author",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "duration",
"columnName": "duration",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "thumb",
"columnName": "thumb",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "website",
"columnName": "website",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "playlistTitle",
"columnName": "playlistTitle",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "formats",
"columnName": "formats",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "urls",
"columnName": "urls",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "''"
},
{
"fieldPath": "chapters",
"columnName": "chapters",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "creationTime",
"columnName": "creationTime",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "history",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `duration` TEXT NOT NULL, `thumb` TEXT NOT NULL, `type` TEXT NOT NULL, `time` INTEGER NOT NULL, `downloadPath` TEXT NOT NULL, `website` TEXT NOT NULL, `format` TEXT NOT NULL, `downloadId` INTEGER NOT NULL DEFAULT 0)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "url",
"columnName": "url",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "author",
"columnName": "author",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "duration",
"columnName": "duration",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "thumb",
"columnName": "thumb",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "type",
"columnName": "type",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "time",
"columnName": "time",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "downloadPath",
"columnName": "downloadPath",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "website",
"columnName": "website",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "format",
"columnName": "format",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "downloadId",
"columnName": "downloadId",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "0"
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "downloads",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `thumb` TEXT NOT NULL, `duration` TEXT NOT NULL, `type` TEXT NOT NULL, `format` TEXT NOT NULL, `container` TEXT NOT NULL DEFAULT 'Default', `downloadSections` TEXT NOT NULL DEFAULT '', `allFormats` TEXT NOT NULL, `downloadPath` TEXT NOT NULL, `website` TEXT NOT NULL, `downloadSize` TEXT NOT NULL, `playlistTitle` TEXT NOT NULL, `audioPreferences` TEXT NOT NULL, `videoPreferences` TEXT NOT NULL, `customFileNameTemplate` TEXT NOT NULL, `SaveThumb` INTEGER NOT NULL, `status` TEXT NOT NULL DEFAULT 'Queued', `downloadStartTime` INTEGER NOT NULL DEFAULT 0)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "url",
"columnName": "url",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "author",
"columnName": "author",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "thumb",
"columnName": "thumb",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "duration",
"columnName": "duration",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "type",
"columnName": "type",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "format",
"columnName": "format",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "container",
"columnName": "container",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "'Default'"
},
{
"fieldPath": "downloadSections",
"columnName": "downloadSections",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "''"
},
{
"fieldPath": "allFormats",
"columnName": "allFormats",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "downloadPath",
"columnName": "downloadPath",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "website",
"columnName": "website",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "downloadSize",
"columnName": "downloadSize",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "playlistTitle",
"columnName": "playlistTitle",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "audioPreferences",
"columnName": "audioPreferences",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "videoPreferences",
"columnName": "videoPreferences",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "customFileNameTemplate",
"columnName": "customFileNameTemplate",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "SaveThumb",
"columnName": "SaveThumb",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "status",
"columnName": "status",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "'Queued'"
},
{
"fieldPath": "downloadStartTime",
"columnName": "downloadStartTime",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "0"
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "commandTemplates",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `title` TEXT NOT NULL, `content` TEXT NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "content",
"columnName": "content",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "searchHistory",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `query` TEXT NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "query",
"columnName": "query",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "templateShortcuts",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `content` TEXT NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "content",
"columnName": "content",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "cookies",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `content` TEXT NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "url",
"columnName": "url",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "content",
"columnName": "content",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": true,
"columnNames": [
"id"
]
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd34711f8239a4a966885543cd5454eab')"
]
}
}

View file

@ -8,13 +8,14 @@ import com.deniscerri.ytdlnis.database.models.*
@TypeConverters(Converters::class)
@Database(
entities = [ResultItem::class, HistoryItem::class, DownloadItem::class, CommandTemplate::class, SearchHistoryItem::class, TemplateShortcut::class, CookieItem::class],
version = 6,
version = 7,
autoMigrations = [
AutoMigration (from = 1, to = 2),
AutoMigration (from = 2, to = 3),
AutoMigration (from = 3, to = 4),
AutoMigration (from = 4, to = 5),
AutoMigration (from = 5, to = 6)
AutoMigration (from = 5, to = 6),
AutoMigration (from = 6, to = 7)
]
)
abstract class DBManager : RoomDatabase(){

View file

@ -1,20 +1,20 @@
package com.deniscerri.ytdlnis.database.dao
import androidx.lifecycle.LiveData
import androidx.room.*
import com.deniscerri.ytdlnis.database.models.DownloadItem
import kotlinx.coroutines.flow.Flow
@Dao
interface DownloadDao {
@Query("SELECT * FROM downloads ORDER BY status")
fun getAllDownloads() : Flow<List<DownloadItem>>
fun getAllDownloads() : LiveData<List<DownloadItem>>
@Query("SELECT * FROM downloads WHERE status='Active'")
fun getActiveDownloads() : Flow<List<DownloadItem>>
fun getActiveDownloads() : LiveData<List<DownloadItem>>
@Query("SELECT COUNT(*) FROM downloads WHERE status='Active'")
fun getActiveDownloadsCount() : Flow<Int>
fun getActiveDownloadsCount() : LiveData<Int>
@Query("SELECT * FROM downloads WHERE status='Active'")
fun getActiveDownloadsList() : List<DownloadItem>
@ -23,25 +23,25 @@ interface DownloadDao {
fun getActiveAndQueuedDownloadsList() : List<DownloadItem>
@Query("SELECT * FROM downloads WHERE status='Queued' ORDER BY downloadStartTime, id")
fun getQueuedDownloads() : Flow<List<DownloadItem>>
fun getQueuedDownloads() : LiveData<List<DownloadItem>>
@Query("SELECT * FROM downloads WHERE status='Queued' ORDER BY downloadStartTime, id")
fun getQueuedDownloadsList() : List<DownloadItem>
@Query("SELECT * FROM downloads WHERE status='Cancelled' ORDER BY id DESC")
fun getCancelledDownloads() : Flow<List<DownloadItem>>
fun getCancelledDownloads() : LiveData<List<DownloadItem>>
@Query("SELECT * FROM downloads WHERE status='Cancelled' ORDER BY id DESC")
fun getCancelledDownloadsList() : List<DownloadItem>
@Query("SELECT * FROM downloads WHERE status='Error' ORDER BY id DESC")
fun getErroredDownloads() : Flow<List<DownloadItem>>
fun getErroredDownloads() : LiveData<List<DownloadItem>>
@Query("SELECT * FROM downloads WHERE status='Error' ORDER BY id DESC")
fun getErroredDownloadsList() : List<DownloadItem>
@Query("SELECT * FROM downloads WHERE status='Processing' ORDER BY id DESC")
fun getProcessingDownloads() : Flow<List<DownloadItem>>
fun getProcessingDownloads() : LiveData<List<DownloadItem>>
@Query("SELECT * FROM downloads WHERE id=:id LIMIT 1")
fun getDownloadById(id: Long) : DownloadItem

View file

@ -1,16 +1,16 @@
package com.deniscerri.ytdlnis.database.dao
import androidx.lifecycle.LiveData
import androidx.room.*
import com.deniscerri.ytdlnis.database.models.ResultItem
import kotlinx.coroutines.flow.Flow
@Dao
interface ResultDao {
@Query("SELECT * FROM results")
fun getResults() : Flow<List<ResultItem>>
fun getResults() : LiveData<List<ResultItem>>
@Query("SELECT COUNT(id) FROM results")
fun getCount() : Flow<Int>
fun getCount() : LiveData<Int>
@Query("SELECT COUNT(id) FROM results")
fun getCountInt() :Int

View file

@ -1,18 +1,18 @@
package com.deniscerri.ytdlnis.database.repository
import androidx.lifecycle.LiveData
import com.deniscerri.ytdlnis.database.Converters
import com.deniscerri.ytdlnis.database.dao.DownloadDao
import com.deniscerri.ytdlnis.database.models.DownloadItem
import kotlinx.coroutines.flow.Flow
class DownloadRepository(private val downloadDao: DownloadDao) {
val allDownloads : Flow<List<DownloadItem>> = downloadDao.getAllDownloads()
val activeDownloads : Flow<List<DownloadItem>> = downloadDao.getActiveDownloads()
val activeDownloadsCount : Flow<Int> = downloadDao.getActiveDownloadsCount()
val queuedDownloads : Flow<List<DownloadItem>> = downloadDao.getQueuedDownloads()
val cancelledDownloads : Flow<List<DownloadItem>> = downloadDao.getCancelledDownloads()
val erroredDownloads : Flow<List<DownloadItem>> = downloadDao.getErroredDownloads()
val processingDownloads : Flow<List<DownloadItem>> = downloadDao.getProcessingDownloads()
val allDownloads : LiveData<List<DownloadItem>> = downloadDao.getAllDownloads()
val activeDownloads : LiveData<List<DownloadItem>> = downloadDao.getActiveDownloads()
val activeDownloadsCount : LiveData<Int> = downloadDao.getActiveDownloadsCount()
val queuedDownloads : LiveData<List<DownloadItem>> = downloadDao.getQueuedDownloads()
val cancelledDownloads : LiveData<List<DownloadItem>> = downloadDao.getCancelledDownloads()
val erroredDownloads : LiveData<List<DownloadItem>> = downloadDao.getErroredDownloads()
val processingDownloads : LiveData<List<DownloadItem>> = downloadDao.getProcessingDownloads()
enum class Status {
Active, Queued, Error, Processing, Cancelled
@ -53,7 +53,7 @@ class DownloadRepository(private val downloadDao: DownloadDao) {
}
fun getQueuedDownloads() : List<DownloadItem> {
return downloadDao.getQueuedDownloadsList();
return downloadDao.getQueuedDownloadsList()
}
fun getCancelledDownloads() : List<DownloadItem> {

View file

@ -2,17 +2,17 @@ package com.deniscerri.ytdlnis.database.repository
import android.content.Context
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.deniscerri.ytdlnis.database.dao.CommandTemplateDao
import com.deniscerri.ytdlnis.database.dao.ResultDao
import com.deniscerri.ytdlnis.database.models.CommandTemplate
import com.deniscerri.ytdlnis.database.models.ResultItem
import com.deniscerri.ytdlnis.util.InfoUtil
import kotlinx.coroutines.flow.Flow
class ResultRepository(private val resultDao: ResultDao, private val commandTemplateDao: CommandTemplateDao, private val context: Context) {
private val tag: String = "ResultRepository"
val allResults : Flow<List<ResultItem>> = resultDao.getResults()
val allResults : LiveData<List<ResultItem>> = resultDao.getResults()
var itemCount = MutableLiveData(-1)
suspend fun insert(it: ResultItem){

View file

@ -11,7 +11,6 @@ import android.util.DisplayMetrics
import android.widget.Toast
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope
import androidx.preference.PreferenceManager
import androidx.work.Constraints
@ -41,6 +40,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import java.util.Locale
import java.util.concurrent.TimeUnit
@ -76,13 +76,13 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
commandTemplateDao = DBManager.getInstance(application).commandTemplateDao
infoUtil = InfoUtil(application)
allDownloads = repository.allDownloads.asLiveData()
queuedDownloads = repository.queuedDownloads.asLiveData()
activeDownloads = repository.activeDownloads.asLiveData()
activeDownloadsCount = repository.activeDownloadsCount.asLiveData()
processingDownloads = repository.processingDownloads.asLiveData()
cancelledDownloads = repository.cancelledDownloads.asLiveData()
erroredDownloads = repository.erroredDownloads.asLiveData()
allDownloads = repository.allDownloads
queuedDownloads = repository.queuedDownloads
activeDownloads = repository.activeDownloads
activeDownloadsCount = repository.activeDownloadsCount
processingDownloads = repository.processingDownloads
cancelledDownloads = repository.cancelledDownloads
erroredDownloads = repository.erroredDownloads
videoQualityPreference = sharedPreferences.getString("video_quality", application.getString(R.string.best_quality)).toString()
formatIDPreference = sharedPreferences.getString("format_id", "").toString()
@ -257,12 +257,6 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
else -> ""
}
val downloadPath = when(historyItem.type){
Type.audio -> sharedPreferences.getString("music_path", FileUtil.getDefautAudioPath())
Type.video -> sharedPreferences.getString("video_path", FileUtil.getDefautVideoPath())
else -> sharedPreferences.getString("command_path", FileUtil.getDefaultCommandPath())
}
val container = when(historyItem.type){
Type.audio -> sharedPreferences.getString("audio_format", "Default")!!
Type.video -> sharedPreferences.getString("video_format", "Default")!!
@ -285,7 +279,7 @@ class DownloadViewModel(application: Application) : AndroidViewModel(application
container,
"",
ArrayList(),
downloadPath!!, historyItem.website, "", "", audioPreferences, videoPreferences,customFileNameTemplate!!, saveThumb, DownloadRepository.Status.Processing.toString(), 0
File(historyItem.downloadPath).parent!!, historyItem.website, "", "", audioPreferences, videoPreferences,customFileNameTemplate!!, saveThumb, DownloadRepository.Status.Processing.toString(), 0
)
}

View file

@ -6,7 +6,6 @@ import android.util.Log
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope
import androidx.preference.PreferenceManager
import com.deniscerri.ytdlnis.App
@ -35,7 +34,7 @@ class ResultViewModel(application: Application) : AndroidViewModel(application)
val commandDao = DBManager.getInstance(application).commandTemplateDao
repository = ResultRepository(dao, commandDao, getApplication<Application>().applicationContext)
searchHistoryRepository = SearchHistoryRepository(DBManager.getInstance(application).searchHistoryDao)
items = repository.allResults.asLiveData()
items = repository.allResults
loadingItems.postValue(false)
itemCount = repository.itemCount
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(application)
@ -104,7 +103,7 @@ class ResultViewModel(application: Application) : AndroidViewModel(application)
res
}
}
fun getQueryType(inputQuery: String) : String {
private fun getQueryType(inputQuery: String) : String {
var type = "Search"
val p = Pattern.compile("^(https?)://(www.)?(music.)?youtu(.be)?")
val m = p.matcher(inputQuery)

View file

@ -122,7 +122,7 @@ class DownloadWorker(
if (sponsorBlockFilters.isNotEmpty()) {
val filters = java.lang.String.join(",", sponsorBlockFilters.filter { it.isNotBlank() })
request.addOption("--sponsorblock-remove", filters)
if (filters.isNotBlank()) request.addOption("--sponsorblock-remove", filters)
}
if(downloadItem.title.isNotBlank()){
@ -145,6 +145,10 @@ class DownloadWorker(
downloadItem.customFileNameTemplate += " %(section_title)s %(autonumber)s"
request.addOption("--output-na-placeholder", " ")
}
if (sharedPreferences.getBoolean("use_audio_quality", false)){
request.addOption("--audio-quality", sharedPreferences.getInt("audio_quality", 0))
}
}
if (sharedPreferences.getBoolean("restrict_filenames", true)) {
@ -207,8 +211,6 @@ class DownloadWorker(
request.addOption("--parse-metadata", "%(album,title)s:%(meta_album)s")
}
request.addOption("--audio-quality", sharedPreferences.getInt("audio_quality", 0))
if (downloadItem.audioPreferences.splitByChapters && downloadItem.downloadSections.isBlank()){
request.addOption("--split-chapters")
request.addOption("-P", tempFileDir.absolutePath)

View file

@ -278,4 +278,5 @@
<string name="format_filtering_hint_2">All items must either be audio or video to use this option</string>
<string name="piped_instance">Piped Instance</string>
<string name="piped_instance_summary">Write a PIPED API Server, the app can use for youtube queries and formats</string>
<string name="custom_audio_quality">Use Custom Audio Quality</string>
</resources>

View file

@ -96,11 +96,18 @@
app:useSimpleSummaryProvider="true"
app:title="@string/video_format" />
<SwitchPreferenceCompat
android:widgetLayout="@layout/preferece_material_switch"
app:defaultValue="false"
app:icon="@drawable/ic_music"
app:key="use_audio_quality"
app:title="@string/custom_audio_quality" />
<SeekBarPreference
android:defaultValue="0"
android:icon="@drawable/ic_music"
android:max="10"
android:dependency="use_audio_quality"
app:key="audio_quality"
app:min="0"
app:showSeekBarValue="true"