From b7ff1de901a9630b56fc6784d8625b2e4f0a3143 Mon Sep 17 00:00:00 2001 From: Maxime Callet <maxime.callet@savoirfairelinux.com> Date: Thu, 23 Sep 2021 17:26:52 -0400 Subject: [PATCH] call: split local and peer video surface management Change-Id: If8341dd461821d83a11d9f98764be3e4474ede4c --- .../main/java/cx/ring/client/CallActivity.kt | 23 ++-- .../client/ConversationSelectionActivity.kt | 3 +- .../java/cx/ring/fragments/CallFragment.kt | 127 ++++++------------ .../cx/ring/services/HardwareServiceImpl.kt | 77 ++++------- .../ring/services/NotificationServiceImpl.kt | 24 ++-- .../java/cx/ring/tv/call/TVCallFragment.kt | 87 +++++++++--- .../app/src/main/res/layout/tv_frag_call.xml | 78 +++++------ .../src/main/res/values-fr-rFR/strings.xml | 3 +- .../app/src/main/res/values/strings.xml | 3 +- .../kotlin/net/jami/call/CallPresenter.kt | 62 ++++----- .../src/main/kotlin/net/jami/call/CallView.kt | 5 +- .../net/jami/services/HardwareService.kt | 17 +-- 12 files changed, 243 insertions(+), 266 deletions(-) diff --git a/ring-android/app/src/main/java/cx/ring/client/CallActivity.kt b/ring-android/app/src/main/java/cx/ring/client/CallActivity.kt index 5f043279c..c70d04d53 100644 --- a/ring-android/app/src/main/java/cx/ring/client/CallActivity.kt +++ b/ring-android/app/src/main/java/cx/ring/client/CallActivity.kt @@ -96,17 +96,20 @@ class CallActivity : AppCompatActivity() { private fun handleNewIntent(intent: Intent) { val action = intent.action - val hasVideo = intent.getBooleanExtra(CallFragment.KEY_HAS_VIDEO, false) + val wantVideo = intent.getBooleanExtra(CallFragment.KEY_HAS_VIDEO, false) if (Intent.ACTION_CALL == action) { val contactId = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER) - val callFragment = CallFragment.newInstance(action, fromIntent(intent), contactId, hasVideo) + val callFragment = CallFragment.newInstance(action, fromIntent(intent), contactId, wantVideo) supportFragmentManager.beginTransaction() .replace(R.id.main_call_layout, callFragment, CALL_FRAGMENT_TAG).commit() } else if (Intent.ACTION_VIEW == action || ACTION_CALL_ACCEPT == action) { val confId = intent.getStringExtra(NotificationService.KEY_CALL_ID) - val callFragment = CallFragment.newInstance(action, confId, hasVideo) - supportFragmentManager.beginTransaction() - .replace(R.id.main_call_layout, callFragment, CALL_FRAGMENT_TAG).commit() + val currentId = callFragment?.arguments?.get(NotificationService.KEY_CALL_ID) + if (currentId != confId) { + val callFragment = CallFragment.newInstance(action, confId, wantVideo) + supportFragmentManager.beginTransaction() + .replace(R.id.main_call_layout, callFragment, CALL_FRAGMENT_TAG).commit() + } } } @@ -125,7 +128,6 @@ class CallActivity : AppCompatActivity() { } public override fun onUserLeaveHint() { - val callFragment = callFragment callFragment?.onUserLeave() } @@ -183,16 +185,11 @@ class CallActivity : AppCompatActivity() { // Get the call Fragment private val callFragment: CallFragment? get() { - var callFragment: CallFragment? = null - // Get the call Fragment - val fragment = supportFragmentManager.findFragmentByTag(CALL_FRAGMENT_TAG) - if (fragment is CallFragment) { - callFragment = fragment - } - return callFragment + return supportFragmentManager.findFragmentByTag(CALL_FRAGMENT_TAG) as CallFragment? } companion object { + private val TAG = CallActivity::class.simpleName!! const val ACTION_CALL_ACCEPT = BuildConfig.APPLICATION_ID + ".action.CALL_ACCEPT" private const val CALL_FRAGMENT_TAG = "CALL_FRAGMENT_TAG" diff --git a/ring-android/app/src/main/java/cx/ring/client/ConversationSelectionActivity.kt b/ring-android/app/src/main/java/cx/ring/client/ConversationSelectionActivity.kt index 9176a1231..1a9016422 100644 --- a/ring-android/app/src/main/java/cx/ring/client/ConversationSelectionActivity.kt +++ b/ring-android/app/src/main/java/cx/ring/client/ConversationSelectionActivity.kt @@ -36,6 +36,7 @@ import net.jami.services.ConversationFacade import net.jami.model.Account import net.jami.model.Conference import net.jami.services.CallService +import net.jami.services.NotificationService import net.jami.smartlist.SmartListViewModel import javax.inject.Inject import javax.inject.Singleton @@ -74,7 +75,7 @@ class ConversationSelectionActivity : AppCompatActivity() { public override fun onStart() { super.onStart() - val conference: Conference? = intent?.getStringExtra(CallFragment.KEY_CONF_ID)?.let { confId -> mCallService.getConference(confId) } + val conference: Conference? = intent?.getStringExtra(NotificationService.KEY_CALL_ID)?.let { confId -> mCallService.getConference(confId) } mDisposable.add(mConversationFacade .currentAccountSubject .switchMap { a: Account -> a.getConversationsViewModels(false) } diff --git a/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.kt b/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.kt index 69b49bb8d..96559dcca 100644 --- a/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.kt +++ b/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.kt @@ -152,7 +152,7 @@ class CallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView, } else if (action == Intent.ACTION_VIEW || action == CallActivity.ACTION_CALL_ACCEPT) { Log.w(TAG, "DEBUG fn initPresenter [CallFragment.kt] -> requesting fn initIncomingCall( CONF_ID, GET_CALL)") - presenter.initIncomingCall(args.getString(KEY_CONF_ID)!!, action == Intent.ACTION_VIEW) + presenter.initIncomingCall(args.getString(NotificationService.KEY_CALL_ID)!!, action == Intent.ACTION_VIEW) } } } @@ -200,37 +200,9 @@ class CallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView, } } - override fun onStart() { - super.onStart() - Log.w(TAG, "DEBUG fn onStart [CallFragment.kt] -> on start, value hasVideo = ${presenter.wantVideo}, restartvideo : $restartVideo | restartPreview : $restartPreview") - if (restartVideo && restartPreview) { - displayVideoSurface(true, !presenter.isPipMode && presenter.wantVideo) - restartVideo = false - restartPreview = false - } else if (restartVideo) { - displayVideoSurface(displayVideoSurface = true, displayPreviewContainer = false) - restartVideo = false - } - } - override fun onStop() { super.onStop() previewSnapAnimation.cancel() - binding?.let { binding -> - if (binding.videoSurface.visibility == View.VISIBLE) { - restartVideo = true - } - if (!isChoosePluginMode) { - if (binding.previewContainer.visibility == View.VISIBLE) { - restartPreview = true - } - } else { - if (binding.pluginPreviewContainer.visibility == View.VISIBLE) { - restartPreview = true - presenter.stopPlugin() - } - } - } } override fun onCreateView( @@ -693,26 +665,22 @@ class CallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView, } override fun onCreateOptionsMenu(m: Menu, inf: MenuInflater) { - super.onCreateOptionsMenu(m, inf) inf.inflate(R.menu.ac_call, m) dialPadBtn = m.findItem(R.id.menuitem_dialpad) pluginsMenuBtn = m.findItem(R.id.menuitem_video_plugins) } override fun onPrepareOptionsMenu(menu: Menu) { - super.onPrepareOptionsMenu(menu) + Log.w(CallPresenter.TAG, "DEBUG onPrepareOptionsMenu") presenter.prepareOptionMenu() } override fun onOptionsItemSelected(item: MenuItem): Boolean { - super.onOptionsItemSelected(item) - val itemId = item.itemId - if (itemId == android.R.id.home) { - presenter.chatClick() - } else if (itemId == R.id.menuitem_dialpad) { - presenter.dialpadClick() - } else if (itemId == R.id.menuitem_video_plugins) { - displayVideoPluginsCarousel() + when (item.itemId) { + android.R.id.home -> presenter.chatClick() + R.id.menuitem_dialpad -> presenter.dialpadClick() + R.id.menuitem_video_plugins -> displayVideoPluginsCarousel() + else -> return super.onOptionsItemSelected(item) } return true } @@ -732,34 +700,23 @@ class CallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView, } override fun displayContactBubble(display: Boolean) { - if (binding != null) binding!!.contactBubbleLayout.handler.post { - if (binding != null) binding!!.contactBubbleLayout.visibility = - if (display) View.VISIBLE else View.GONE + Log.w(TAG, "DEBUG fn displayContactBubble -> $display") + binding?.apply { + contactBubbleLayout.visibility = if (display) View.VISIBLE else View.GONE } } - override fun displayVideoSurface( - displayVideoSurface: Boolean, - displayPreviewContainer: Boolean - ) { - Log.w(TAG, "DEBUG fn displayVideoSurface [CallFragment.kt] -> changement des affichages videos displayVideoSurface: $displayVideoSurface; displayPreviewContainer: $displayPreviewContainer") - binding!!.videoSurface.visibility = if (displayVideoSurface) View.VISIBLE else View.GONE + override fun displayPeerVideo(display: Boolean) { + Log.w(TAG, "DEBUG fn displayPeerVideo -> $display") + binding!!.videoSurface.visibility = if (display) View.VISIBLE else View.GONE + displayContactBubble(!display) + } - if (isChoosePluginMode) { - Log.w(TAG, "DEBUG fn displayVideoSurface |1| inside => if (isChoosePluginMode) {displayPreviewContainer: $displayPreviewContainer}") - binding!!.pluginPreviewSurface.visibility = - if (displayPreviewContainer) View.VISIBLE else View.GONE - binding!!.pluginPreviewContainer.visibility = - if (displayPreviewContainer) View.VISIBLE else View.GONE - binding!!.previewContainer.visibility = View.GONE - } else { - Log.w(TAG, "DEBUG fn displayVideoSurface |2| inside => else { displayPreviewContainer : $displayPreviewContainer}") - binding!!.pluginPreviewSurface.visibility = View.GONE - binding!!.pluginPreviewContainer.visibility = View.GONE - binding!!.previewContainer.visibility = - if (displayPreviewContainer) View.VISIBLE else View.GONE - } - updateMenu() + override fun displayLocalVideo(display: Boolean) { + Log.w(TAG, "DEBUG fn displayLocalVideo -> $display") + /*binding!!.pluginPreviewSurface.visibility = View.GONE + binding!!.pluginPreviewContainer.visibility = View.GONE*/ + binding!!.previewContainer.visibility = if (display) View.VISIBLE else View.GONE } // todo Change function name, this name is misleading, this function concerns PIP preview @@ -853,6 +810,10 @@ class CallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView, activity.intent = Intent(Intent.ACTION_VIEW, ConversationPath.toUri(call.account!!, conversationUri), context, CallActivity::class.java) .apply { putExtra(NotificationService.KEY_CALL_ID, call.confId ?: call.daemonIdString) } + arguments = Bundle().apply { + putString(KEY_ACTION, Intent.ACTION_VIEW) + putString(NotificationService.KEY_CALL_ID, call.confId ?: call.daemonIdString) + } } } if (hasProfileName) { @@ -968,24 +929,19 @@ class CallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView, isSpeakerOn: Boolean, hasMultipleCamera: Boolean, canDial: Boolean, showPluginBtn: Boolean, onGoingCall: Boolean, hasActiveVideo: Boolean ) { - // - if (!hasActiveVideo) { - binding!!.callCameraSwitchBtn.isChecked = true - binding!!.callCameraSwitchBtn.setImageResource(R.drawable.baseline_videocam_off_24) - } - binding!!.callCameraFlipBtn.visibility = if (hasMultipleCamera && !binding!!.callCameraSwitchBtn.isChecked) View.VISIBLE else View.GONE - - if (dialPadBtn != null) { - dialPadBtn!!.isVisible = canDial - } - if (pluginsMenuBtn != null) { - pluginsMenuBtn!!.isVisible = showPluginBtn + Log.w(CallPresenter.TAG, "DEBUG initMenu hasActiveVideo: $hasActiveVideo; hasMultipleCamera: $hasMultipleCamera") + binding?.apply { + callSpeakerBtn.visibility = if (hasActiveVideo) View.GONE else View.VISIBLE + callCameraSwitchBtn.isChecked = !hasActiveVideo + callCameraSwitchBtn.setImageResource(if (hasActiveVideo) R.drawable.baseline_videocam_24 else R.drawable.baseline_videocam_off_24) + callCameraFlipBtn.visibility = if (hasMultipleCamera && hasActiveVideo) View.VISIBLE else View.GONE } + dialPadBtn?.isVisible = canDial + pluginsMenuBtn?.isVisible = showPluginBtn updateMenu() } - override fun initNormalStateDisplay(audioOnly: Boolean, isMuted: Boolean) { - Log.w(TAG, "initNormalStateDisplay") + override fun initNormalStateDisplay(isMuted: Boolean) { binding?.apply { shapeRipple.stopRipple() callAcceptBtn.visibility = View.GONE @@ -993,7 +949,7 @@ class CallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView, callRefuseBtn.visibility = View.GONE callControlGroup.visibility = View.VISIBLE callHangupBtn.visibility = View.VISIBLE - contactBubbleLayout.visibility = if (audioOnly) View.VISIBLE else View.GONE + contactBubbleLayout.visibility = View.VISIBLE callMicBtn.isChecked = isMuted } requireActivity().invalidateOptionsMenu() @@ -1203,8 +1159,10 @@ class CallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView, //todo if videomode, should mute/unmute audio output, if audio only, should switch between speaker options fun speakerClicked() { - presenter.speakerClick(binding!!.callSpeakerBtn.isChecked) - //binding!!.callSpeakerBtn.setImageResource(if (binding!!.callSpeakerBtn.isChecked) R.drawable.baseline_sound_on_24 else R.drawable.baseline_sound_off_24) + binding?.let { + presenter.speakerClick(it.callSpeakerBtn.isChecked) + //it.callSpeakerBtn.setImageResource(if (it.callSpeakerBtn.isChecked) R.drawable.baseline_sound_on_24 else R.drawable.baseline_sound_off_24) + } } private fun startScreenShare(mediaProjection: MediaProjection?) { @@ -1273,7 +1231,7 @@ class CallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView, override fun startAddParticipant(conferenceId: String) { startActivityForResult(Intent(Intent.ACTION_PICK) .setClass(requireActivity(), ConversationSelectionActivity::class.java) - .putExtra(KEY_CONF_ID, conferenceId), + .putExtra(NotificationService.KEY_CALL_ID, conferenceId), REQUEST_CODE_ADD_PARTICIPANT) } @@ -1401,7 +1359,7 @@ class CallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView, } //change preview image - displayVideoSurface(true, presenter.wantVideo) + //displayPeerVideo(true, presenter.wantVideo) } /** @@ -1455,7 +1413,6 @@ class CallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView, val TAG = CallFragment::class.simpleName!! const val ACTION_PLACE_CALL = "PLACE_CALL" const val KEY_ACTION = "action" - const val KEY_CONF_ID = "confId" const val KEY_HAS_VIDEO = "HAS_VIDEO" private const val REQUEST_CODE_ADD_PARTICIPANT = 6 private const val REQUEST_PERMISSION_INCOMING = 1003 @@ -1463,6 +1420,7 @@ class CallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView, private const val REQUEST_CODE_SCREEN_SHARE = 7 fun newInstance(action: String, path: ConversationPath?, contactId: String?, hasVideo: Boolean): CallFragment { + Log.w(TAG, "DEBUG newInstance $action $path $contactId $hasVideo") return CallFragment().apply { arguments = Bundle().apply { putString(KEY_ACTION, action) @@ -1474,10 +1432,11 @@ class CallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView, } fun newInstance(action: String, confId: String?, hasVideo: Boolean): CallFragment { + Log.w(TAG, "DEBUG newInstance $action $confId $hasVideo") return CallFragment().apply { arguments = Bundle().apply { putString(KEY_ACTION, action) - putString(KEY_CONF_ID, confId) + putString(NotificationService.KEY_CALL_ID, confId) putBoolean(KEY_HAS_VIDEO, hasVideo) } } diff --git a/ring-android/app/src/main/java/cx/ring/services/HardwareServiceImpl.kt b/ring-android/app/src/main/java/cx/ring/services/HardwareServiceImpl.kt index 77b0d779e..0b52f3e6b 100644 --- a/ring-android/app/src/main/java/cx/ring/services/HardwareServiceImpl.kt +++ b/ring-android/app/src/main/java/cx/ring/services/HardwareServiceImpl.kt @@ -320,30 +320,22 @@ class HardwareServiceImpl( } override fun decodingStarted(id: String, shmPath: String, width: Int, height: Int, isMixer: Boolean) { - Log.i(TAG, "decodingStarted() " + id + " " + width + "x" + height) + Log.i(TAG, "DEBUG decodingStarted() " + id + " " + width + "x" + height) val shm = Shm(id, width, height) videoInputs[id] = shm + videoEvents.onNext(VideoEvent(id, start = true)) videoSurfaces[id]?.get()?.let { holder -> shm.window = startVideo(id, holder.surface, width, height) if (shm.window == 0L) { - Log.i(TAG, "DJamiService.decodingStarted() no window !") - val event = VideoEvent() - event.start = true - event.callId = shm.id - videoEvents.onNext(event) - return + Log.w(TAG, "DJamiService.decodingStarted() no window !") + } else { + videoEvents.onNext(VideoEvent(shm.id, started = true, w = shm.w, h = shm.h)) } - val event = VideoEvent() - event.callId = shm.id - event.started = true - event.w = shm.w - event.h = shm.h - videoEvents.onNext(event) } } override fun decodingStopped(id: String, shmPath: String, isMixer: Boolean) { - Log.i(TAG, "decodingStopped() $id") + Log.i(TAG, "DEBUG decodingStopped() $id") val shm = videoInputs.remove(id) ?: return if (shm.window != 0L) { try { @@ -352,9 +344,14 @@ class HardwareServiceImpl( Log.e(TAG, "decodingStopped error$e") } shm.window = 0 + videoEvents.onNext(VideoEvent(id, started = false)) } } + override fun hasInput(id: String): Boolean { + return videoInputs[id] !== null + } + override fun getCameraInfo(camId: String, formats: IntVect, sizes: UintVect, rates: UintVect) { // Use a larger resolution for Android 6.0+, 64 bits devices val useLargerSize = @@ -444,9 +441,7 @@ class HardwareServiceImpl( if (surface == null) { Log.w(TAG, "Can't start capture: no surface registered.") cameraService.setPreviewParams(videoParams) - val event = VideoEvent() - event.start = true - videoEvents.onNext(event) + videoEvents.onNext(VideoEvent(start = true)) return } val conf = mCameraPreviewCall.get() @@ -491,12 +486,12 @@ class HardwareServiceImpl( ) } cameraService.setPreviewParams(videoParams) - val event = VideoEvent() - event.started = true - event.w = videoParams.width - event.h = videoParams.height - event.rot = videoParams.rotation - videoEvents.onNext(event) + videoEvents.onNext(VideoEvent( + started = true, + w = videoParams.width, + h = videoParams.height, + rot = videoParams.rotation + )) } override fun stopCapture() { @@ -521,11 +516,7 @@ class HardwareServiceImpl( if (cameraService.isOpen) { //final CameraService.VideoParams params = previewParams; cameraService.closeCamera() - val event = VideoEvent() - event.started = false - //event.w = params.width; - //event.h = params.height; - videoEvents.onNext(event) + videoEvents.onNext(VideoEvent(started = false)) } mIsCapturing = false } @@ -543,17 +534,10 @@ class HardwareServiceImpl( } if (shm == null || shm.window == 0L) { Log.i(TAG, "DJamiService.addVideoSurface() no window !") - val event = VideoEvent() - event.start = true - videoEvents.onNext(event) - return + //videoEvents.onNext(VideoEvent(id, start = true)) + } else { + videoEvents.onNext(VideoEvent(shm.id, started = true, w = shm.w, h = shm.h)) } - val event = VideoEvent() - event.callId = shm.id - event.started = true - event.w = shm.w - event.h = shm.h - videoEvents.onNext(event) } override fun updateVideoSurfaceId(currentId: String, newId: String) { @@ -607,10 +591,7 @@ class HardwareServiceImpl( } shm.window = 0 } - val event = VideoEvent() - event.callId = shm.id - event.started = false - videoEvents.onNext(event) + //videoEvents.onNext(VideoEvent(shm.id, started = false)) } override fun removePreviewVideoSurface() { @@ -642,12 +623,12 @@ class HardwareServiceImpl( cameraService.setOrientation(rotation) if (mCapturingId != null) { val videoParams = cameraService.getParams(mCapturingId) - val event = VideoEvent() - event.started = true - event.w = videoParams.width - event.h = videoParams.height - event.rot = videoParams.rotation - videoEvents.onNext(event) + videoEvents.onNext(VideoEvent( + started = true, + w = videoParams.width, + h = videoParams.height, + rot = videoParams.rotation + )) } } diff --git a/ring-android/app/src/main/java/cx/ring/services/NotificationServiceImpl.kt b/ring-android/app/src/main/java/cx/ring/services/NotificationServiceImpl.kt index 044f6035d..cac0492a5 100644 --- a/ring-android/app/src/main/java/cx/ring/services/NotificationServiceImpl.kt +++ b/ring-android/app/src/main/java/cx/ring/services/NotificationServiceImpl.kt @@ -145,31 +145,27 @@ class NotificationServiceImpl( R.drawable.baseline_call_end_24, mContext.getText(R.string.action_call_decline), PendingIntent.getService(mContext, random.nextInt(), Intent(DRingService.ACTION_CALL_REFUSE) .setClass(mContext, DRingService::class.java) - .putExtra(NotificationService.KEY_CALL_ID, call.daemonIdString), PendingIntent.FLAG_ONE_SHOT - ) - ) + .putExtra(NotificationService.KEY_CALL_ID, call.daemonIdString), PendingIntent.FLAG_ONE_SHOT)) Log.w(TAG, "DEBUG fn buildCallNotification [NotificationServiceImpl.kt] -> conference.hasvideo = ${conference.hasVideo()} ") if (conference.hasVideo()){ messageNotificationBuilder - .addAction(R.id.btnAcceptAudio, if (ongoingCallId == null) mContext.getText(R.string.action_call_accept_audio) else mContext.getText(R.string.action_call_end_accept), - PendingIntent.getService(mContext, random.nextInt(), Intent(if (ongoingCallId == null) DRingService.ACTION_CALL_ACCEPT else DRingService.ACTION_CALL_END_ACCEPT) + .addAction(R.drawable.baseline_call_24, if (ongoingCallId == null) mContext.getText(R.string.action_call_accept_audio) else mContext.getText(R.string.action_call_hold_accept), + PendingIntent.getService(mContext, random.nextInt(), Intent(if (ongoingCallId == null) DRingService.ACTION_CALL_ACCEPT else DRingService.ACTION_CALL_HOLD_ACCEPT) .setClass(mContext, DRingService::class.java) - .putExtra(NotificationService.KEY_END_ID, ongoingCallId) + .putExtra(NotificationService.KEY_HOLD_ID, ongoingCallId) .putExtra(NotificationService.KEY_CALL_ID, call.daemonIdString) - .putExtra(CallFragment.KEY_HAS_VIDEO, false), PendingIntent.FLAG_ONE_SHOT) - ) - .addAction(R.id.btnAcceptVideo, if (ongoingCallId == null) mContext.getText(R.string.action_call_accept_video) else mContext.getText(R.string.action_call_end_accept), - PendingIntent.getService(mContext, random.nextInt(), Intent(if (ongoingCallId == null) DRingService.ACTION_CALL_ACCEPT else DRingService.ACTION_CALL_END_ACCEPT) + .putExtra(CallFragment.KEY_HAS_VIDEO, false), PendingIntent.FLAG_ONE_SHOT)) + .addAction(R.drawable.baseline_videocam_24, if (ongoingCallId == null) mContext.getText(R.string.action_call_accept_video) else mContext.getText(R.string.action_call_hold_accept_video), + PendingIntent.getService(mContext, random.nextInt(), Intent(if (ongoingCallId == null) DRingService.ACTION_CALL_ACCEPT else DRingService.ACTION_CALL_HOLD_ACCEPT) .setClass(mContext, DRingService::class.java) - .putExtra(NotificationService.KEY_END_ID, ongoingCallId) + .putExtra(NotificationService.KEY_HOLD_ID, ongoingCallId) .putExtra(NotificationService.KEY_CALL_ID, call.daemonIdString) - .putExtra(CallFragment.KEY_HAS_VIDEO, true), PendingIntent.FLAG_ONE_SHOT) - ) + .putExtra(CallFragment.KEY_HAS_VIDEO, true), PendingIntent.FLAG_ONE_SHOT)) } else { messageNotificationBuilder.addAction( - R.id.btnAcceptAudio, if (ongoingCallId == null) mContext.getText(R.string.action_call_accept_audio) else mContext.getText(R.string.action_call_end_accept), + R.drawable.baseline_call_24, if (ongoingCallId == null) mContext.getText(R.string.action_call_accept_audio) else mContext.getText(R.string.action_call_end_accept), PendingIntent.getService(mContext, random.nextInt(), Intent(if (ongoingCallId == null) DRingService.ACTION_CALL_ACCEPT else DRingService.ACTION_CALL_END_ACCEPT) .setClass(mContext, DRingService::class.java) .putExtra(NotificationService.KEY_END_ID, ongoingCallId) diff --git a/ring-android/app/src/main/java/cx/ring/tv/call/TVCallFragment.kt b/ring-android/app/src/main/java/cx/ring/tv/call/TVCallFragment.kt index fce5146af..0d06744f4 100644 --- a/ring-android/app/src/main/java/cx/ring/tv/call/TVCallFragment.kt +++ b/ring-android/app/src/main/java/cx/ring/tv/call/TVCallFragment.kt @@ -76,6 +76,7 @@ import net.jami.model.Contact import net.jami.model.Uri import net.jami.services.DeviceRuntimeService import net.jami.services.HardwareService.AudioState +import net.jami.services.NotificationService import java.util.* import javax.inject.Inject import kotlin.math.max @@ -119,7 +120,7 @@ class TVCallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView if (action == CallFragment.ACTION_PLACE_CALL || action == Intent.ACTION_CALL) prepareCall(false) else if (action == Intent.ACTION_VIEW || action == CallActivity.ACTION_CALL_ACCEPT) - presenter.initIncomingCall(args.getString(CallFragment.KEY_CONF_ID)!!, action == Intent.ACTION_VIEW) + presenter.initIncomingCall(args.getString(NotificationService.KEY_CALL_ID)!!, action == Intent.ACTION_VIEW) } } @@ -262,10 +263,17 @@ class TVCallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView override fun displayContactBubble(display: Boolean) { binding!!.contactBubbleLayout.visibility = if (display) View.VISIBLE else View.GONE } + override fun displayPeerVideo(display: Boolean) { + Log.w(CallFragment.TAG, "DEBUG fn displayPeerVideo -> $display") + binding!!.videoSurface.visibility = if (display) View.VISIBLE else View.GONE + displayContactBubble(!display) + } - override fun displayVideoSurface(displayVideoSurface: Boolean, displayPreviewContainer: Boolean) { - binding!!.videoSurface.visibility = if (displayVideoSurface) View.VISIBLE else View.GONE - binding!!.previewContainer.visibility = if (displayPreviewContainer) View.VISIBLE else View.GONE + override fun displayLocalVideo(display: Boolean) { + Log.w(CallFragment.TAG, "DEBUG fn displayLocalVideo -> $display") + /*binding!!.pluginPreviewSurface.visibility = View.GONE + binding!!.pluginPreviewContainer.visibility = View.GONE*/ + binding!!.previewContainer.visibility = if (display) View.VISIBLE else View.GONE } override fun displayPreviewSurface(display: Boolean) { @@ -320,20 +328,17 @@ class TVCallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView } } - override fun initMenu( - isSpeakerOn: Boolean, displayFlip: Boolean, canDial: Boolean, - showPluginBtn: Boolean, onGoingCall: Boolean, hasActiveVideo: Boolean - ) { + override fun initMenu(isSpeakerOn: Boolean, displayFlip: Boolean, canDial: Boolean, showPluginBtn: Boolean, onGoingCall: Boolean, hasActiveVideo: Boolean) { } - override fun initNormalStateDisplay(audioOnly: Boolean, muted: Boolean) { + override fun initNormalStateDisplay(muted: Boolean) { mSession!!.isActive = true binding?.apply { shapeRipple.stopRipple() callAcceptBtn.visibility = View.GONE callRefuseBtn.visibility = View.GONE callHangupBtn.visibility = View.VISIBLE - contactBubbleLayout.visibility = if (audioOnly) View.VISIBLE else View.INVISIBLE + contactBubbleLayout.visibility = View.VISIBLE } requireActivity().invalidateOptionsMenu() handleVisibilityTimer() @@ -492,31 +497,71 @@ class TVCallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView } @SuppressLint("RestrictedApi") - override fun updateConfInfo(info: List<ParticipantInfo>) { - val binding = binding!! + override fun updateConfInfo(participantInfo: List<ParticipantInfo>) { + val binding = binding ?: return + mConferenceMode = participantInfo.size > 1 binding.participantLabelContainer.removeAllViews() - if (info.isNotEmpty()) { + if (participantInfo.isNotEmpty()) { + val username = if (participantInfo.size > 1) + "Conference with ${participantInfo.size} people" + else participantInfo[0].contact.displayName + val displayName = if (participantInfo.size > 1) null else participantInfo[0].contact.displayName + val hasProfileName = displayName != null && !displayName.contentEquals(username) + val call = participantInfo[0].call + if (call != null) { + val conversationUri = if (call.conversationId != null) + Uri(Uri.SWARM_SCHEME, call.conversationId!!) + else call.contact!!.conversationUri.blockingFirst() + activity?.let { activity -> + activity.intent = Intent(Intent.ACTION_VIEW, + ConversationPath.toUri(call.account!!, conversationUri), context, TVCallActivity::class.java) + .apply { putExtra(NotificationService.KEY_CALL_ID, call.confId ?: call.daemonIdString) } + } + arguments = Bundle().apply { + putString(CallFragment.KEY_ACTION, Intent.ACTION_VIEW) + putString(NotificationService.KEY_CALL_ID, call.confId ?: call.daemonIdString) + } + } + if (hasProfileName) { + binding.contactBubbleNumTxt.visibility = View.VISIBLE + binding.contactBubbleTxt.text = displayName + binding.contactBubbleNumTxt.text = username + } else { + binding.contactBubbleNumTxt.visibility = View.GONE + binding.contactBubbleTxt.text = username + } + binding.contactBubble.setImageDrawable(AvatarDrawable.Builder() + .withContact(participantInfo[0].contact) + .withCircleCrop(true) + .withPresence(false) + .build(requireActivity())) + val inflater = LayoutInflater.from(binding.participantLabelContainer.context) - for (i in info) { + for (i in participantInfo) { val displayName = i.contact.displayName if (!TextUtils.isEmpty(displayName)) { val label = ItemParticipantLabelBinding.inflate(inflater) val params = PercentFrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) params.percentLayoutInfo.leftMarginPercent = i.x / mVideoWidth.toFloat() params.percentLayoutInfo.topMarginPercent = i.y / mVideoHeight.toFloat() + params.percentLayoutInfo.rightMarginPercent = + 1f - (i.x + i.w) / mVideoWidth.toFloat() + //params.getPercentLayoutInfo().rightMarginPercent = (i.x + i.w) / (float) mVideoWidth; label.participantName.text = displayName + label.moderator.visibility = if (i.isModerator) View.VISIBLE else View.GONE + label.mute.visibility = if (i.audioMuted) View.VISIBLE else View.GONE binding.participantLabelContainer.addView(label.root, params) } } } - binding.participantLabelContainer.visibility = if (info.isEmpty()) View.GONE else View.VISIBLE + binding.participantLabelContainer.visibility = if (participantInfo.isEmpty()) View.GONE else View.VISIBLE if (!mConferenceMode) { - binding.confControlGroup!!.visibility = View.GONE + binding.confControlGroup.visibility = View.GONE } else { - binding.confControlGroup!!.visibility = View.VISIBLE - confAdapter?.apply { updateFromCalls(info) } + binding.confControlGroup.visibility = View.VISIBLE + confAdapter?.apply { updateFromCalls(participantInfo) } // Create new adapter - ?: ConfParticipantAdapter(info, object : ConfParticipantSelected { + ?: ConfParticipantAdapter(participantInfo, object : ConfParticipantSelected { override fun onParticipantSelected(view: View, contact: ParticipantInfo) { val maximized = presenter.isMaximized(contact) val popup = PopupMenu(view.context, view) @@ -594,7 +639,7 @@ class TVCallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView override fun startAddParticipant(conferenceId: String) { startActivityForResult(Intent(Intent.ACTION_PICK) .setClass(requireActivity(), ConversationSelectionActivity::class.java) - .putExtra(CallFragment.KEY_CONF_ID, conferenceId), + .putExtra(NotificationService.KEY_CALL_ID, conferenceId), REQUEST_CODE_ADD_PARTICIPANT) } @@ -690,7 +735,7 @@ class TVCallFragment : BaseSupportFragment<CallPresenter, CallView>(), CallView fun newInstance(action: String, confId: String?): TVCallFragment { return TVCallFragment().apply { arguments = Bundle().apply { putString(CallFragment.KEY_ACTION, action) - putString(CallFragment.KEY_CONF_ID, confId) + putString(NotificationService.KEY_CALL_ID, confId) }} } } diff --git a/ring-android/app/src/main/res/layout/tv_frag_call.xml b/ring-android/app/src/main/res/layout/tv_frag_call.xml index a1e71e2f9..2d45aecaa 100644 --- a/ring-android/app/src/main/res/layout/tv_frag_call.xml +++ b/ring-android/app/src/main/res/layout/tv_frag_call.xml @@ -18,10 +18,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. --> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" - xmlns:tools="http://schemas.android.com/tools"> + xmlns:tools="http://schemas.android.com/tools" + tools:context=".tv.call.TVCallActivity"> <data> - <variable name="presenter" type="cx.ring.tv.call.TVCallFragment" /> @@ -33,7 +33,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. android:clipChildren="false" android:clipToPadding="false" android:keepScreenOn="true" - tools:context=".tv.call.TVCallActivity"> + tools:background="@color/cardview_dark_background"> <SurfaceView android:id="@+id/video_surface" @@ -74,25 +74,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. tools:visibility="visible" /> </androidx.cardview.widget.CardView> - <androidx.cardview.widget.CardView - android:id="@+id/plugin_preview_container" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentEnd="true" - android:layout_alignParentBottom="true" - android:layout_margin="12dp" - android:visibility="gone" - app:cardCornerRadius="16dp" - app:cardPreventCornerOverlap="false"> - - <cx.ring.views.AutoFitTextureView - android:id="@+id/plugin_preview_surface" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:visibility="visible" - tools:visibility="visible" /> - </androidx.cardview.widget.CardView> - <LinearLayout android:id="@+id/contact_bubble_layout" android:layout_width="match_parent" @@ -207,6 +188,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. app:useCompatPadding="true" /> </LinearLayout> + </LinearLayout> </LinearLayout> @@ -216,7 +198,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" - android:layout_margin="16dp" + android:layout_marginStart="16dp" + android:layout_marginTop="16dp" + android:layout_marginEnd="16dp" android:layout_marginBottom="48dp" android:onClick="@{() -> presenter.hangUpClicked()}" android:tint="@color/white" @@ -224,25 +208,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. app:backgroundTint="@color/colorError" app:rippleColor="@android:color/white" app:srcCompat="@drawable/baseline_call_end_24" - app:useCompatPadding="true" /> - - <com.google.android.material.floatingactionbutton.FloatingActionButton - android:id="@+id/call_add_btn" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_toRightOf="@+id/call_hangup_btn" - android:layout_toEndOf="@+id/call_hangup_btn" - android:layout_alignParentBottom="true" - android:layout_marginStart="16dp" - android:layout_marginTop="16dp" - android:layout_marginEnd="16dp" - android:layout_marginBottom="16dp" - android:onClick="@{() -> presenter.addParticipant()}" - android:tint="@color/white" - android:visibility="gone" - app:backgroundTint="@color/blue_400" - app:rippleColor="@android:color/white" - app:srcCompat="@drawable/baseline_person_add_24" app:useCompatPadding="true" tools:visibility="visible" /> @@ -274,5 +239,32 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. </LinearLayout> + <com.google.android.material.floatingactionbutton.FloatingActionButton + android:id="@+id/call_add_btn" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_toRightOf="@+id/call_hangup_btn" + android:layout_toEndOf="@+id/call_hangup_btn" + android:layout_alignParentBottom="true" + android:layout_marginStart="16dp" + android:layout_marginTop="16dp" + android:layout_marginEnd="16dp" + android:layout_marginBottom="48dp" + android:onClick="@{() -> presenter.addParticipant()}" + android:visibility="gone" + app:srcCompat="@drawable/baseline_person_add_24" + app:useCompatPadding="true" + tools:visibility="visible" /> + + <androidx.recyclerview.widget.RecyclerView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:id="@+id/conf_control_group" + android:layout_alignParentEnd="true" + android:layout_alignParentTop="true" + app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" + tools:listitem="@layout/item_conference_participant" + tools:itemCount="4" /> + </RelativeLayout> -</layout> \ No newline at end of file +</layout> diff --git a/ring-android/app/src/main/res/values-fr-rFR/strings.xml b/ring-android/app/src/main/res/values-fr-rFR/strings.xml index f2beb2ba2..fc7dc1afe 100644 --- a/ring-android/app/src/main/res/values-fr-rFR/strings.xml +++ b/ring-android/app/src/main/res/values-fr-rFR/strings.xml @@ -97,7 +97,8 @@ <string name="action_call_accept">Prendre un appel</string> <string name="action_call_accept_audio">Répondre en audio</string> <string name="action_call_accept_video">Répondre en video</string> - <string name="action_call_hold_accept">Mettre en attente et prendre l\'appel</string> + <string name="action_call_hold_accept">Répondre en audio</string> + <string name="action_call_hold_accept_video">Répondre en video</string> <string name="action_call_end_accept">Terminer et prendre l\'appel</string> <string name="action_call_decline">Refuser</string> <string name="action_call_mic_mute">Couper le micro</string> diff --git a/ring-android/app/src/main/res/values/strings.xml b/ring-android/app/src/main/res/values/strings.xml index 03483258b..d714c9f62 100644 --- a/ring-android/app/src/main/res/values/strings.xml +++ b/ring-android/app/src/main/res/values/strings.xml @@ -152,7 +152,8 @@ along with this program; if not, write to the Free Software <string name="action_call_accept">Take call</string> <string name="action_call_accept_audio">Answer in audio</string> <string name="action_call_accept_video">Answer in video</string> - <string name="action_call_hold_accept">Hold and take call</string> + <string name="action_call_hold_accept">Hold and take call audio</string> + <string name="action_call_hold_accept_video">Hold and take call video</string> <string name="action_call_end_accept">End and take call</string> <string name="action_call_decline">Decline</string> <string name="action_call_mic_mute">Mute microphone</string> diff --git a/ring-android/libjamiclient/src/main/kotlin/net/jami/call/CallPresenter.kt b/ring-android/libjamiclient/src/main/kotlin/net/jami/call/CallPresenter.kt index b12a0c7ef..256d4368b 100644 --- a/ring-android/libjamiclient/src/main/kotlin/net/jami/call/CallPresenter.kt +++ b/ring-android/libjamiclient/src/main/kotlin/net/jami/call/CallPresenter.kt @@ -189,6 +189,7 @@ class CallPresenter @Inject constructor( } fun prepareOptionMenu() { + Log.w(TAG, "DEBUG prepareOptionMenu") val isSpeakerOn: Boolean = mHardwareService.isSpeakerphoneOn //boolean hasContact = mSipCall != null && null != mSipCall.getContact() && mSipCall.getContact().isUnknown(); val conference = mConference @@ -280,7 +281,6 @@ class CallPresenter @Inject constructor( currentSurfaceId = newId } mHardwareService.addVideoSurface(conference.id, holder) - view?.displayContactBubble(false) } private fun videoSurfaceUpdateId(newId: String) { @@ -356,7 +356,7 @@ class CallPresenter @Inject constructor( private fun confUpdate(call: Conference) { mConference = call - Log.w(TAG, "confUpdate " + call.id + " " + call.state) + Log.w(TAG, "DEBUG confUpdate " + call.id + " " + call.state) val status = call.state if (status === CallStatus.HOLD) { if (call.isSimpleCall) mCallService.unhold(call.id) else JamiService.addMainParticipant(call.id) @@ -364,23 +364,28 @@ class CallPresenter @Inject constructor( val hasVideo = call.hasVideo() val hasActiveVideo = call.hasActiveVideo() videoIsMuted = !hasActiveVideo + val view = view ?: return view.updateMenu() + if (call.isOnGoing) { mOnGoingCall = true - view.initNormalStateDisplay(!hasVideo, isMicrophoneMuted) - view.updateMenu() + view.initNormalStateDisplay(isMicrophoneMuted) if (hasVideo) { mHardwareService.setPreviewSettings() mHardwareService.updatePreviewVideoSurface(call) videoSurfaceUpdateId(call.id) pluginSurfaceUpdateId(call.pluginId) - view.displayVideoSurface(true, hasActiveVideo && mDeviceRuntimeService.hasVideoPermission()) + //view.displayPeerVideo(hasVideo) + view.displayLocalVideo(hasActiveVideo && mDeviceRuntimeService.hasVideoPermission()) if (permissionChanged) { mHardwareService.switchInput(call.id, permissionChanged) permissionChanged = false } } + if (mHardwareService.hasInput(call.id)) { + view.displayPeerVideo(true) + } timeUpdateTask?.dispose() timeUpdateTask = mUiScheduler.schedulePeriodicallyDirect({ updateTime() }, 0, 1, TimeUnit.SECONDS) } else if (call.isRinging) { @@ -388,7 +393,7 @@ class CallPresenter @Inject constructor( val scall = call.call!! view.handleCallWakelock(!hasVideo) if (scall.isIncoming) { - if (mAccountService.getAccount(scall.account!!)!!.isAutoanswerEnabled) { + if (mAccountService.getAccount(scall.account)?.isAutoanswerEnabled == true) { Log.w(TAG, "Accept because of autoanswer") mCallService.accept(scall.daemonIdString!!, wantVideo) // only display the incoming call screen if the notification is a full screen intent @@ -431,41 +436,38 @@ class CallPresenter @Inject constructor( } private fun onVideoEvent(event: VideoEvent) { - Log.w(TAG, "DEBUG fn onVideoEvent") - Log.d(TAG, "VIDEO_EVENT: " + event.start + " " + event.callId + " " + event.w + "x" + event.h) + Log.w(TAG, "DEBUG onVideoEvent $event") val view = view ?: return val conference = mConference - if (event.start) { - Log.w(TAG, "DEBUG fn onVideoEvent |1| inside => if (event.start) ") - view.displayVideoSurface(true, !isPipMode && mDeviceRuntimeService.hasVideoPermission() && conference?.hasActiveVideo() == true) - } else if (conference != null && conference.id == event.callId) { - Log.w(TAG, "DEBUG fn onVideoEvent |2| inside => else if (mConference != null && mConference!!.id == event.callId)") - Log.w(TAG, "DEBUG fn onVideoEvent |2| inside => event.started ${event.started} && !isPipMode ${!isPipMode} && mDeviceRuntimeService.hasVideoPermission() ${mDeviceRuntimeService.hasVideoPermission()} && hasVideo $wantVideo && !videoIsMuted ${!videoIsMuted}") - view.displayVideoSurface(event.started, - event.started && !isPipMode && mDeviceRuntimeService.hasVideoPermission() && conference.hasActiveVideo()) - if (event.started) { - videoWidth = event.w - videoHeight = event.h - view.resetVideoSize(videoWidth, videoHeight) + if (event.callId == null) { + Log.w(TAG, "DEBUG onVideoEvent $event; callId == null; event.start: ${event.start}, event.started: ${event.started}") + if (event.start) { + view.displayLocalVideo(true) } - } else if (event.callId == null) { - Log.w(TAG, "DEBUG fn onVideoEvent |3| inside => else if (event.callId == null)") if (event.started) { previewWidth = event.w previewHeight = event.h view.resetPreviewVideoSize(previewWidth, previewHeight, event.rot) } + } else if (conference != null && conference.id == event.callId) { + Log.w(TAG, "DEBUG onVideoEvent $event; onference != null && conference.id: ${conference.id} == event.callId: ${event.callId}; event.start: ${event.start}, event.started: ${event.started}") + if (event.start) { + view.displayPeerVideo(true) + } else if (event.started) { + videoWidth = event.w + videoHeight = event.h + view.resetVideoSize(videoWidth, videoHeight) + } else { + view.displayPeerVideo(false) + } } - if (conference != null && conference.pluginId == event.callId) { + /*if (conference != null && conference.pluginId == event.callId) { Log.w(TAG, "DEBUG fn onVideoEvent |4| inside => if (mConference != null && mConference!!.pluginId == event.callId)") if (event.started) { previewWidth = event.w previewHeight = event.h view.resetPluginPreviewVideoSize(previewWidth, previewHeight, event.rot) } - } - /*if (event.started || event.start) { - getView().resetVideoSize(videoWidth, videoHeight, previewWidth, previewHeight); }*/ } @@ -502,16 +504,16 @@ class CallPresenter @Inject constructor( } fun pipModeChanged(pip: Boolean) { + Log.w(TAG, "DEBUG fn pipModeChanged $pip") isPipMode = pip if (pip) { - Log.w(TAG, "DEBUG fn pipModeChanged |1| entering pipMode -> hangupButton : false; previewSurface: false; displayVideoSurface(true, false)") view!!.displayHangupButton(false) view!!.displayPreviewSurface(false) - view!!.displayVideoSurface(true, false) + //view!!.displayPeerVideo(true, false) } else { - Log.w(TAG, "DEBUG fn pipModeChanged |2| entering pipMode -> previewSurface: true; displayVideoSurface(true, mDeviceRuntimeService.hasVideoPermission() && hasVideo && !videoIsMuted)") + //Log.w(TAG, "DEBUG fn pipModeChanged |2| entering pipMode -> previewSurface: true; displayVideoSurface(true, mDeviceRuntimeService.hasVideoPermission() && hasVideo && !videoIsMuted)") view!!.displayPreviewSurface(true) - view!!.displayVideoSurface(true, mDeviceRuntimeService.hasVideoPermission()) + //view!!.displayPeerVideo(true, mDeviceRuntimeService.hasVideoPermission()) } } diff --git a/ring-android/libjamiclient/src/main/kotlin/net/jami/call/CallView.kt b/ring-android/libjamiclient/src/main/kotlin/net/jami/call/CallView.kt index 0f3905884..78c0921b4 100644 --- a/ring-android/libjamiclient/src/main/kotlin/net/jami/call/CallView.kt +++ b/ring-android/libjamiclient/src/main/kotlin/net/jami/call/CallView.kt @@ -27,7 +27,8 @@ import net.jami.services.HardwareService.AudioState interface CallView { fun displayContactBubble(display: Boolean) - fun displayVideoSurface(displayVideoSurface: Boolean, displayPreviewContainer: Boolean) + fun displayPeerVideo(display: Boolean) + fun displayLocalVideo(display: Boolean) fun displayPreviewSurface(display: Boolean) fun displayHangupButton(display: Boolean) fun displayDialPadKeyboard() @@ -37,7 +38,7 @@ interface CallView { fun updateTime(duration: Long) fun updateCallStatus(callState: CallStatus) fun initMenu(isSpeakerOn: Boolean, hasMultipleCamera: Boolean, canDial: Boolean, showPluginBtn: Boolean, onGoingCall: Boolean, hasActiveVideo: Boolean) - fun initNormalStateDisplay(audioOnly: Boolean, muted: Boolean) + fun initNormalStateDisplay(muted: Boolean) fun initIncomingCallDisplay(hasVideo: Boolean) fun initOutGoingCallDisplay() fun resetPreviewVideoSize(previewWidth: Int, previewHeight: Int, rot: Int) diff --git a/ring-android/libjamiclient/src/main/kotlin/net/jami/services/HardwareService.kt b/ring-android/libjamiclient/src/main/kotlin/net/jami/services/HardwareService.kt index 7345ec96f..8fd4043cc 100644 --- a/ring-android/libjamiclient/src/main/kotlin/net/jami/services/HardwareService.kt +++ b/ring-android/libjamiclient/src/main/kotlin/net/jami/services/HardwareService.kt @@ -43,14 +43,14 @@ abstract class HardwareService( val mPreferenceService: PreferencesService, protected val mUiScheduler: Scheduler ) { - class VideoEvent { - var start = false - var started = false - var w = 0 - var h = 0 - var rot = 0 - var callId: String? = null - } + data class VideoEvent ( + val callId: String? = null, + val start: Boolean = false, + val started: Boolean = false, + val w: Int = 0, + val h: Int = 0, + val rot: Int = 0 + ) class BluetoothEvent (val connected: Boolean) @@ -90,6 +90,7 @@ abstract class HardwareService( abstract fun abandonAudioFocus() abstract fun decodingStarted(id: String, shmPath: String, width: Int, height: Int, isMixer: Boolean) abstract fun decodingStopped(id: String, shmPath: String, isMixer: Boolean) + abstract fun hasInput(id: String): Boolean abstract fun getCameraInfo(camId: String, formats: IntVect, sizes: UintVect, rates: UintVect) abstract fun setParameters(camId: String, format: Int, width: Int, height: Int, rate: Int) abstract fun startCapture(camId: String?) -- GitLab