diff --git a/app/src/main/assets/config.static b/app/src/main/assets/config.static index 17bb0f1..29b6eaf 100644 --- a/app/src/main/assets/config.static +++ b/app/src/main/assets/config.static @@ -5,7 +5,7 @@ call_hold_other_calls yes audio_player aaudio,nil audio_source aaudio,nil audio_alert aaudio,nil -audio_level no +audio_level yes ausrc_format s16 auplay_format s16 auenc_format s16 @@ -36,6 +36,7 @@ module srtp.so module dtls_srtp.so module gzrtp.so module uuid.so +module vumeter.so module_app account.so module_app debug_cmd.so module_app mwi.so diff --git a/app/src/main/cpp/baresip.c b/app/src/main/cpp/baresip.c index f1ee081..36f4616 100644 --- a/app/src/main/cpp/baresip.c +++ b/app/src/main/cpp/baresip.c @@ -305,6 +305,16 @@ static void event_handler(enum ua_event ev, struct bevent *event, void *arg) len = re_snprintf(event_buf, sizeof event_buf, "recorder sessionid,%r", &data); break; } + /* Added by ritoseo */ + case UA_EVENT_VU_TX: + len = re_snprintf(event_buf, sizeof event_buf, "vu_tx_report,%s", prm); + //LOGE("call tx audio level, %s\n", prm); + break; + case UA_EVENT_VU_RX: + len = re_snprintf(event_buf, sizeof event_buf, "vu_rx_report,%s", prm); + //LOGE("call rx audio level, %s\n", prm); + break; + /********************/ default: return; } diff --git a/app/src/main/kotlin/com/tutpro/baresip/plus/BaresipService.kt b/app/src/main/kotlin/com/tutpro/baresip/plus/BaresipService.kt index 9a98e72..76661bf 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/plus/BaresipService.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/plus/BaresipService.kt @@ -326,6 +326,10 @@ class BaresipService: Service() { responseIntent.putExtra("data", resArr.toString()) responseIntent.setPackage("kr.co.rito.sipsvc"); context?.sendBroadcast(responseIntent) + } else if(req == "remove_history") { + CallsActivity.uaHistory.clear() + BaresipService.callHistory.clear() + CallHistoryNew.delete() } else if(req == "contact_list") { sendContactList() } else if(req == "save_address") { @@ -550,8 +554,15 @@ class BaresipService: Service() { displaySplitMode = DISPLAY_SPLIT_MODE_원거리_대하단_근거리_소상단 } else if(layout == "layout8") { displaySplitMode = DISPLAY_SPLIT_MODE_원거리_반좌단_근거리_반우단 + } else if(layout == "layout9") { + displaySplitMode = DISPLAY_SPLIT_MODE_원거리_최대_근거리_없음 + } else if(layout == "layout10") { + displaySplitMode = DISPLAY_SPLIT_MODE_원거리_없음_근거리_최대 } + Config.replaceVariable("display_split_mode", displaySplitMode.toString()) + Config.save() + sendActivityAction("update layout") } } else if(req == "misc_setting") { @@ -559,12 +570,17 @@ class BaresipService: Service() { if(param != null) { val json = JSONObject(param) val device_name = json.getString("device_name") + val display_type = json.getString("display_type") Config.replaceVariable("device_name", device_name) BaresipService.deviceName = device_name + + Config.replaceVariable("far_view_display_id", display_type) + BaresipService.farViewDisplayId = display_type.toInt() Config.save() sendActivityAction("update info") + sendActivityAction("update display") } } } @@ -929,14 +945,24 @@ class BaresipService: Service() { if(display2 == "connected") connectedCount++ + //println("Changed connectedDisplayCount : ${connectedDisplayCount}, connectedCount : ${connectedCount}") if(connectedDisplayCount != connectedCount) { val displayManager = getSystemService(DISPLAY_SERVICE) as DisplayManager val displays = displayManager.displays - if(connectedCount == displays.size) { + if(connectedCount > connectedDisplayCount) { + if(connectedCount == displays.size) { + connectedDisplayCount = connectedCount + //println("Changed connectedDisplayCount : ${connectedDisplayCount}") + + sendActivityAction("update display") + } + } else { connectedDisplayCount = connectedCount + //println("Changed connectedDisplayCount : ${connectedDisplayCount}") sendActivityAction("update display") } + } //connectedDisplayCount = connectedCount Utils.propertySet("sys.ritosip.display1.status", display1) @@ -1030,7 +1056,17 @@ class BaresipService: Service() { } } + if(BaresipService.deviceName != null) { + Utils.propertySet("sys.ritosip.device_name", BaresipService.deviceName) + } + if(BaresipService.callAnswerMode != null) { + Utils.propertySet("sys.ritosip.answer_mode", BaresipService.callAnswerMode) + } + + Utils.propertySet("sys.ritosip.far_view_display_id", BaresipService.farViewDisplayId.toString()) + Utils.propertySet("sys.ritosip.display_split_mode", BaresipService.displaySplitMode.toString()) + Utils.propertySet("sys.ritosip.sip.total_duration", BaresipService.totalDurationSeconds.toString()) captureCount++ delay(100) @@ -1125,6 +1161,11 @@ class BaresipService: Service() { CallHistoryNew.save() } + val value = Utils.readNumberFromFile("/sdcard/Documents/sip_total_duration") + if(value != null) { + BaresipService.totalDurationSeconds = value + } + Message.restore() hotSpotAddresses = Utils.hotSpotAddresses() @@ -1366,6 +1407,16 @@ class BaresipService: Service() { return } + if (ev[0] == "vu_tx_report") { + Utils.propertySet("sys.ritosip.call.audio.tx_level", ev[1]) + return + } + + if (ev[0] == "vu_rx_report") { + Utils.propertySet("sys.ritosip.call.audio.rx_level", ev[1]) + return + } + val ua = UserAgent.ofUap(uap) val aor = ua?.account?.aor @@ -1770,6 +1821,13 @@ class BaresipService: Service() { CallHistoryNew.save() ua.account.missedCalls = ua.account.missedCalls || missed } + + /* Added by ritoseo */ + val duration = call.duration() + BaresipService.totalDurationSeconds += duration + Utils.saveNumberToFile("/sdcard/Documents/sip_total_duration", BaresipService.totalDurationSeconds) + /* ---------------- */ + if (!Utils.isVisible()) { if (missed) { val caller = Utils.friendlyUri(this, call.peerUri, ua.account) @@ -2471,12 +2529,15 @@ class BaresipService: Service() { val DISPLAY_SPLIT_MODE_원거리_대좌단_근거리_소우단 = 6 val DISPLAY_SPLIT_MODE_원거리_대하단_근거리_소상단 = 7 val DISPLAY_SPLIT_MODE_원거리_반좌단_근거리_반우단 = 8 + val DISPLAY_SPLIT_MODE_원거리_최대_근거리_없음 = 9 + val DISPLAY_SPLIT_MODE_원거리_없음_근거리_최대 = 10 var isSupportAudioCall = false var deviceIpAddress = "0.0.0.0" var deviceName = "" var preferTransport = "udp" var videoFormatHeight = 480 var connectedDisplayCount = 0 + var prevConnectedDisplayCount = 0 var callAnswerMode = "auto" var audioInputDevice = "usb" var useDisplaySplitMode = false diff --git a/app/src/main/kotlin/com/tutpro/baresip/plus/CallHistory.kt b/app/src/main/kotlin/com/tutpro/baresip/plus/CallHistory.kt index 279ed52..8515ccc 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/plus/CallHistory.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/plus/CallHistory.kt @@ -75,6 +75,17 @@ class CallHistoryNew(val aor: String, val peerUri: String, val direction: String } } + fun delete() { + Log.d(TAG, "Deleting history of ${BaresipService.callHistory.size} calls") + val file = File(BaresipService.filesPath + "/call_history") + try { + file.delete() + } catch (e: IOException) { + Log.e(TAG, "Deleting exception: $e") + e.printStackTrace() + } + } + fun restore() { val file = File(BaresipService.filesPath + "/call_history") if (file.exists()) { diff --git a/app/src/main/kotlin/com/tutpro/baresip/plus/Config.kt b/app/src/main/kotlin/com/tutpro/baresip/plus/Config.kt index d249652..e04d782 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/plus/Config.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/plus/Config.kt @@ -276,9 +276,25 @@ object Config { BaresipService.callAnswerMode = "auto" config = "${config}answer_mode ${BaresipService.callAnswerMode}\n" + + val farViewDisplayId = previousVariable("far_view_display_id") + if (farViewDisplayId != "") + BaresipService.farViewDisplayId = farViewDisplayId.toInt() + else + BaresipService.farViewDisplayId = 1 + config = "${config}far_view_display_id ${BaresipService.farViewDisplayId}\n" + + + val displaySplitMode = previousVariable("display_split_mode") + if (displaySplitMode != "") + BaresipService.displaySplitMode = displaySplitMode.toInt() + else + BaresipService.displaySplitMode = BaresipService.DISPLAY_SPLIT_MODE_원거리_최대_근거리_우하단 + config = "${config}display_split_mode ${BaresipService.displaySplitMode}\n" + + save() BaresipService.isConfigInitialized = true - } private fun previousVariable(name: String): String { diff --git a/app/src/main/kotlin/com/tutpro/baresip/plus/MainActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/plus/MainActivity.kt index bef2699..6fd2679 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/plus/MainActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/plus/MainActivity.kt @@ -195,7 +195,7 @@ class MainActivity : AppCompatActivity() { if(!isKeyboardVisible) { val currentFocusView = currentFocus if(event.action == KeyEvent.ACTION_UP) { - println("pokaRITO pokachip z. " + event) + println("pokaRITO pokachip z. " + event + " focusView : " + currentFocusView) if(event.keyCode == KeyEvent.KEYCODE_DPAD_UP) { if(navUpList.contains(currentFocusView)) { val view = navUpList.get(currentFocusView)!! @@ -208,23 +208,20 @@ class MainActivity : AppCompatActivity() { return false } } + } else { + if(currentFocusView == binding.aorSpinner) { + callStartButton.requestFocus() + return false + } } } else if(event.keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { - println("pokaRITO pokachip k. " + currentFocusView) - if(binding.radioStatic.isFocused) { - println("pokaRITO pokachip radioStatic focused") - } if(navDownList.contains(currentFocusView)) { - println("pokaRITO pokachip zz. " + currentFocusView) val view = navDownList.get(currentFocusView)!! if(view.isVisible) { - println("pokaRITO pokachip zzz. " + view) view.requestFocus() return false } - } else if(currentFocusView is RadioButton) { - println("pokaRITO pokachip rr. " + currentFocusView) } } else if(event.keyCode == KeyEvent.KEYCODE_ENTER) { @@ -438,7 +435,12 @@ class MainActivity : AppCompatActivity() { dialogImgBtn2 = binding.dialogButtonImg2 callStartButton = binding.callStartBtn callStartButton.setOnClickListener { - callVideoButton.performClick() + val status = Utils.propertyGet("sys.ritosip.sip.status") + if(status == "registered") { + callVideoButton.performClick() + } else { + showCustomToast(this, "SIP서버에 연결 되어 있지 않습니다.") + } } //callHistoryButton = binding.callHistoryBtn settingButton = binding.settingBtn @@ -1323,6 +1325,7 @@ class MainActivity : AppCompatActivity() { // } catch(e : java.lang.Exception) { // } // presentation?.setContentView(videoView.surfaceSelfView) + videoView.surfaceView.bringToFront() videoView.surfaceSelfView.bringToFront() } else { // try { @@ -1550,6 +1553,48 @@ class MainActivity : AppCompatActivity() { prm2.leftMargin = 960 prm2.topMargin = 270 + videoView.surfaceSelfView.layoutParams = prm2 + } else if(BaresipService.displaySplitMode == BaresipService.DISPLAY_SPLIT_MODE_원거리_최대_근거리_없음) { + var prm1: RelativeLayout.LayoutParams = + RelativeLayout.LayoutParams( + 1920, + 1080 + ) + prm1.leftMargin = 0 + prm1.topMargin = 0 + + videoView.surfaceView.layoutParams = prm1 + + + var prm2: RelativeLayout.LayoutParams = + RelativeLayout.LayoutParams( + 1, + 1 + ) + prm2.leftMargin = 0 + prm2.topMargin = 0 + + videoView.surfaceSelfView.layoutParams = prm2 + } else if(BaresipService.displaySplitMode == BaresipService.DISPLAY_SPLIT_MODE_원거리_없음_근거리_최대) { + var prm1: RelativeLayout.LayoutParams = + RelativeLayout.LayoutParams( + 1, + 1 + ) + prm1.leftMargin = 0 + prm1.topMargin = 0 + + videoView.surfaceView.layoutParams = prm1 + + + var prm2: RelativeLayout.LayoutParams = + RelativeLayout.LayoutParams( + 1920, + 1080 + ) + prm2.leftMargin = 0 + prm2.topMargin = 0 + videoView.surfaceSelfView.layoutParams = prm2 } @@ -1568,8 +1613,44 @@ class MainActivity : AppCompatActivity() { } private fun updateDisplay() { - println("Update Display : ${BaresipService.connectedDisplayCount}") + println("Update Display : ${BaresipService.connectedDisplayCount}, prevDisplayCount : ${BaresipService.prevConnectedDisplayCount}") if(BaresipService.connectedDisplayCount < 2) { + if(BaresipService.prevConnectedDisplayCount != BaresipService.connectedDisplayCount) { + try { + presentation?.dismiss() + } catch(e : java.lang.Exception) { + } + + try { + val parentView = videoView.surfaceView.parent + (parentView as ViewGroup).removeView(videoView.surfaceView) + } catch(e : java.lang.Exception) { + } + + try { + val parentView = videoView.surfaceSelfView.parent + (parentView as ViewGroup).removeView(videoView.surfaceSelfView) + } catch(e : java.lang.Exception) { + } + + try { + val parentView = videoView.standbyView.parent + (parentView as ViewGroup).removeView(videoView.standbyView) + } catch(e : java.lang.Exception) { + } + + + var prm: FrameLayout.LayoutParams = + FrameLayout.LayoutParams( + 1920, + 1080 + ) + prm.leftMargin = 0 + prm.topMargin = 0 + videoView.surfaceView.layoutParams = prm + videoLayout.addView(videoView.surfaceView) + } + try { val parentView = videoView.surfaceSelfView.parent (parentView as ViewGroup).removeView(videoView.surfaceSelfView) @@ -1589,6 +1670,17 @@ class MainActivity : AppCompatActivity() { updateDisplayLayout() } else { + try { + presentation?.dismiss() + } catch(e : java.lang.Exception) { + } + + try { + val parentView = videoView.surfaceView.parent + (parentView as ViewGroup).removeView(videoView.surfaceView) + } catch(e : java.lang.Exception) { + } + try { val parentView = videoView.surfaceSelfView.parent (parentView as ViewGroup).removeView(videoView.surfaceSelfView) @@ -1601,6 +1693,13 @@ class MainActivity : AppCompatActivity() { } catch(e : java.lang.Exception) { } + var useSecondScreenAsFar = false + if(BaresipService.farViewDisplayId == 1) { + useSecondScreenAsFar = false + } else if(BaresipService.farViewDisplayId == 2) { + useSecondScreenAsFar = true + } + val displayManager = getSystemService(DISPLAY_SERVICE) as DisplayManager val displays = displayManager.displays val secondDisplay = displays[1] // 두 번째 디스플레이 가져오기 @@ -1615,31 +1714,57 @@ class MainActivity : AppCompatActivity() { prm1.topMargin = 0 videoView.surfaceView.layoutParams = prm1 - var prm2: RelativeLayout.LayoutParams = - RelativeLayout.LayoutParams( - 1920, - 1080 - ) - prm2.leftMargin = 0 - prm2.topMargin = 0 - videoView.surfaceSelfView.layoutParams = prm2 - presentation?.setContentView(R.layout.presentation_layout) - val presentationView = presentation?.window?.decorView?.findViewById(R.id.presentationLayout) - try { - presentationView?.addView(videoView.surfaceSelfView) - } catch(e : java.lang.Exception) { - } - try { + if(useSecondScreenAsFar) { + //presentation?.setContentView(videoView.surfaceView) + presentation?.setContentView(R.layout.presentation_layout) + val presentationView = presentation?.window?.decorView?.findViewById(R.id.presentationLayout) + presentationView?.addView(videoView.surfaceView) presentationView?.addView(videoView.standbyView) - } catch(e : java.lang.Exception) { + } else { + var prm2: RelativeLayout.LayoutParams = + RelativeLayout.LayoutParams( + 1920, + 1080 + ) + prm2.leftMargin = 0 + prm2.topMargin = 0 + videoView.surfaceSelfView.layoutParams = prm2 + presentation?.setContentView(R.layout.presentation_layout) + val presentationView = presentation?.window?.decorView?.findViewById(R.id.presentationLayout) + try { + presentationView?.addView(videoView.surfaceSelfView) + } catch(e : java.lang.Exception) { + } + try { + presentationView?.addView(videoView.standbyView) + } catch(e : java.lang.Exception) { + } } + + if(useSecondScreenAsFar) { + var prm2: RelativeLayout.LayoutParams = + RelativeLayout.LayoutParams( + 1920, + 1080 + ) + prm2.leftMargin = 0 + prm2.topMargin = 0 + videoView.surfaceSelfView.layoutParams = prm2 + videoLayout.addView(videoView.surfaceSelfView) + } else { + videoLayout.addView(videoView.surfaceView) + } + if(isCallExist()) { videoView.surfaceSelfView.bringToFront() + videoView.surfaceView.bringToFront() } else { videoView.standbyView.bringToFront() } presentation?.show() } + + BaresipService.prevConnectedDisplayCount = BaresipService.connectedDisplayCount } private fun addVideoLayoutViews() { @@ -1678,18 +1803,29 @@ class MainActivity : AppCompatActivity() { videoView.surfaceSelfView.layoutParams = prm2 videoLayout.addView(videoView.surfaceSelfView) + + updateDisplayLayout() } else { - val useSecondScreenAsFar = false; + var useSecondScreenAsFar = false // DisplayManager 가져오기 val displayManager = getSystemService(DISPLAY_SERVICE) as DisplayManager val displays = displayManager.displays + if(BaresipService.farViewDisplayId == 1) { + useSecondScreenAsFar = false + } else if(BaresipService.farViewDisplayId == 2) { + useSecondScreenAsFar = true + } + if (displays.size > 1) { // 보조 디스플레이가 있는 경우 println("디스플레이 상태 : [0]${Utils.checkDisplayConnection(0)} [1]${Utils.checkDisplayConnection(1)}") val secondDisplay = displays[1] // 두 번째 디스플레이 가져오기 presentation = SecondScreenPresentation(this, secondDisplay) if(useSecondScreenAsFar) { - presentation?.setContentView(videoView.surfaceView) + presentation?.setContentView(R.layout.presentation_layout) + val presentationView = presentation?.window?.decorView?.findViewById(R.id.presentationLayout) + presentationView?.addView(videoView.surfaceView) + presentationView?.addView(videoView.standbyView) } else { //presentation?.setContentView(videoView.surfaceSelfView) var prm2: FrameLayout.LayoutParams = @@ -2270,6 +2406,8 @@ class MainActivity : AppCompatActivity() { AppCompatDelegate.setDefaultNightMode(Preferences(applicationContext).displayTheme) delegate.applyDayNight() } + + updateDisplay() handleNextEvent() return } diff --git a/app/src/main/kotlin/com/tutpro/baresip/plus/Utils.kt b/app/src/main/kotlin/com/tutpro/baresip/plus/Utils.kt index 7e82907..31e1da0 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/plus/Utils.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/plus/Utils.kt @@ -1331,6 +1331,33 @@ object Utils { return "plugout" } + fun saveNumberToFile(path: String, number: Int) { + val file = File(path) + try { + file.writeText(number.toString()) + Log.d("FileSave", "숫자 저장 완료: $number") + + RandomAccessFile(path, "rw").use { raf -> + raf.fd.sync() // eMMC에 확실히 기록 + raf.close() + } + } catch (e: IOException) { + Log.e("FileSave", "파일 저장 실패 : " + e.toString()) + } + } + + fun readNumberFromFile(path: String): Int? { + val file = File(path) + return try { + val text = file.readText().trim() + Log.d("FileRead", "읽은 숫자: $text") + text.toIntOrNull() + } catch (e: IOException) { + Log.e("FileRead", "파일 읽기 실패 : " + e.toString()) + null + } + } + fun fileContainsString(filePath: String, keyword: String): Boolean { val file = File(filePath) if (!file.exists()) return false diff --git a/app/src/main/res/drawable/toast_frame_rito.xml b/app/src/main/res/drawable/toast_frame_rito.xml new file mode 100644 index 0000000..eec1827 --- /dev/null +++ b/app/src/main/res/drawable/toast_frame_rito.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 436b09e..e12b0c4 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -161,6 +161,8 @@ android:layout_height="64dp" android:background="@color/cardview_shadow_start_color" android:clickable="false" + android:focusable="false" + android:focusableInTouchMode="false" android:gravity="center_vertical" android:popupBackground="@color/colorSpinnerDropdown" android:spinnerMode="dropdown" /> @@ -727,7 +729,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Netmask" - android:inputType="text" + android:inputType="phone" android:textSize="24sp" /> diff --git a/distribution.video/baresip/lib/arm64-v8a/libbaresip.a b/distribution.video/baresip/lib/arm64-v8a/libbaresip.a index 9ac12d6..2d153f8 100644 Binary files a/distribution.video/baresip/lib/arm64-v8a/libbaresip.a and b/distribution.video/baresip/lib/arm64-v8a/libbaresip.a differ