Improved account's codec comfiguration

This commit is contained in:
Juha Heinanen
2022-09-11 09:21:09 +03:00
13 changed files with 234 additions and 76 deletions

View File

@ -1,5 +1,6 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion = 32
@ -23,6 +24,7 @@ android {
lintOptions {
checkDependencies true
}
vectorDrawables.useSupportLibrary = true
}
splits {
abi {
@ -38,6 +40,7 @@ android {
}
buildFeatures {
viewBinding true
dataBinding true
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
@ -52,7 +55,7 @@ android {
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.appcompat:appcompat:1.5.0'
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation 'com.google.android.material:material:1.6.1'
@ -61,7 +64,7 @@ dependencies {
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
implementation "androidx.preference:preference-ktx:1.2.0"
implementation "androidx.exifinterface:exifinterface:1.3.3"
implementation "androidx.core:core-ktx:1.8.0"
implementation "androidx.core:core-ktx:1.9.0"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1'
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.activity:activity-ktx:1.5.1"

View File

@ -0,0 +1,3 @@
package com.tutpro.baresip
data class Codec(val name: String, var enabled: Boolean)

View File

@ -1,22 +1,26 @@
package com.tutpro.baresip
import android.annotation.SuppressLint
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.*
import android.widget.LinearLayout.LayoutParams
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.ItemTouchHelper.*
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.tutpro.baresip.databinding.ActivityCodecsBinding
import java.util.*
class CodecsActivity : AppCompatActivity() {
private lateinit var binding: ActivityCodecsBinding
private lateinit var acc: Account
private lateinit var ua: UserAgent
private lateinit var codecsAdapter: CodecsAdapter
private var aor = ""
private var newCodecs = ArrayList<String>()
private var newCodecs = ArrayList<Codec>()
private var media = ""
override fun onCreate(savedInstanceState: Bundle?) {
@ -35,68 +39,86 @@ class CodecsActivity : AppCompatActivity() {
ua = UserAgent.ofAor(aor)!!
acc = ua.account
val codecs: ArrayList<String>
val allCodecs: ArrayList<String>
val accCodecs: ArrayList<String>
val title = binding.CodecsTitle
val codecsTitle = binding.CodecsTitle
val codecList = binding.CodecList
itemTouchHelper.attachToRecyclerView(codecList)
if (media == "audio") {
title.text = getString(R.string.audio_codecs)
codecs = ArrayList(Api.audio_codecs().split(","))
codecsTitle.text = getString(R.string.audio_codecs)
allCodecs = ArrayList(Api.audio_codecs().split(","))
accCodecs = acc.audioCodec
} else {
title.text = getString(R.string.video_codecs)
codecs = ArrayList(Api.video_codecs().split(",").distinct())
codecsTitle.text = getString(R.string.video_codecs)
allCodecs = ArrayList(Api.video_codecs().split(",").distinct())
accCodecs = acc.videoCodec
}
newCodecs.addAll(accCodecs)
for (codec in accCodecs)
newCodecs.add(Codec(codec, true))
for (codec in allCodecs)
if (codec !in accCodecs)
newCodecs.add(Codec(codec, false))
while (newCodecs.size < codecs.size) newCodecs.add("-")
codecsAdapter = CodecsAdapter(newCodecs)
val layout = binding.SpinnerTable
val spinnerList = Array(codecs.size) { ArrayList<String>() }
for (i in codecs.indices) {
val spinner = Spinner(applicationContext)
spinner.id = i + 100
spinner.layoutParams = TableRow.LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT)
spinner.layoutParams.height = 75
layout.addView(spinner)
if (accCodecs.size > i) {
val codec = accCodecs[i]
spinnerList[i].add(codec)
spinnerList[i].add("-")
for (c in codecs) if (c != codec) spinnerList[i].add(c)
} else {
spinnerList[i].addAll(codecs)
spinnerList[i].add(0, "-")
}
val codecSpinner = findViewById<Spinner>(spinner.id)
val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_item,
spinnerList[i])
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
codecSpinner.adapter = adapter
codecSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
newCodecs[parent.id - 100] = parent.selectedItem.toString()
}
override fun onNothingSelected(parent: AdapterView<*>) {
}
}
}
codecList.layoutManager = LinearLayoutManager(this)
codecList.adapter = codecsAdapter
binding.CodecsTitle.setOnClickListener {
itemTouchHelper.attachToRecyclerView(binding.CodecList)
codecsTitle.setOnClickListener {
if (media == "audio")
Utils.alertView(this, getString(R.string.audio_codecs),
getString(R.string.audio_codecs_help))
getString(R.string.audio_codecs_help))
else
Utils.alertView(this, getString(R.string.video_codecs),
getString(R.string.video_codecs_help))
getString(R.string.video_codecs_help))
}
}
private val itemTouchHelper by lazy {
val simpleItemTouchCallback = object : ItemTouchHelper.SimpleCallback(
UP or DOWN or START or END, RIGHT) {
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
val fromPosition = viewHolder.adapterPosition
val toPosition = target.adapterPosition
codecsAdapter.moveItem(fromPosition, toPosition)
codecsAdapter.notifyItemMoved(fromPosition, toPosition)
return true
}
@SuppressLint("NotifyDataSetChanged")
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
val position = viewHolder.adapterPosition
if (newCodecs[position].enabled) {
codecsAdapter.disableItem(position)
codecsAdapter.notifyItemRemoved(position)
} else {
codecsAdapter.enableItem(position)
codecsAdapter.notifyDataSetChanged()
}
}
@SuppressLint("NotifyDataSetChanged")
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
super.clearView(recyclerView, viewHolder)
recyclerView.post { codecsAdapter.notifyDataSetChanged() }
}
}
ItemTouchHelper(simpleItemTouchCallback)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
super.onCreateOptionsMenu(menu)
@ -116,28 +138,33 @@ class CodecsActivity : AppCompatActivity() {
R.id.checkIcon -> {
var save = false
val mc = ArrayList(LinkedHashSet<String>(newCodecs.filter { it != "-" } as ArrayList<String>))
val mcList = Utils.implode(mc, ",")
val codecs = ArrayList<String>()
for (codec in newCodecs)
if (codec.enabled)
codecs.add(codec.name)
val codecList = Utils.implode(codecs, ",")
if (media == "audio")
if (mc != acc.audioCodec) {
if (Api.account_set_audio_codecs(acc.accp, mcList) == 0) {
Log.d(TAG, "New audio codecs '$mcList'")
acc.audioCodec = mc
if (codecs != acc.audioCodec) {
if (Api.account_set_audio_codecs(acc.accp, codecList) == 0) {
Log.d(TAG, "New audio codecs '$codecList'")
acc.audioCodec = codecs
save = true
} else {
Log.e(TAG, "Setting of audio codecs '$mcList' failed")
Log.e(TAG, "Setting of audio codecs '$codecList' failed")
}
}
if (media == "video")
if (mc != acc.videoCodec) {
if (Api.account_set_video_codecs(acc.accp, mcList) == 0) {
Log.d(TAG, "New video codecs '$mcList'")
acc.videoCodec = mc
if (codecs != acc.videoCodec) {
if (Api.account_set_video_codecs(acc.accp, codecList) == 0) {
Log.d(TAG, "New video codecs '$codecs'")
acc.videoCodec = codecs
save = true
} else {
Log.e(TAG, "Setting of video codecs '$mcList' failed")
Log.e(TAG, "Setting of video codecs '$codecs' failed")
}
}

View File

@ -0,0 +1,59 @@
package com.tutpro.baresip
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import java.util.*
class CodecsAdapter(private val codecs: ArrayList<Codec>):
RecyclerView.Adapter<CodecsAdapter.CodecViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CodecViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.codec, parent, false)
return CodecViewHolder(v)
}
override fun getItemCount(): Int {
return codecs.size
}
fun moveItem(fromPosition: Int, toPosition: Int) {
val codec: Codec = codecs[fromPosition]
codec.enabled = codecs[toPosition].enabled
codecs.removeAt(fromPosition)
codecs.add(toPosition, codec)
}
fun enableItem(position: Int) {
val codec: Codec = codecs[position]
codec.enabled = true
codecs.removeAt(position)
codecs.add(0, codec)
}
fun disableItem(position: Int) {
val codec: Codec = codecs[position]
if (codec.enabled) {
codec.enabled = false
codecs.removeAt(position)
codecs.add(codec)
}
}
override fun onBindViewHolder(holder: CodecViewHolder, position: Int) {
val codec = codecs[position]
holder.codecName.text = codec.name
holder.codecName.alpha = if (codec.enabled) 1.0f else 0.5f
holder.reorderImage.setImageResource(
if (codec.enabled) R.drawable.reorder else android.R.color.transparent
)
}
class CodecViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
var codecName: TextView = itemView.findViewById(R.id.codecName)
var reorderImage: ImageView = itemView.findViewById(R.id.reorderImage)
}
}

View File

@ -38,7 +38,6 @@ import java.io.File
import java.net.URLDecoder
import kotlin.system.exitProcess
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding

View File

@ -0,0 +1,8 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM17,13h-4v4h-2v-4L7,13v-2h4L11,7h2v4h4v2z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M3,15h18v-2L3,13v2zM3,19h18v-2L3,17v2zM3,11h18L21,9L3,9v2zM3,5v2h18L21,5L3,5z"/>
</vector>

View File

@ -140,6 +140,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_toStartOf="@id/Register"
android:textSize="18sp"
android:text="@string/register" >
@ -150,6 +151,7 @@
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_gravity="end"
android:layout_centerVertical="true"
android:checked="false" >
</CheckBox>
</RelativeLayout>
@ -367,6 +369,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_toStartOf="@id/Default"
android:textSize="18sp"
android:text="@string/default_account" >
@ -376,6 +379,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_gravity="end"
android:checked="false" >
</CheckBox>

View File

@ -17,11 +17,11 @@
android:text="@string/audio_codecs" >
</TextView>
<TableLayout
android:id="@+id/SpinnerTable"
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/CodecList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="36dp" >
</TableLayout>
android:layout_marginTop="32dp"
android:scrollbars="vertical" />
</RelativeLayout>

View File

@ -240,6 +240,7 @@
android:hint="@string/dtmf"
android:importantForAutofill="no"
android:inputType="phone"
android:digits="0123456789#*"
android:textSize="20sp" >
</EditText>

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp" >
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:layout_margin="4dp" >
<TextView
android:id="@+id/codecName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textColor="@android:color/black"
android:textSize="18sp"
android:padding="10dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<ImageView
android:id="@+id/reorderImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:srcCompat="@drawable/reorder"
android:contentDescription="@string/codec_action" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

View File

@ -143,12 +143,6 @@
<string name="register_help">Jos merkitty, rekisteröinti on
aktiivinen ja REGISTER-sanomat lähetetään noin 12 minuutin välein.
</string>
<string name="audio_codecs">Audion koodausmenetelmät</string>
<string name="audio_codecs_help">Luettelo käytössä olevista audion
koodausmenetelmistä prioriteettijärjestyksessä</string>
<string name="video_codecs">Videon koodausmenetelmät</string>
<string name="video_codecs_help">Luettelo käytössä olevista videon
koodausmenetelmistä prioriteettijärjestyksessä</string>
<string name="media_nat">Media NAT hallinta</string>
<string name="media_nat_help">Valitsee media NAT hallintaprotokollan
(vapaaehtoinen). Vaihtoehtoja ovat STUN (Session Traversal Utilities
@ -291,6 +285,16 @@
<string name="short_chat_question">Haluatko poistaa viestiketjun \'%1$s\'\?</string>
<string name="delete_chats">Tyhjennä</string>
<string name="delete_chats_alert">Haluatko tyhjentää tilin \'%1$s\' viestihistorian\?</string>
<!-- Codecs Activity -->
<string name="audio_codecs">Audion koodausmenetelmät</string>
<string name="audio_codecs_help">Luettelo audion koodausmenetelmistä prioriteettijärjestyksessä.
Järjestä raahaamalla ja pudottamalla, ota käyttöön tai poista käytöstä pyyhkäisemällä oikealle.
</string>
<string name="video_codecs">Videon koodausmenetelmät</string>
<string name="video_codecs_help">Luettelo videon koodausmenetelmistä prioriteettijärjestyksessä.
Järjestä raahaamalla ja pudottamalla, ota käyttöön tai poista käytöstä pyyhkäisemällä oikealle.
</string>
<string name="codec_action">Järjestä</string>
<!-- Config Activity -->
<string name="configuration">Asetukset</string>
<string name="start_automatically">Käynnistä automaattisesti</string>

View File

@ -144,10 +144,6 @@
<string name="register_help">If checked, registration is enabled and REGISTER requests are sent at
12 minute intervals.
</string>
<string name="audio_codecs">Audio Codecs</string>
<string name="audio_codecs_help">List of supported audio codecs in priority order</string>
<string name="video_codecs">Video Codecs</string>
<string name="video_codecs_help">List of supported video codecs in priority order</string>
<string name="media_nat">Media NAT Traversal</string>
<string name="media_nat_help">Selects media NAT traversal protocol (if any). Possible choices are STUN
(Session Traversal Utilities for NAT, RFC 5389) and ICE (Interactive Connectivity
@ -281,6 +277,14 @@
<string name="short_chat_question">Do you want to delete chat with \'%1$s\'\?</string>
<string name="delete_chats">Delete</string>
<string name="delete_chats_alert">Do you want to delete chat history of account \'%1$s\'\?</string>
<!-- Codecs Activity -->
<string name="audio_codecs">Audio Codecs</string>
<string name="audio_codecs_help">List of audio codecs in priority order. Drag to reorder,
swipe right to enable or disable.</string>
<string name="video_codecs">Video Codecs</string>
<string name="video_codecs_help">List of video codecs in priority order. Drag to reorder,
swipe right to enable or disable.</string>
<string name="codec_action">Reorder</string>
<!-- Config Activity -->
<string name="configuration">Settings</string>
<string name="start_automatically">Start Automatically</string>