UI 변경 진행 중

메뉴 버튼 팝업 처리 추가
This commit is contained in:
ritoseo 2025-04-02 10:54:23 +09:00
parent 600e6c5007
commit 3bb1079674
15 changed files with 307 additions and 10 deletions

View File

@ -47,6 +47,11 @@ android {
'proguard-rules.pro'
}
}
android.applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = "ritosip-${defaultConfig.versionName}.apk"
}
}
buildFeatures {
viewBinding true
dataBinding true

View File

@ -1705,6 +1705,16 @@ JNIEXPORT void JNICALL Java_com_tutpro_baresip_plus_Api_call_1set_1video_1direct
re_thread_leave();
}
JNIEXPORT void JNICALL Java_com_tutpro_baresip_plus_Api_call_1set_1video_1mute(
JNIEnv *env, jobject obj, jlong call, jboolean mute)
{
(void)env;
(void)obj;
re_thread_enter();
video_set_source_mute(call_video((struct call *)call), (bool)mute);
re_thread_leave();
}
JNIEXPORT void JNICALL Java_com_tutpro_baresip_plus_Api_call_1set_1media_1direction(
JNIEnv *env, jobject obj, jlong call, jint adir, jint vdir)
{

View File

@ -964,7 +964,9 @@ JNIEXPORT void JNICALL Java_com_tutpro_baresip_plus_VideoView_set_1surfaceSelf(
}
} else {
LOGW("[SELF] Releasing windowSelf");
ANativeWindow_release(window_self);
if(window_self) {
ANativeWindow_release(window_self);
}
window_self = NULL;
}
}

View File

@ -99,6 +99,7 @@ object Api {
external fun call_has_video(callp: Long): Boolean
external fun call_set_video_source(callp: Long, front: Boolean): Int
external fun call_set_video_direction(callp: Long, dir: Int)
external fun call_set_video_mute(callp: Long, mute: Boolean) // added by ritoseo
external fun call_set_media_direction(callp: Long, adir: Int, vdir: Int)
external fun call_disable_video_stream(callp: Long, disable: Boolean)
external fun call_video_enabled(callp: Long): Boolean

View File

@ -395,6 +395,36 @@ class BaresipService: Service() {
} else if(req == "audio_unmute") {
Api.calls_mute(false)
isMicMuted = false
} else if(req == "video_mute") {
if(uas.size > 0) {
val ua = uas[0]
val call = ua.currentCall()
call?.setVideoMute(true)
isVideoMuted = true
}
} else if(req == "video_unmute") {
if(uas.size > 0) {
val ua = uas[0]
val call = ua.currentCall()
call?.setVideoMute(false)
isVideoMuted = false
}
} else if(req == "audio_source") {
val param = intent?.getStringExtra("param")
if(param != null) {
try {
val json = JSONObject(param)
var device = "usb"
val source_target = json.getString("target")
if(source_target == "aux") {
device = "codec"
}
Utils.setAudioSourceDevice(device)
audioInputDevice = device
} catch(e : Exception) {
e.printStackTrace()
}
}
} else if(req == "set_account") {
UserAgent.deleteAllUas()
val param = intent?.getStringExtra("param")
@ -422,9 +452,13 @@ class BaresipService: Service() {
Api.account_set_auth_pass(acc.accp, password)
acc.authPass = Api.account_auth_pass(acc.accp)
Api.account_set_answermode(acc.accp, Api.ANSWERMODE_AUTO)
acc.answerMode = Api.ANSWERMODE_AUTO
if(BaresipService.callAnswerMode == "manual") {
Api.account_set_answermode(acc.accp, Api.ANSWERMODE_MANUAL)
acc.answerMode = Api.ANSWERMODE_MANUAL
} else {
Api.account_set_answermode(acc.accp, Api.ANSWERMODE_AUTO)
acc.answerMode = Api.ANSWERMODE_AUTO
}
/*
Api.log_level_set(0)
@ -773,9 +807,13 @@ class BaresipService: Service() {
if (call != null) {
callExist = true
var audioMute = "unmute"
var videoMute = "unmute"
if(isMicMuted)
audioMute = "mute"
if(isVideoMuted)
videoMute = "mute"
Utils.propertySet("sys.ritosip.call.mute.audio", audioMute)
Utils.propertySet("sys.ritosip.call.mute.video", videoMute)
Utils.propertySet("sys.ritosip.call.status", "calling")
Utils.propertySet("sys.ritosip.call.number", call.peerUri)
@ -899,6 +937,18 @@ class BaresipService: Service() {
Utils.propertySet("sys.ritosip.media.input", "content")
}
val usbMicExist = Utils.checkUsbMicrophone()
if(usbMicExist) {
Utils.propertySet("sys.ritosip.usb.microphone", "connected")
if(audioInputDevice == "usb") {
Utils.propertySet("sys.rito.audio.input.device", "usb")
} else {
Utils.propertySet("sys.rito.audio.input.device", "codec")
}
} else {
Utils.propertySet("sys.ritosip.usb.microphone", "disconnected")
}
delay(100) // 1초마다 실행
val now = LocalDateTime.now()
@ -2341,6 +2391,7 @@ class BaresipService: Service() {
var callActionUri = ""
var isMainVisible = false
var isMicMuted = false
var isVideoMuted = false
var isRecOn = false
var toneCountry = "us"
var videoSize = Size(0, 0)
@ -2392,6 +2443,8 @@ class BaresipService: Service() {
var preferTransport = "udp"
var videoFormatHeight = 480
var connectedDisplayCount = 0
var callAnswerMode = "auto"
var audioInputDevice = "usb"
var useDisplaySplitMode = false
var displaySplitMode = DISPLAY_SPLIT_MODE_원거리_최대_근거리_우하단
var farViewDisplayId = 1

View File

@ -96,6 +96,10 @@ class Call(val callp: Long, val ua: UserAgent, val peerUri: String, val dir: Str
Api.call_set_video_direction(callp, vdir)
}
fun setVideoMute(mute: Boolean) { // added by ritoseo
Api.call_set_video_mute(callp, mute)
}
fun setMediaDirection(adir: Int, vdir: Int) {
Api.call_set_media_direction(callp, adir, vdir)
}

View File

@ -269,6 +269,12 @@ object Config {
BaresipService.preferTransport = "udp"
config = "${config}prefer_transport ${BaresipService.preferTransport}\n"
val answerMode = previousVariable("answer_mode")
if (answerMode != "")
BaresipService.callAnswerMode = answerMode
else
BaresipService.callAnswerMode = "auto"
config = "${config}answer_mode ${BaresipService.callAnswerMode}\n"
save()
BaresipService.isConfigInitialized = true

View File

@ -34,12 +34,14 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.appcompat.widget.AppCompatButton
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.graphics.Insets
import androidx.core.net.toUri
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
import androidx.lifecycle.Observer
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.google.android.material.dialog.MaterialAlertDialogBuilder
@ -127,6 +129,9 @@ class MainActivity : AppCompatActivity() {
private lateinit var comDevChangedListener: AudioManager.OnCommunicationDeviceChangedListener
private lateinit var permissions: Array<String>
private lateinit var dialogImgBtn1: AppCompatButton
private lateinit var dialogImgBtn2: AppCompatButton
private var callHandler: Handler = Handler(Looper.getMainLooper())
private var callRunnable: Runnable? = null
private var downloadsInputUri: Uri? = null
@ -238,6 +243,12 @@ class MainActivity : AppCompatActivity() {
dialpadButton = binding.dialpadButton
swipeRefresh = binding.swipeRefresh
dialogImgBtn1 = binding.dialogButtonImg1
dialogImgBtn1.setOnClickListener {
}
dialogImgBtn2 = binding.dialogButtonImg2
BaresipService.supportedCameras = Utils.supportedCameras(applicationContext).isNotEmpty()
imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
@ -1876,7 +1887,10 @@ class MainActivity : AppCompatActivity() {
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
val BTN_MISC = 188
//val BTN_MENU = 58
val SCANCODE_OPTION = 357 //MENU키 -> OPTION키로 매핑
//println("onKeyDown : ${keyCode}")
//println("onKeyDown2 : ${event?.scanCode}")
val stream = if (am.mode == AudioManager.MODE_RINGTONE)
AudioManager.STREAM_RING
else
@ -1892,13 +1906,40 @@ class MainActivity : AppCompatActivity() {
return true
}
KeyEvent.KEYCODE_BACK -> {
callVideoButton.requestFocus()
//callVideoButton.requestFocus()
return true
}
KeyEvent.KEYCODE_0, KeyEvent.KEYCODE_1, KeyEvent.KEYCODE_2, KeyEvent.KEYCODE_3, KeyEvent.KEYCODE_4, KeyEvent.KEYCODE_5, KeyEvent.KEYCODE_6,
KeyEvent.KEYCODE_7, KeyEvent.KEYCODE_8, KeyEvent.KEYCODE_9
-> {
callUri.setText(callUri.text.toString() + (keyCode - KeyEvent.KEYCODE_0).toString())
}
KeyEvent.KEYCODE_DEL -> {
val editable = callUri.text
val length = editable.length
if (length > 0) {
editable.delete(length - 1, length)
}
}
BTN_MISC -> {
return true
}
}
when (event?.scanCode) {
SCANCODE_OPTION -> {
val dialog = findViewById<FrameLayout>(R.id.dialogLayout)
if(dialog.isVisible) {
dialog.visibility = View.INVISIBLE
} else {
dialog.visibility = View.VISIBLE
findViewById<AppCompatButton>(R.id.dialogButtonImg1).requestFocus()
}
// val dialog = findViewById<FrameLayout>(R.id.dialogBase)
// val customButton = LayoutInflater.from(this).inflate(R.layout.image_button, null)
// dialog.addView(customButton)
return true
}
}
return super.onKeyDown(keyCode, event)
@ -2184,7 +2225,10 @@ class MainActivity : AppCompatActivity() {
this.setShowWhenLocked(false)
switchVideoLayout(false)
callVideoButton.requestFocus()
//callVideoButton.requestFocus()
BaresipService.isMicMuted = false
BaresipService.isVideoMuted = false
}
"message", "message show", "message reply" -> {
val i = Intent(applicationContext, ChatActivity::class.java)
@ -2959,7 +3003,8 @@ class MainActivity : AppCompatActivity() {
callButton.visibility = View.VISIBLE
callButton.isEnabled = true
}
callVideoButton.visibility = View.VISIBLE
//callVideoButton.visibility = View.VISIBLE
callVideoButton.visibility = View.INVISIBLE // modified by ritoseo
callVideoButton.isEnabled = true
hangupButton.visibility = View.INVISIBLE
hangupButton.isEnabled = false
@ -2993,7 +3038,8 @@ class MainActivity : AppCompatActivity() {
callButton.isEnabled = true
}
callVideoButton.visibility = View.VISIBLE
//callVideoButton.visibility = View.VISIBLE
callVideoButton.visibility = View.INVISIBLE // modified by ritoseo
callVideoButton.isEnabled = true
hangupButton.visibility = View.INVISIBLE
answerButton.visibility = View.INVISIBLE

View File

@ -30,6 +30,7 @@ import android.net.wifi.WifiManager
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.os.Process
import android.provider.DocumentsContract
import android.provider.MediaStore
import android.provider.OpenableColumns
@ -1259,6 +1260,15 @@ object Utils {
}
}
fun setAudioSourceDevice(dev : String) {
propertySet("sys.rito.audio.input.device", dev)
//val process = Runtime.getRuntime().exec("ritosysc shell-order=killall audioserver")
val process = Runtime.getRuntime().exec("ritosysc shell-order=killall android.hardware.audio.service")
//val process = Runtime.getRuntime().exec("ritosysc shell-order=service call audio 11 i32 1 i32 3")
process.waitFor()
process.destroy()
}
fun checkDisplayConnection(idx : Int): String {
val connId = idx + 1
val file = File("/sys/class/drm/card0-HDMI-A-${connId}/status") // 파일 경로 설정
@ -1268,6 +1278,20 @@ object Utils {
}
}
fun checkUsbMicrophone(): Boolean {
var found = false
val file = File("/proc/asound/cards") // 파일 경로 설정
file.bufferedReader().use { reader ->
reader.lineSequence().forEach { line ->
if(line.contains("USB")) {
found = true
}
}
}
return found
}
fun checkCameraConnection(idx : Int): String {
if(idx == 0) {
val file = File("/d/hdmirx/status") // 파일 경로 설정

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true">
<shape android:shape="rectangle">
<stroke android:width="2dp" android:color="#FFFFFF" />
<solid android:color="#FF9800" /> <!-- 포커스 배경 (주황색 강조) -->
<corners android:radius="16dp" />
</shape>
</item>
<item android:state_pressed="true">
<shape android:shape="rectangle">
<stroke android:width="2dp" android:color="#FFFFFF" />
<solid android:color="#FFA726" /> <!-- 포커스 배경 (주황색 강조) -->
<corners android:radius="16dp" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<stroke android:width="2dp" android:color="#88FFFFFF" />
<solid android:color="#424242" /> <!-- 포커스 배경 (회색) -->
<corners android:radius="16dp" />
</shape>
</item>
</selector>

View File

@ -98,6 +98,7 @@
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="@color/cardview_shadow_start_color"
android:clickable="false"
android:gravity="center_vertical"
android:popupBackground="@color/colorSpinnerDropdown"
android:spinnerMode="dropdown" />
@ -145,10 +146,12 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/custom_borer"
android:background="@drawable/custom_border"
android:enabled="false"
android:hint="@string/callee"
android:inputType="textEmailAddress"
android:textColorHint="@color/colorSecondaryDark"
android:textColor="#FF000000"
android:textSize="34sp">
<!-- <requestFocus /> -->
</AutoCompleteTextView>
@ -229,7 +232,8 @@
android:background="@null"
android:contentDescription="@string/video_call"
android:padding="0dp"
android:src="@drawable/call_video"></ImageButton>
android:src="@drawable/call_video"
android:visibility="invisible"></ImageButton>
<ImageButton
android:id="@+id/hangupButton"
@ -507,4 +511,92 @@
android:visibility="invisible" >
</RelativeLayout>
<FrameLayout
android:id="@+id/dialogLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible"
tools:visibility="visible">
<FrameLayout
android:id="@+id/dialogBase"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="150px"
android:layout_marginVertical="150px"
android:background="@drawable/custom_border">
<!--
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/dialogButton1"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginLeft="250px"
android:layout_marginTop="250px"
android:background="@drawable/bg_button_selector"
android:focusable="true"
android:focusableInTouchMode="true"
android:gravity="center"
android:padding="16dp"
android:text="전화걸기"
android:textColor="@color/colorWhite"
android:textSize="30sp"
android:textStyle="bold" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/dialogButton2"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginLeft="700px"
android:layout_marginTop="250px"
android:background="@drawable/bg_button_selector"
android:focusable="true"
android:focusableInTouchMode="true"
android:gravity="center"
android:padding="16dp"
android:text="설정"
android:textColor="@color/colorWhite"
android:textSize="30sp"
android:textStyle="bold" />
-->
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/dialogButtonImg1"
android:layout_width="220px"
android:layout_height="wrap_content"
android:layout_marginLeft="400px"
android:layout_marginTop="250px"
android:background="@drawable/bg_button_selector"
android:drawableTop="@drawable/callbutton2"
android:focusable="true"
android:focusableInTouchMode="true"
android:gravity="center"
android:padding="16dp"
android:drawablePadding="25px"
android:text="전화걸기"
android:textColor="@color/colorWhite"
android:textSize="30sp"
android:textStyle="bold" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/dialogButtonImg2"
android:layout_width="220px"
android:layout_height="wrap_content"
android:layout_marginLeft="950px"
android:layout_marginTop="250px"
android:background="@drawable/bg_button_selector"
android:drawableTop="@drawable/setting"
android:focusable="true"
android:focusableInTouchMode="true"
android:gravity="center"
android:padding="16dp"
android:drawablePadding="25px"
android:text="설정"
android:textColor="@color/colorWhite"
android:textSize="30sp"
android:textStyle="bold" />
</FrameLayout>
</FrameLayout>
</RelativeLayout>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/imageButton"
android:layout_width="128px"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:background="@drawable/bg_button_selector"
android:focusable="true"
android:clickable="true"
android:focusableInTouchMode="true"
android:padding="16dp">
<ImageView
android:id="@+id/buttonImage"
android:layout_width="128px"
android:layout_height="128px"
android:src="@drawable/callbutton"
android:layout_marginBottom="8dp" />
<TextView
android:id="@+id/buttonText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="전화걸기?"
android:textColor="@color/colorWhite"
android:textSize="24sp"
android:textAlignment="center" />
</LinearLayout>

View File

@ -1468,6 +1468,7 @@ struct stream *video_strm(const struct video *v);
const struct vidcodec *video_codec(const struct video *vid, bool tx);
void video_sdp_attr_decode(struct video *v);
void video_req_keyframe(struct video *vid);
void video_set_source_mute(struct video *vid, bool mute); // added by ritoseo
double video_calc_seconds(uint64_t rtp_ts);
double video_timestamp_to_seconds(uint64_t timestamp);