diff --git a/app/src/main/assets/config b/app/src/main/assets/config index 95e84d98..26b659fb 100644 --- a/app/src/main/assets/config +++ b/app/src/main/assets/config @@ -23,8 +23,8 @@ net_prefer_ipv6 no module opus.so module amr.so module ilbc.so -module g7221.so module g722.so +module g7221.so module g726.so module g711.so module webrtc_aec.so diff --git a/app/src/main/kotlin/com/tutpro/baresip/Account.kt b/app/src/main/kotlin/com/tutpro/baresip/Account.kt index 78a559fc..a0acdbf4 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Account.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Account.kt @@ -1,6 +1,8 @@ package com.tutpro.baresip import android.content.Context +import java.util.* +import kotlin.collections.ArrayList class Account(val accp: String) { @@ -151,6 +153,27 @@ class Account(val accp: String) { return aor.split("@")[1] } + private fun removeAudioCodecsStartingWith(prefix: String) { + val newCodecs = ArrayList() + for (acSpec in audioCodec) + if (!acSpec.toLowerCase(Locale.ROOT).startsWith(prefix)) newCodecs.add(acSpec) + audioCodec = newCodecs + } + + fun removeAudioCodecs(codecModule: String) { + when (codecModule) { + "g711" -> { + removeAudioCodecsStartingWith("pcm") + } + "g722" -> { + removeAudioCodecsStartingWith("g722/") + } + else -> { + removeAudioCodecsStartingWith(codecModule) + } + } + } + companion object { fun accounts(): ArrayList { diff --git a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt index 9b49e7ed..7e994907 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt @@ -186,7 +186,7 @@ class BaresipService: Service() { showStatusNotification() if (Config.variable("dyn_dns")[0] == "yes") - Config.remove("dns_server") + Config.removeVariable("dns_server") if (AccountsActivity.noAccounts()) { val newIntent = Intent(this, MainActivity::class.java) @@ -712,9 +712,9 @@ class BaresipService: Service() { Log.d(LOG_TAG, "Received 'stopped' from baresip with param '$error'") isServiceRunning = false if (error == "ua_init") { - Config.remove("sip_listen") - Config.remove("sip_certificate") - Config.remove("sip_cafile") + Config.removeVariable("sip_listen") + Config.removeVariable("sip_certificate") + Config.removeVariable("sip_cafile") } val intent = Intent("service event") intent.putExtra("event", "stopped") diff --git a/app/src/main/kotlin/com/tutpro/baresip/Config.kt b/app/src/main/kotlin/com/tutpro/baresip/Config.kt index 531e1477..81ee9be8 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Config.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Config.kt @@ -21,17 +21,6 @@ object Config { config = "${config}ausrc_format s16\nauplay_format s16\nauenc_format s16\naudec_format s16\nmodule webrtc_aec.so\n" write = true } - if (!config.contains(Regex("module[ ]+amr.so"))) { - config = config.replace(Regex("module[ ]+g7...?.so\n"), "") - config = config.replace(Regex("module[ ]+ilbc.so\n"), "") - config = "${config}module amr.so\n" - config = "${config}module ilbc.so\n" - config = "${config}module g7221.so\n" - config = "${config}module g722.so\n" - config = "${config}module g726.so\n" - config = "${config}module g711.so\n" - write = true - } if (config.contains(Regex("#module_app[ ]+mwi.so"))) { config = config.replace(Regex("#module_app[ ]+mwi.so"), "module_app mwi.so") @@ -69,7 +58,7 @@ object Config { } val preferIpv6 = variable("prefer_ipv6") if (preferIpv6.size > 0) { - remove("prefer_ipv6") + removeVariable("prefer_ipv6") config = "net_prefer_ipv6 ${preferIpv6[0]}\n${config}" write = true } else { @@ -112,18 +101,21 @@ object Config { return result } - fun add(variable: String, value: String) { - config += "$variable $value\n" + fun addLine(line: String) { + config += "$line\n" } - fun remove(variable: String) { - config = Utils.removeLinesStartingWithName(config, variable) - Utils.putFileContents(configPath, config.toByteArray()) + fun removeLine(line: String) { + config = Utils.removeLinesStartingWithString(config, line) } - fun replace(variable: String, value: String) { - remove(variable) - add(variable, value) + fun removeVariable(variable: String) { + config = Utils.removeLinesStartingWithString(config, "$variable ") + } + + fun replaceVariable(variable: String, value: String) { + removeVariable(variable) + addLine("$variable $value") } fun reset(ctx: Context) { diff --git a/app/src/main/kotlin/com/tutpro/baresip/ConfigActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/ConfigActivity.kt index 48b99228..1e841821 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/ConfigActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/ConfigActivity.kt @@ -3,14 +3,19 @@ package com.tutpro.baresip import android.app.Activity import android.content.Context import android.content.Intent +import android.graphics.Color import android.net.ConnectivityManager import android.os.Build import android.os.Bundle import android.support.v7.app.AppCompatActivity +import android.util.TypedValue +import android.view.Gravity import android.view.Menu import android.view.MenuItem import android.view.View import android.widget.* +import android.widget.RelativeLayout.LayoutParams +import android.widget.AdapterView class ConfigActivity : AppCompatActivity() { @@ -35,6 +40,7 @@ class ConfigActivity : AppCompatActivity() { private var oldDnsServers = "" private var oldCertificateFile = false private var oldCAFile = false + private var oldAudioModules = mutableMapOf() private var oldAec = false private var oldOpusBitrate = "" private var oldOpusPacketLoss = "" @@ -43,6 +49,7 @@ class ConfigActivity : AppCompatActivity() { private var callVolume = BaresipService.callVolume private var save = false private var restart = false + private val audioModules = listOf("opus", "amr", "ilbc", "g722", "g7221", "g726", "g711") override fun onCreate(savedInstanceState: Bundle?) { @@ -91,6 +98,37 @@ class ConfigActivity : AppCompatActivity() { oldCAFile = Config.variable("sip_cafile").isNotEmpty() caFile.isChecked = oldCAFile + val audioModulesList = findViewById(R.id.AudioModulesList) as LinearLayout + var id = 1000 + for (module in audioModules) { + val rl = RelativeLayout(this) + val rlParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT) + rlParams.marginStart = 16 + rl.layoutParams = rlParams + val tv = TextView(this) + tv.id = id++ + val tvParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT) + tvParams.addRule(RelativeLayout.ALIGN_PARENT_START) + tvParams.addRule(RelativeLayout.CENTER_VERTICAL) + tvParams.addRule(RelativeLayout.START_OF, id) + tv.layoutParams = tvParams + tv.text = module + tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18f) + tv.setTextColor(Color.BLACK) + rl.addView(tv) + val cb = CheckBox(this) + cb.id = id++ + val cbParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT) + cbParams.addRule(RelativeLayout.ALIGN_PARENT_END) + cbParams.addRule(RelativeLayout.CENTER_VERTICAL) + cb.layoutParams = cbParams + cb.gravity = Gravity.END + cb.isChecked = Config.variable("module $module.so").size > 0 + oldAudioModules.put(module, cb.isChecked) + rl.addView(cb) + audioModulesList.addView(rl) + } + aec = findViewById(R.id.Aec) as CheckBox val aecCv = Config.variable("module") oldAec = aecCv.contains("webrtc_aec.so") @@ -166,7 +204,7 @@ class ConfigActivity : AppCompatActivity() { var autoStartString = "no" if (autoStart.isChecked) autoStartString = "yes" if (oldAutoStart != autoStartString) { - Config.replace("auto_start", autoStartString) + Config.replaceVariable("auto_start", autoStartString) save = true restart = false } @@ -178,8 +216,8 @@ class ConfigActivity : AppCompatActivity() { "${getString(R.string.invalid_listen_address)}: $listenAddr") return false } - Config.remove("sip_listen") - if (listenAddr != "") Config.add("sip_listen", listenAddr) + Config.removeVariable("sip_listen") + if (listenAddr != "") Config.addLine("sip_listen $listenAddr") save = true restart = true } @@ -191,8 +229,8 @@ class ConfigActivity : AppCompatActivity() { "${getString(R.string.invalid_bind_address)}: $bindAddr") return false } - Config.remove("net_interface") - if (bindAddr != "") Config.add("net_interface", bindAddr) + Config.removeVariable("net_interface") + if (bindAddr != "") Config.addLine("net_interface $bindAddr") save = true restart = true } @@ -200,7 +238,7 @@ class ConfigActivity : AppCompatActivity() { var preferIPv6String = "no" if (preferIPv6.isChecked) preferIPv6String = "yes" if (oldPreferIPv6 != preferIPv6String) { - Config.replace("net_prefer_ipv6", preferIPv6String) + Config.replaceVariable("net_prefer_ipv6", preferIPv6String) save = true restart = true } @@ -212,19 +250,19 @@ class ConfigActivity : AppCompatActivity() { "${getString(R.string.invalid_dns_servers)}: $dnsServers") return false } - Config.remove("dyn_dns") - Config.remove("dns_server") + Config.removeVariable("dyn_dns") + Config.removeVariable("dns_server") if (dnsServers.isNotEmpty()) { for (server in dnsServers.split(",")) - Config.add("dns_server", server) - Config.add("dyn_dns", "no") + Config.addLine("dns_server $server") + Config.addLine("dyn_dns no") if (Api.net_use_nameserver(dnsServers) != 0) { Utils.alertView(this, getString(R.string.error), "${getString(R.string.failed_to_set_dns_servers)}: $dnsServers") return false } } else { - Config.add("dyn_dns", "yes") + Config.addLine("dyn_dns yes") if (Build.VERSION.SDK_INT >= 23) { val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager Config.updateDnsServers(cm.getLinkProperties(cm.activeNetwork).getDnsServers()) @@ -249,10 +287,10 @@ class ConfigActivity : AppCompatActivity() { return false } Utils.putFileContents(BaresipService.filesPath + "/cert.pem", content) - Config.remove("sip_certificate") - Config.add("sip_certificate", BaresipService.filesPath + "/cert.pem") + Config.removeVariable("sip_certificate") + Config.addLine("sip_certificate ${BaresipService.filesPath}/cert.pem") } else { - Config.remove("sip_certificate") + Config.removeVariable("sip_certificate") } save = true restart = true @@ -272,22 +310,44 @@ class ConfigActivity : AppCompatActivity() { } Utils.putFileContents(BaresipService.filesPath + "/ca_certs.crt", content) - Config.remove("sip_cafile") - Config.add("sip_cafile", BaresipService.filesPath + "/ca_certs.crt") + Config.removeVariable("sip_cafile") + Config.addLine("sip_cafile ${BaresipService.filesPath}/ca_certs.crt") } else { - Config.remove("sip_cafile") + Config.removeVariable("sip_cafile") } save = true restart = true } + var id = 1001 + for (module in audioModules) { + val box = findViewById(id++) + if (box.isChecked && !oldAudioModules[module]!!) { + if (Api.module_load("$module.so") != 0) { + Utils.alertView(this, getString(R.string.error), + "${getString(R.string.failed_to_load_module)}: $module.so") + return false + } + Config.addLine("module $module.so") + save = true + } + if (!box.isChecked && oldAudioModules[module]!!) { + Api.module_unload("$module.so") + Config.removeLine("module $module.so") + for (ua in UserAgent.uas()) ua.account.removeAudioCodecs(module) + AccountsActivity.saveAccounts() + save = true + } + id++ + } + if (aec.isChecked != oldAec) { - Config.remove("module webrtc_aec.so") + Config.removeLine("module webrtc_aec.so") if (aec.isChecked) { - Config.add("module", "webrtc_aec.so") + Config.addLine("module webrtc_aec.so") if (Api.module_load("webrtc_aec.so") != 0) { Utils.alertView(this, getString(R.string.error), - getString(R.string.failed_to_load_aec_module)) + getString(R.string.failed_to_load_module)) aec.isChecked = false return false } @@ -304,8 +364,8 @@ class ConfigActivity : AppCompatActivity() { "${getString(R.string.invalid_opus_bitrate)}: $opusBitRate.") return false } - Config.remove("opus_bitrate") - Config.add("opus_bitrate", opusBitRate) + Config.removeVariable("opus_bitrate") + Config.addLine("opus_bitrate $opusBitRate") save = true restart = true } @@ -317,11 +377,11 @@ class ConfigActivity : AppCompatActivity() { "${getString(R.string.invalid_opus_packet_loss)}: $opusPacketLoss") return false } - Config.remove("opus_inbandfec") - Config.remove("opus_packet_loss") + Config.removeVariable("opus_inbandfec") + Config.removeVariable("opus_packet_loss") if (opusPacketLoss != "0") { - Config.add("opus_inbandfec", "yes") - Config.add("opus_packet_loss", opusPacketLoss) + Config.addLine("opus_inbandfec yes") + Config.addLine("opus_packet_loss $opusPacketLoss") } save = true restart = true @@ -330,21 +390,21 @@ class ConfigActivity : AppCompatActivity() { var iceModeString = "full" if (iceLite.isChecked) iceModeString = "lite" if (oldIceMode != iceModeString) { - Config.replace("ice_mode", iceModeString) + Config.replaceVariable("ice_mode", iceModeString) save = true restart = true } if (BaresipService.callVolume != callVolume) { BaresipService.callVolume = callVolume - Config.replace("call_volume", callVolume.toString()) + Config.replaceVariable("call_volume", callVolume.toString()) save = true } var logLevelString = "2" if (debug.isChecked) logLevelString = "0" if (oldLogLevel != logLevelString) { - Config.replace("log_level", logLevelString) + Config.replaceVariable("log_level", logLevelString) Api.log_level_set(logLevelString.toInt()) Log.logLevelSet(logLevelString.toInt()) save = true @@ -415,6 +475,10 @@ class ConfigActivity : AppCompatActivity() { Utils.alertView(this, getString(R.string.tls_ca_file), getString(R.string.tls_ca_file_help)) } + findViewById(R.id.AudioModulesTitle) as TextView -> { + Utils.alertView(this, getString(R.string.audio_modules_title), + getString(R.string.audio_modules_help)) + } findViewById(R.id.AecTitle) as TextView-> { Utils.alertView(this, getString(R.string.aec), getString(R.string.aec_help)) diff --git a/app/src/main/kotlin/com/tutpro/baresip/Utils.kt b/app/src/main/kotlin/com/tutpro/baresip/Utils.kt index b5234eef..afe6ada3 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Utils.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Utils.kt @@ -38,10 +38,10 @@ object Utils { return result } - fun removeLinesStartingWithName(string: String, name: String): String { + fun removeLinesStartingWithString(lines: String, string: String): String { var result = "" - for (line in string.split("\n")) - if (!line.startsWith(name) && (line.length > 0)) result += line + "\n" + for (line in lines.split("\n")) + if (!line.startsWith(string) && (line.length > 0)) result += line + "\n" return result } diff --git a/app/src/main/res/layout/activity_config.xml b/app/src/main/res/layout/activity_config.xml index d712bd7c..87ef2633 100644 --- a/app/src/main/res/layout/activity_config.xml +++ b/app/src/main/res/layout/activity_config.xml @@ -192,7 +192,29 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="12dp" - android:orientation="horizontal" > + android:orientation="vertical" > + + + + + + + Virheelliset DNS-palvelimet DNS-palvelinten asetus epäonnistui + TLS-varmennintiedosto + Jos merkitty, tiedosto \'cert.pem\', joka sisältää + tämän baresip-sovelluksen julkisen ja yksityisen TLS-varmentimen, on joko jo ladattu tai tullaan + lataamaan Download-hakemistosta. Turvallisuusyistä tuhoa tiedosto heti lataamisen jälkeen. + + TLS CA-tiedosto + Jos merkitty, tiedosto \'ca_certs.crt\', joka sisältää + TLS-varmenninauktoriteettien julkiset varmentimen, on joko jo ladattu tai tullaan lataamaan + Download-hakemistosta. + + Audio-modulit + Merkittyjen modulien tarjoamat audio-koodekit ovat tilien + käytettävissä. + + Modulin lataaminen epäonnistui Akustinen kaiun poisto Jos merkitty, kaikua yritetään poistaa puheluiden aikana. - Kaiunpoistomodulin lataaminen epäonnistui. Opus-koodekin bittinopeus Opus-koodekin käyttämä keskimääräinen enimmäisnopeus. Mahdollisia arvoja ovat @@ -306,15 +320,6 @@ Tämä pulelu on turvallinen ja kohde on todennettu! Haluatko poistaa todennuksen? Poista todennus - TLS CA-tiedosto - Jos merkitty, tiedosto \'ca_certs.crt\', joka sisältää - todennusauktoriteettien TLS-sertifikaatit, on ladattu tai ladataan Download-kansiosta. - - TLS sertifikaattitiedosto - "Jos merkitty, tiedosto \'cert.pem\', joka sisältää - tämän baresip-sovelluksen TLS-sertifikaatin ja yksityisen avaimen, on ladattu tai ladataan - Download-kansiosta." - Sovelluksen tiedot talletettiin Download-kansion tiedostoon \'baresip.bs\'. diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 17fbf08a..03cd0346 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -181,9 +181,12 @@ TLS CA File If checked, file \'ca_certs.crt\' containing TLS certificates of Certificate Authorities has been or will be loaded from Download directory. + Audio Modules + Audio codecs provided by the checked modules are + available for use by the accounts. + Failed to load module. Acoustic Echo Cancellation If checked, echo cancellation is attempted on call audio. - Failed to load Acoustic Echo Cancellation module. Opus Bit Rate Average maximum bit rate used by Opus audio stream. Valid values are 6000-510000. Factory default is 28000.