From 5a0bab1d6e65eeae85bfb57a5c15c01471f278ea Mon Sep 17 00:00:00 2001 From: Haroon Amjad <> Date: Mon, 5 Oct 2026 17:04:47 +0300 Subject: [PATCH] Update OpenTok SDK version and refactor video call handling --- android/app/build.gradle | 2 +- .../main/kotlin/com/hmg/hmgDr/MainActivity.kt | 191 +- .../Service/VideoStreamContainerService.kt | 182 +- .../VideoStreamFloatingWidgetService.kt | 2124 +++++++-------- .../hmgDr/ui/fragment/VideoCallFragment.kt | 2346 ++++++++--------- .../util/opentok/DynamicVideoRenderer.kt | 758 +++--- .../opentok/ThumbnailCircleVideoRenderer.kt | 714 ++--- lib/config/config.dart | 4 +- .../viewModel/PatientSearchViewModel.dart | 2 +- .../In_patient/list_of_my_inpatient.dart | 6 +- lib/widgets/auth/sms-popup.dart | 77 +- 11 files changed, 3209 insertions(+), 3197 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 209e35c7..f52eb79a 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -129,7 +129,7 @@ dependencies { //openTok - implementation 'com.opentok.android:opentok-android-sdk:2.20.1' + implementation 'com.opentok.android:opentok-android-sdk:2.35.1' //permissions // implementation 'pub.devrel:easypermissions:0.4.0' // implementation project(':easypermissions') diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/MainActivity.kt b/android/app/src/main/kotlin/com/hmg/hmgDr/MainActivity.kt index 7f9d2a42..ffd72c4b 100644 --- a/android/app/src/main/kotlin/com/hmg/hmgDr/MainActivity.kt +++ b/android/app/src/main/kotlin/com/hmg/hmgDr/MainActivity.kt @@ -16,7 +16,7 @@ import android.util.Log import android.widget.Toast import androidx.annotation.NonNull import com.google.gson.GsonBuilder -import com.hmg.hmgDr.Service.VideoStreamFloatingWidgetService +//import com.hmg.hmgDr.Service.VideoStreamFloatingWidgetService import com.hmg.hmgDr.Model.GetSessionStatusModel import com.hmg.hmgDr.Model.SessionStatusModel import com.hmg.hmgDr.ui.VideoCallResponseListener @@ -43,7 +43,7 @@ class MainActivity : FlutterFragmentActivity(), MethodChannel.MethodCallHandler, private val LAUNCH_VIDEO: Int = 1 private var serviceIntent: Intent? = null - private var videoStreamService: VideoStreamFloatingWidgetService? = null +// private var videoStreamService: VideoStreamFloatingWidgetService? = null private var bound = false override fun onCreate(savedInstanceState: Bundle?) { @@ -59,46 +59,46 @@ class MainActivity : FlutterFragmentActivity(), MethodChannel.MethodCallHandler, override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { - this.result = result - this.call = call - - when (call.method) { - "openVideoCall" -> { - val apiKey = call.argument("kApiKey") - val sessionId = call.argument("kSessionId") - val token = call.argument("kToken") - val appLang = call.argument("appLang") - val baseUrl = call.argument("baseUrl") - - // Session Status model - val VC_ID = call.argument("VC_ID") - val tokenID = call.argument("TokenID") - val generalId = call.argument("generalId") - val doctorId = call.argument("DoctorId") - val patientName = call.argument("patientName") - val isRecording = call.argument("isRecording") - - val sessionStatusModel = - GetSessionStatusModel( - VC_ID, - tokenID, - generalId, - doctorId, - patientName, - isRecording!! - ) - - - openVideoCall(apiKey, sessionId, token, appLang, baseUrl, sessionStatusModel) - - } - "closeVideoCall" -> { - videoStreamService?.closeVideoCall() - } - else -> { - result.notImplemented() - } - } +// this.result = result +// this.call = call +// +// when (call.method) { +// "openVideoCall" -> { +// val apiKey = call.argument("kApiKey") +// val sessionId = call.argument("kSessionId") +// val token = call.argument("kToken") +// val appLang = call.argument("appLang") +// val baseUrl = call.argument("baseUrl") +// +// // Session Status model +// val VC_ID = call.argument("VC_ID") +// val tokenID = call.argument("TokenID") +// val generalId = call.argument("generalId") +// val doctorId = call.argument("DoctorId") +// val patientName = call.argument("patientName") +// val isRecording = call.argument("isRecording") +// +// val sessionStatusModel = +// GetSessionStatusModel( +// VC_ID, +// tokenID, +// generalId, +// doctorId, +// patientName, +// isRecording!! +// ) +// +// +// openVideoCall(apiKey, sessionId, token, appLang, baseUrl, sessionStatusModel) +// +// } +// "closeVideoCall" -> { +// videoStreamService?.closeVideoCall() +// } +// else -> { +// result.notImplemented() +// } +// } } private fun openVideoCall( @@ -110,24 +110,24 @@ class MainActivity : FlutterFragmentActivity(), MethodChannel.MethodCallHandler, sessionStatusModel: GetSessionStatusModel ) { - val arguments = Bundle() - arguments.putString("apiKey", apiKey) - arguments.putString("sessionId", sessionId) - arguments.putString("token", token) - arguments.putString("appLang", appLang) - arguments.putString("baseUrl", baseUrl) - arguments.putParcelable("sessionStatusModel", sessionStatusModel) - - // start service -// serviceIntent = Intent(this@MainActivity, VideoStreamContainerService::class.java) - if (videoStreamService == null || videoStreamService?.serviceRunning == false) { - serviceIntent = Intent(this@MainActivity, VideoStreamFloatingWidgetService::class.java) - serviceIntent?.run { - putExtras(arguments) - action = VideoStreamFloatingWidgetService.ACTION_START_CALL - } - checkFloatingWidgetPermission() - } +// val arguments = Bundle() +// arguments.putString("apiKey", apiKey) +// arguments.putString("sessionId", sessionId) +// arguments.putString("token", token) +// arguments.putString("appLang", appLang) +// arguments.putString("baseUrl", baseUrl) +// arguments.putParcelable("sessionStatusModel", sessionStatusModel) +// +// // start service +//// serviceIntent = Intent(this@MainActivity, VideoStreamContainerService::class.java) +// if (videoStreamService == null || videoStreamService?.serviceRunning == false) { +// serviceIntent = Intent(this@MainActivity, VideoStreamFloatingWidgetService::class.java) +// serviceIntent?.run { +// putExtras(arguments) +// action = VideoStreamFloatingWidgetService.ACTION_START_CALL +// } +// checkFloatingWidgetPermission() +// } } private fun checkFloatingWidgetPermission() { @@ -212,28 +212,29 @@ class MainActivity : FlutterFragmentActivity(), MethodChannel.MethodCallHandler, } override fun minimizeVideoEvent(isMinimize: Boolean) { - if (isMinimize) - methodChannel.invokeMethod("onCallConnected", null) - else { - methodChannel.invokeMethod("onCallDisconnected", null) - unbindService() - videoStreamService?.serviceRunning = false - videoStreamService = null - } +// if (isMinimize) +// methodChannel.invokeMethod("onCallConnected", null) +// else { +// methodChannel.invokeMethod("onCallDisconnected", null) +// unbindService() +// videoStreamService?.serviceRunning = false +// videoStreamService = null +// } } override fun onBackPressed() { - if (videoStreamService != null && videoStreamService?.serviceRunning == true && videoStreamService?.isFullScreen!!) { - videoStreamService!!.onMinimizedClicked() - } else { - super.onBackPressed() - } + super.onBackPressed() + +// if (videoStreamService != null && videoStreamService?.serviceRunning == true && videoStreamService?.isFullScreen!!) { +// videoStreamService!!.onMinimizedClicked() +// } else { +// } } override fun onPause() { - if (videoStreamService != null && videoStreamService?.serviceRunning == true && videoStreamService?.isFullScreen!!) { - videoStreamService!!.onMinimizedClicked() - } +// if (videoStreamService != null && videoStreamService?.serviceRunning == true && videoStreamService?.isFullScreen!!) { +// videoStreamService!!.onMinimizedClicked() +// } super.onPause() } @@ -248,32 +249,32 @@ class MainActivity : FlutterFragmentActivity(), MethodChannel.MethodCallHandler, // } private fun bindService() { - serviceIntent?.run { - if (videoStreamService != null && !videoStreamService!!.serviceRunning) { - startService(this) - } - bindService(this, serviceConnection, Context.BIND_AUTO_CREATE) - } +// serviceIntent?.run { +// if (videoStreamService != null && !videoStreamService!!.serviceRunning) { +// startService(this) +// } +// bindService(this, serviceConnection, Context.BIND_AUTO_CREATE) +// } } private fun unbindService() { - if (bound) { - videoStreamService?.videoCallResponseListener = null // unregister - unbindService(serviceConnection) - bound = false - } +// if (bound) { +// videoStreamService?.videoCallResponseListener = null // unregister +// unbindService(serviceConnection) +// bound = false +// } } private val serviceConnection: ServiceConnection = object : ServiceConnection { override fun onServiceConnected(name: ComponentName?, service: IBinder?) { -// val binder: VideoStreamContainerService.VideoStreamBinder = -// service as VideoStreamContainerService.VideoStreamBinder - val binder: VideoStreamFloatingWidgetService.VideoStreamBinder = - service as VideoStreamFloatingWidgetService.VideoStreamBinder - videoStreamService = binder.service - bound = true - videoStreamService!!.videoCallResponseListener = this@MainActivity // register - videoStreamService?.serviceRunning = true +//// val binder: VideoStreamContainerService.VideoStreamBinder = +//// service as VideoStreamContainerService.VideoStreamBinder +// val binder: VideoStreamFloatingWidgetService.VideoStreamBinder = +// service as VideoStreamFloatingWidgetService.VideoStreamBinder +// videoStreamService = binder.service +// bound = true +// videoStreamService!!.videoCallResponseListener = this@MainActivity // register +// videoStreamService?.serviceRunning = true } override fun onServiceDisconnected(name: ComponentName?) { diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/Service/VideoStreamContainerService.kt b/android/app/src/main/kotlin/com/hmg/hmgDr/Service/VideoStreamContainerService.kt index add401ff..9da19a7a 100644 --- a/android/app/src/main/kotlin/com/hmg/hmgDr/Service/VideoStreamContainerService.kt +++ b/android/app/src/main/kotlin/com/hmg/hmgDr/Service/VideoStreamContainerService.kt @@ -1,91 +1,91 @@ -package com.hmg.hmgDr.Service - -import android.app.Service -import android.content.Intent -import android.os.Binder -import android.os.Bundle -import android.os.IBinder -import com.hmg.hmgDr.MainActivity -import com.hmg.hmgDr.ui.VideoCallResponseListener -import com.hmg.hmgDr.ui.fragment.VideoCallFragment - -class VideoStreamContainerService : Service(), VideoCallResponseListener { - - var videoCallResponseListener: VideoCallResponseListener? = null - var mActivity: MainActivity? = null - set(value) { - field = value - if (field != null) { - setDialogFragment() - } - } - var arguments: Bundle? = null - var serviceRunning: Boolean = false - - - private val serviceBinder: IBinder = VideoStreamBinder() - private var dialogFragment: VideoCallFragment? = null - - override fun onBind(intent: Intent?): IBinder { - return serviceBinder - } - - private fun setDialogFragment() { - mActivity?.run { - if (dialogFragment == null) { - val transaction = supportFragmentManager.beginTransaction() - dialogFragment = VideoCallFragment.newInstance(arguments!!) - dialogFragment?.let { - it.setCallListener(this@VideoStreamContainerService) - it.isCancelable = true - if (it.isAdded) { - it.dismiss() - } else { - it.show(transaction, "dialog") - } - } - } else if (!dialogFragment!!.isVisible) { - val transaction = supportFragmentManager.beginTransaction() - dialogFragment!!.show(transaction, "dialog") - } else { - // don't do anything - } - } - } - - fun closeVideoCall(){ - dialogFragment?.onCallClicked() - } - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - if (intent != null && intent.extras != null) { - arguments = intent.extras - } -// Toast.makeText(this, "Service started by user.", Toast.LENGTH_LONG).show() - return START_STICKY - } - - override fun onDestroy() { - super.onDestroy() -// Toast.makeText(this, "Service destroyed by user.", Toast.LENGTH_LONG).show() - } - - inner class VideoStreamBinder : Binder() { - val service: VideoStreamContainerService - get() = this@VideoStreamContainerService - } - - override fun onCallFinished(resultCode: Int, intent: Intent?) { - dialogFragment = null - videoCallResponseListener?.onCallFinished(resultCode, intent) - } - - override fun errorHandle(message: String) { - dialogFragment = null -// Toast.makeText(this, message, Toast.LENGTH_LONG).show() - } - - override fun minimizeVideoEvent(isMinimize: Boolean) { - videoCallResponseListener?.minimizeVideoEvent(isMinimize) - } -} \ No newline at end of file +//package com.hmg.hmgDr.Service +// +//import android.app.Service +//import android.content.Intent +//import android.os.Binder +//import android.os.Bundle +//import android.os.IBinder +//import com.hmg.hmgDr.MainActivity +////import com.hmg.hmgDr.ui.VideoCallResponseListener +////import com.hmg.hmgDr.ui.fragment.VideoCallFragment +// +//class VideoStreamContainerService : Service(), VideoCallResponseListener { +// +//// var videoCallResponseListener: VideoCallResponseListener? = null +//// var mActivity: MainActivity? = null +//// set(value) { +//// field = value +//// if (field != null) { +//// setDialogFragment() +//// } +//// } +//// var arguments: Bundle? = null +//// var serviceRunning: Boolean = false +//// +//// +//// private val serviceBinder: IBinder = VideoStreamBinder() +//// private var dialogFragment: VideoCallFragment? = null +//// +//// override fun onBind(intent: Intent?): IBinder { +//// return serviceBinder +//// } +//// +//// private fun setDialogFragment() { +//// mActivity?.run { +//// if (dialogFragment == null) { +//// val transaction = supportFragmentManager.beginTransaction() +//// dialogFragment = VideoCallFragment.newInstance(arguments!!) +//// dialogFragment?.let { +//// it.setCallListener(this@VideoStreamContainerService) +//// it.isCancelable = true +//// if (it.isAdded) { +//// it.dismiss() +//// } else { +//// it.show(transaction, "dialog") +//// } +//// } +//// } else if (!dialogFragment!!.isVisible) { +//// val transaction = supportFragmentManager.beginTransaction() +//// dialogFragment!!.show(transaction, "dialog") +//// } else { +//// // don't do anything +//// } +//// } +//// } +//// +//// fun closeVideoCall(){ +//// dialogFragment?.onCallClicked() +//// } +//// +//// override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { +//// if (intent != null && intent.extras != null) { +//// arguments = intent.extras +//// } +////// Toast.makeText(this, "Service started by user.", Toast.LENGTH_LONG).show() +//// return START_STICKY +//// } +//// +//// override fun onDestroy() { +//// super.onDestroy() +////// Toast.makeText(this, "Service destroyed by user.", Toast.LENGTH_LONG).show() +//// } +//// +//// inner class VideoStreamBinder : Binder() { +//// val service: VideoStreamContainerService +//// get() = this@VideoStreamContainerService +//// } +//// +//// override fun onCallFinished(resultCode: Int, intent: Intent?) { +//// dialogFragment = null +//// videoCallResponseListener?.onCallFinished(resultCode, intent) +//// } +//// +//// override fun errorHandle(message: String) { +//// dialogFragment = null +////// Toast.makeText(this, message, Toast.LENGTH_LONG).show() +//// } +//// +//// override fun minimizeVideoEvent(isMinimize: Boolean) { +//// videoCallResponseListener?.minimizeVideoEvent(isMinimize) +//// } +//} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/Service/VideoStreamFloatingWidgetService.kt b/android/app/src/main/kotlin/com/hmg/hmgDr/Service/VideoStreamFloatingWidgetService.kt index 8ece1bd5..ab74cd1c 100644 --- a/android/app/src/main/kotlin/com/hmg/hmgDr/Service/VideoStreamFloatingWidgetService.kt +++ b/android/app/src/main/kotlin/com/hmg/hmgDr/Service/VideoStreamFloatingWidgetService.kt @@ -1,1062 +1,1062 @@ -package com.hmg.hmgDr.Service - -import android.annotation.SuppressLint -import android.app.* -import android.content.Intent -import android.graphics.BitmapFactory -import android.opengl.GLSurfaceView -import android.os.* -import android.util.Log -import android.view.* -import android.widget.* -import androidx.constraintlayout.widget.ConstraintLayout -import androidx.core.app.NotificationCompat -import androidx.core.app.NotificationManagerCompat -import androidx.core.content.ContextCompat -import androidx.core.view.GestureDetectorCompat -import com.hmg.hmgDr.Model.ChangeCallStatusRequestModel -import com.hmg.hmgDr.Model.GetSessionStatusModel -import com.hmg.hmgDr.Model.SessionStatusModel -import com.hmg.hmgDr.R -import com.hmg.hmgDr.Model.* -import com.hmg.hmgDr.ui.VideoCallContract -import com.hmg.hmgDr.ui.VideoCallPresenterImpl -import com.hmg.hmgDr.ui.VideoCallResponseListener -import com.hmg.hmgDr.util.DateUtils -import com.hmg.hmgDr.util.opentok.DynamicVideoRenderer -import com.hmg.hmgDr.util.NotificationUtil -import com.hmg.hmgDr.util.ViewsUtil -import com.hmg.hmgDr.util.audio.CustomAudioDevice -import com.opentok.android.* -import java.util.* - - -class VideoStreamFloatingWidgetService : BaseMovingFloatingWidget(), Session.SessionListener, - PublisherKit.PublisherListener, - SubscriberKit.VideoListener, VideoCallContract.VideoCallView { - - companion object { - @JvmStatic - - private val TAG = VideoStreamFloatingWidgetService::class.java.simpleName - - const val CHANNEL_DEFAULT_IMPORTANCE = "Video_stream_channel" - const val CHANNEL_DEFAULT_NAME = "Video cAll" - const val ONGOING_NOTIFICATION_ID = 1 - - const val ACTION_START_CALL = "com.hmg.hmgDr.Service.action.startCall" - const val ACTION_MINIMIZE_CALL = "com.hmg.hmgDr.Service.action.minimizeCall" - const val ACTION_END_CALL = "com.hmg.hmgDr.Service.action.endCall" - const val ACTION_CHANGE_EXPANDED_COLLAPSED = - "com.hmg.hmgDr.Service.action.changeExpandedCollapsed" - const val NOTIFICATION_IS_EXPANDED = "is_expanded" - } - - var arguments: Bundle? = null - var serviceRunning: Boolean = false - - private val serviceBinder: IBinder = VideoStreamBinder() - private lateinit var videoCallPresenter: VideoCallContract.VideoCallPresenter - var videoCallResponseListener: VideoCallResponseListener? = null - - private lateinit var recordContainer: FrameLayout - private lateinit var thumbnail_container: FrameLayout - private lateinit var activity_clingo_video_call: RelativeLayout - private lateinit var mPublisherViewContainer: FrameLayout - private lateinit var mPublisherViewIcon: View - private lateinit var mSubscriberViewContainer: FrameLayout - private lateinit var mSubscriberViewIcon: ImageView - private lateinit var controlPanel: ConstraintLayout - - private lateinit var parentView: View - private lateinit var videoCallContainer: ConstraintLayout - private lateinit var layoutName: RelativeLayout - private lateinit var layoutMini: RelativeLayout - private lateinit var icMini: ImageButton - private lateinit var mCallBtn: ImageView - private lateinit var btnMinimize: ImageView - private lateinit var mCameraBtn: ImageView - private lateinit var mSwitchCameraBtn: ImageView - private lateinit var mspeckerBtn: ImageView - private lateinit var mMicBtn: ImageView - private lateinit var patientName: TextView - private lateinit var tvTimer: TextView -// private lateinit var cmTimer: Chronometer - - private var mSession: Session? = null - private var mPublisher: Publisher? = null - private var mSubscriber: Subscriber? = null - - private var mVolHandler: Handler? = null - private var mConnectedHandler: Handler? = null - private var mVolRunnable: Runnable? = null - private var mConnectedRunnable: Runnable? = null - private var isConnected = false - - private var mCallTimerHandler: Handler? = null - private var mCallTimerRunnable: Runnable? = null - private var mCallFirstTime: Date = Date() - - private var sessionStatusModel: GetSessionStatusModel? = null - - private var apiKey: String? = null - private var sessionId: String? = null - private var token: String? = null - private var appLang: String? = null - private var baseUrl: String? = null - private var isRecording: Boolean = true - - private var isSwitchCameraClicked = false - private var isCameraClicked = false - private var isSpeckerClicked = false - private var isMicClicked = false - private var elapsedTime: Long = 0 - private var formattedCallTime: String = "00:00" - private lateinit var notificationData: NotificationVideoModel - - var isFullScreen: Boolean = true - private var isCircle: Boolean = false - lateinit var customAudioDevice: CustomAudioDevice - - // Notification variables - private var mNotificationManagerCompat: NotificationManagerCompat? = null - private lateinit var notificationCompatBuilder: NotificationCompat.Builder - - override fun onBind(intent: Intent?): IBinder { - return serviceBinder - } - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - if (intent != null) { - - val action = intent.action - - if (action == ACTION_START_CALL) { - if (intent.extras != null) { - arguments = intent.extras - arguments?.run { - apiKey = getString("apiKey") - sessionId = getString("sessionId") - token = getString("token") - appLang = getString("appLang") - baseUrl = getString("baseUrl") - sessionStatusModel = getParcelable("sessionStatusModel") - if (sessionStatusModel != null) - isRecording = sessionStatusModel!!.isRecording - } - - addFloatingWidgetView() - handleDragDialog() - addForegroundService() - } - } else if (action == ACTION_END_CALL) { - closeVideoCall() - } else if (action == ACTION_MINIMIZE_CALL) { - if (!isFullScreen) - onMinimizedClicked() - } else if (action == ACTION_CHANGE_EXPANDED_COLLAPSED) { - val isExpanded = intent.extras!!.getBoolean(NOTIFICATION_IS_EXPANDED) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - // No use channel importance - if (isExpanded) { - notificationCompatBuilder.priority = Notification.PRIORITY_LOW - } else { - notificationCompatBuilder.priority = Notification.PRIORITY_HIGH - } - } else { - if (isExpanded) { - notificationCompatBuilder.priority = Notification.PRIORITY_LOW - } else { - notificationCompatBuilder.priority = Notification.PRIORITY_HIGH - } - } - mNotificationManagerCompat?.notify( - ONGOING_NOTIFICATION_ID, - notificationCompatBuilder.build() - ) - } - - } - return START_STICKY - } - - inner class VideoStreamBinder : Binder() { - val service: VideoStreamFloatingWidgetService - get() = this@VideoStreamFloatingWidgetService - } - - override fun onDestroy() { - try { - mWindowManager?.removeView(floatingWidgetView) - floatingWidgetView = null - mSession = null - mWindowManager = null - - } catch (e: Exception) { - Log.e("onDestroyService", "${e.localizedMessage}.") - } - super.onDestroy() - } - - private fun stopService() { - AudioDeviceManager.getAudioDevice().onPause() - - mCallTimerRunnable?.let { - mCallTimerHandler?.removeCallbacks(it) - mCallTimerHandler = null - mCallTimerRunnable = null - } - - // because problem that timer still continue longer a bit than service so notification called again - mNotificationManagerCompat = null - stopForeground(true) - stopSelf() - videoCallResponseListener?.minimizeVideoEvent(false) - try { - mWindowManager?.removeView(floatingWidgetView) - } catch (e: Exception) { - Log.e("stopService", "${e.localizedMessage}.") - } - } - - override fun addFloatingWidgetView() { - super.addFloatingWidgetView() - - init(floatingWidgetView!!) - - //Add the view to the window - mWindowManager?.addView(floatingWidgetView, windowManagerParams) - } - - @SuppressLint("ClickableViewAccessibility", "RestrictedApi") - private fun init(view: View) { - initUI(view) - - patientName.text = sessionStatusModel!!.patientName - - if (isRecording) { - recordContainer.visibility = View.VISIBLE - } else { - recordContainer.visibility = View.GONE - } - - videoCallPresenter = VideoCallPresenterImpl(this, baseUrl) - - checkClientConnected() - setCallStartTimer() - handleVideoViewHeight() - - mDetector = GestureDetectorCompat( - this, - MyGestureListener( - { showControlPanelTemporarily() }, - { miniCircleDoubleTap() }) - ) - try { - // Add a custom audio device before session initialization, - // so when the service is destroyed it will not be errors that receivers is still in memory - customAudioDevice = CustomAudioDevice(this) - customAudioDevice.setRendererMute(false) - if (AudioDeviceManager.getAudioDevice() == null) { - AudioDeviceManager.setAudioDevice(customAudioDevice) - } else { - AudioDeviceManager.getAudioDevice().onResume() - } - - mSession = Session.Builder(this, apiKey, sessionId).build() - mSession!!.setSessionListener(this) - mSession!!.connect(token) - mSession!!.setReconnectionListener(object : Session.ReconnectionListener { - override fun onReconnecting(session: Session?) { - - } - - override fun onReconnected(session: Session?) { - session?.connect(token) - session?.onResume() - } - }) - } catch (e: Exception) { - e.printStackTrace() - } - } - - private fun initUI(view: View) { - videoCallContainer = view.findViewById(R.id.video_call_ll) - floatingViewContainer = videoCallContainer - - layoutName = view.findViewById(R.id.layout_name) as RelativeLayout - layoutMini = view.findViewById(R.id.layout_mini) - icMini = view.findViewById(R.id.ic_mini) - recordContainer = view.findViewById(R.id.record_container) - activity_clingo_video_call = view.findViewById(R.id.activity_clingo_video_call) - - thumbnail_container = view.findViewById(R.id.thumbnail_container) - mPublisherViewContainer = view.findViewById(R.id.local_video_view_container) - mPublisherViewIcon = view.findViewById(R.id.local_video_view_icon) - mSubscriberViewIcon = view.findViewById(R.id.remote_video_view_icon) - mSubscriberViewContainer = view.findViewById(R.id.remote_video_view_container) - - patientName = view.findViewById(R.id.patient_name) - tvTimer = view.findViewById(R.id.tv_timer) - - controlPanel = view.findViewById(R.id.control_panel) - mCallBtn = view.findViewById(R.id.btn_call) - btnMinimize = view.findViewById(R.id.btn_minimize) - mCameraBtn = view.findViewById(R.id.btn_camera) - mSwitchCameraBtn = view.findViewById(R.id.btn_switch_camera) - mspeckerBtn = view.findViewById(R.id.btn_specker) - mMicBtn = view.findViewById(R.id.btn_mic) - - mCallBtn.setOnClickListener { - onCallClicked() - } - btnMinimize.setOnClickListener { - onMinimizedClicked() - } - mCameraBtn.setOnClickListener { - onCameraClicked(it) - } - mSwitchCameraBtn.setOnClickListener { - onSwitchCameraClicked(it) - } - mspeckerBtn.setOnClickListener { - onSpeckerClicked(it) - } - mMicBtn.setOnClickListener { - onMicClicked(it) - } - icMini.setOnClickListener { - onMiniCircleClicked() - } - } - - private fun checkClientConnected() { - mConnectedHandler = Handler((Looper.getMainLooper())) - mConnectedRunnable = Runnable { - if (!isConnected) { - videoCallPresenter.callClintConnected(sessionStatusModel) - } - } - mConnectedHandler!!.postDelayed( - mConnectedRunnable!!, - (55 * 1000).toLong() - ) - } - - private fun setCallStartTimer() { - mCallTimerHandler = Handler((Looper.getMainLooper())) - mCallTimerRunnable = Runnable { - formattedCallTime = DateUtils.differentDateTimeBetweenDateAndNow(mCallFirstTime) - tvTimer.text = formattedCallTime - - // for change notification timer - if (mNotificationManagerCompat != null) { - notificationData.mSummaryText = formattedCallTime - val bigTextStyle = NotificationUtil.setNotificationBigStyle(notificationData) - notificationCompatBuilder.setStyle(bigTextStyle) - mNotificationManagerCompat?.notify( - ONGOING_NOTIFICATION_ID, - notificationCompatBuilder.build() - ) - } - mCallTimerHandler!!.postDelayed(mCallTimerRunnable!!, 1000L) - } - - } - - private fun handleVideoViewHeight() { - val layoutNameParam: ConstraintLayout.LayoutParams = - layoutName.layoutParams as ConstraintLayout.LayoutParams - val layoutMiniParam: ConstraintLayout.LayoutParams = - layoutMini.layoutParams as ConstraintLayout.LayoutParams - val controlPanelParam: ConstraintLayout.LayoutParams = - controlPanel.layoutParams as ConstraintLayout.LayoutParams - - val layoutNameHeight: Int = - resources.getDimension(R.dimen.layout_name_height).toInt() - val layoutMiniHeight: Int = - resources.getDimension(R.dimen.layout_mini_height).toInt() - val panelHeight: Int = resources.getDimension(R.dimen.layout_panel_height).toInt() - val panelHeightSmall: Int = - resources.getDimension(R.dimen.layout_panel_height_small).toInt() - - val panelPadding: Int = - resources.getDimension(R.dimen.padding_space_big).toInt() - val panelPaddingMedium: Int = - resources.getDimension(R.dimen.padding_space_medium).toInt() - - val temp = ViewsUtil.getStatusBarHeight(applicationContext) / 2 - - val screenWidth: Float - val screenHeight: Float - - if (isFullScreen) { - screenWidth = ViewsUtil.getWidthDp(this) - screenHeight = ViewsUtil.getHeightDp(this) - - layoutNameParam.height = layoutNameHeight + temp - layoutMiniParam.height = 0 - controlPanelParam.height = panelHeight + temp - - controlPanel.setPadding(panelPadding, panelPadding, panelPadding, panelPadding) - } else { - - if (isCircle) { - screenWidth = 300F - screenHeight = 300F - - layoutNameParam.height = 0 - layoutMiniParam.height = 0 - controlPanelParam.height = 0 - } else { - screenWidth = 400F - screenHeight = 600F - - layoutNameParam.height = 0 - layoutMiniParam.height = layoutMiniHeight - controlPanelParam.height = panelHeightSmall - } - - controlPanel.setPadding( - panelPaddingMedium, - panelPaddingMedium, - panelPaddingMedium, - panelPaddingMedium - ) - } - - layoutName.layoutParams = layoutNameParam - layoutMini.layoutParams = layoutMiniParam - controlPanel.layoutParams = controlPanelParam - - var videoStreamHeight = - screenHeight - controlPanelParam.height - layoutNameParam.height - layoutMiniParam.height - - if (isFullScreen) { -// videoStreamHeight -= getStatusBarHeight() / 2 - } - - val callLayoutParam: ConstraintLayout.LayoutParams = - activity_clingo_video_call.layoutParams as ConstraintLayout.LayoutParams - - callLayoutParam.height = videoStreamHeight.toInt() - callLayoutParam.width = screenWidth.toInt() - } - - private fun setViewsVisibility() { - val btnMinimizeLayoutParam: ConstraintLayout.LayoutParams = - btnMinimize.layoutParams as ConstraintLayout.LayoutParams - val mCallBtnLayoutParam: ConstraintLayout.LayoutParams = - mCallBtn.layoutParams as ConstraintLayout.LayoutParams - - val iconSize: Int = resources.getDimension(R.dimen.video_icon_size).toInt() - val iconSizeSmall: Int = - resources.getDimension(R.dimen.video_icon_size_small).toInt() - - val localPreviewMargin: Int = - resources.getDimension(R.dimen.local_preview_margin_top).toInt() - val localPreviewWidth: Int = - resources.getDimension(R.dimen.local_preview_width).toInt() - val localPreviewHeight: Int = - resources.getDimension(R.dimen.local_preview_height).toInt() - val localPreviewLayoutParam: RelativeLayout.LayoutParams = - mPublisherViewContainer.layoutParams as RelativeLayout.LayoutParams - - val remotePreviewIconSize: Int = - resources.getDimension(R.dimen.remote_back_icon_size).toInt() - val remotePreviewIconSizeSmall: Int = - resources.getDimension(R.dimen.remote_back_icon_size_small).toInt() - val remotePreviewLayoutParam: FrameLayout.LayoutParams = - mSubscriberViewIcon.layoutParams as FrameLayout.LayoutParams - - if (isFullScreen) { - layoutName.visibility = View.VISIBLE - layoutMini.visibility = View.GONE - mCameraBtn.visibility = View.VISIBLE - mSwitchCameraBtn.visibility = View.VISIBLE -// mspeckerBtn.visibility = View.VISIBLE - mMicBtn.visibility = View.VISIBLE - - btnMinimizeLayoutParam.width = iconSize - btnMinimizeLayoutParam.height = iconSize - mCallBtnLayoutParam.width = iconSize - mCallBtnLayoutParam.height = iconSize -// localPreviewLayoutIconParam = FrameLayout.LayoutParams(localPreviewIconSize, localPreviewIconSize) -//// localPreviewLayoutParam = RelativeLayout.LayoutParams(localPreviewWidth, localPreviewHeight) - localPreviewLayoutParam.width = localPreviewWidth - localPreviewLayoutParam.height = localPreviewHeight - localPreviewLayoutParam.setMargins(0, localPreviewMargin, localPreviewMargin, 0) - if (mPublisher != null && mPublisher!!.view.parent == null) { - mPublisherViewContainer.addView(mPublisher!!.view) - } - mPublisherViewContainer.visibility = View.VISIBLE - -// remotePreviewLayoutParam = FrameLayout.LayoutParams(remotePreviewIconSize, remotePreviewIconSize) - remotePreviewLayoutParam.width = remotePreviewIconSize - remotePreviewLayoutParam.height = remotePreviewIconSize - } else { - layoutName.visibility = View.GONE - layoutMini.visibility = View.VISIBLE - mCameraBtn.visibility = View.GONE - mSwitchCameraBtn.visibility = View.GONE -// mspeckerBtn.visibility = View.GONE - mMicBtn.visibility = View.GONE -// mPublisherViewContainer.visibility = View.GONE -// mPublisherViewIcon.visibility = View.GONE - -// layoutParam = ConstraintLayout.LayoutParams(iconSizeSmall, iconSizeSmall) - btnMinimizeLayoutParam.width = iconSizeSmall - btnMinimizeLayoutParam.height = iconSizeSmall - mCallBtnLayoutParam.width = iconSizeSmall - mCallBtnLayoutParam.height = iconSizeSmall - - localPreviewLayoutParam.width = 0 - localPreviewLayoutParam.height = 0 - localPreviewLayoutParam.setMargins(0, localPreviewMargin / 2, localPreviewMargin / 2, 0) - - if (mPublisher != null) { - mPublisherViewContainer.removeView(mPublisher!!.view) - } - mPublisherViewContainer.visibility = View.GONE -// localPreviewLayoutIconParam = FrameLayout.LayoutParams(localPreviewIconSmall, localPreviewIconSmall) -//// localPreviewLayoutParam = RelativeLayout.LayoutParams(localPreviewWidthSmall, localPreviewHeightSmall) -// localPreviewLayoutParam.width = localPreviewWidthSmall -// localPreviewLayoutParam.height = localPreviewWidthSmall -// localPreviewLayoutParam.setMargins(0,localPreviewMarginSmall, localPreviewMarginSmall, 0) -// remotePreviewLayoutParam = FrameLayout.LayoutParams(remotePreviewIconSizeSmall, remotePreviewIconSizeSmall) - remotePreviewLayoutParam.width = remotePreviewIconSizeSmall - remotePreviewLayoutParam.height = remotePreviewIconSizeSmall - - if (isCircle) { - controlPanel.visibility = View.GONE - layoutMini.visibility = View.GONE - } else { - controlPanel.visibility = View.VISIBLE - layoutMini.visibility = View.VISIBLE - } - } - - mPublisherViewContainer.layoutParams = localPreviewLayoutParam -// mPublisherViewIcon.layoutParams = localPreviewLayoutIconParam - mSubscriberViewIcon.layoutParams = remotePreviewLayoutParam - - btnMinimize.layoutParams = btnMinimizeLayoutParam - mCallBtn.layoutParams = mCallBtnLayoutParam - - handleVideoViewHeight() - } - - @SuppressLint("ClickableViewAccessibility") - private fun handleDragDialog() { - getWindowManagerDefaultDisplay() - - videoCallContainer.setOnTouchListener(dragListener) - mSubscriberViewContainer.setOnTouchListener(dragListener) - } - - /*** - * Click Listener - */ - - fun onCallClicked() { - disconnectSession() - } - - fun onMinimizedClicked() { - if (isCircle) { - onMiniCircleClicked() - } - if (isFullScreen) { - windowManagerParams.width = 400 - windowManagerParams.height = 600 - - try { - mWindowManager?.updateViewLayout(floatingWidgetView, windowManagerParams) - } catch (e: Exception) { - } - recordContainer.visibility = View.GONE - } else { - windowManagerParams.width = WindowManager.LayoutParams.MATCH_PARENT - windowManagerParams.height = WindowManager.LayoutParams.MATCH_PARENT - - try { - mWindowManager?.updateViewLayout(floatingWidgetView, windowManagerParams) - } catch (e: Exception) { - } - - if (isRecording) { - recordContainer.visibility = View.VISIBLE - } else { - recordContainer.visibility = View.GONE - } - } - isFullScreen = !isFullScreen - - val res = if (isFullScreen) R.drawable.reducing else R.drawable.expand - btnMinimize.setImageResource(res) - setViewsVisibility() - -// videoCallResponseListener?.minimizeVideoEvent(!isFullScreen) - } - - private fun onCameraClicked(view: View?) { - if (mPublisher != null) { - isCameraClicked = !isCameraClicked - mPublisher!!.publishVideo = !isCameraClicked - val res = if (isCameraClicked) R.drawable.video_disabled else R.drawable.video_enabled - mCameraBtn.setImageResource(res) - } - } - - private fun onSwitchCameraClicked(view: View?) { - if (mPublisher != null) { - isSwitchCameraClicked = !isSwitchCameraClicked - mPublisher!!.cycleCamera() - val res = if (isSwitchCameraClicked) R.drawable.camera_front else R.drawable.camera_back - mSwitchCameraBtn.setImageResource(res) - } - } - - private fun onSpeckerClicked(view: View?) { - if (mSubscriber != null) { - isSpeckerClicked = !isSpeckerClicked - mSubscriber!!.subscribeToAudio = !isSpeckerClicked - val res = if (isSpeckerClicked) R.drawable.audio_disabled else R.drawable.audio_enabled - mspeckerBtn.setImageResource(res) - } - } - - private fun onMicClicked(view: View?) { - if (mPublisher != null) { - isMicClicked = !isMicClicked - mPublisher!!.publishAudio = !isMicClicked - val res = if (isMicClicked) R.drawable.mic_disabled else R.drawable.mic_enabled - mMicBtn.setImageResource(res) - } - } - - private fun onMiniCircleClicked() { - if (isCircle) { - windowManagerParams.width = 400 - windowManagerParams.height = 600 - - try { - mWindowManager?.updateViewLayout(floatingWidgetView, windowManagerParams) - } catch (e: Exception) { - } - } else { - windowManagerParams.width = 300 - windowManagerParams.height = 300 - - try { - mWindowManager?.updateViewLayout(floatingWidgetView, windowManagerParams) - } catch (e: Exception) { - } - } - isCircle = !isCircle - - - if (mSubscriber != null) { - (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(isCircle) - } else { - if (isCircle) { - videoCallContainer.background = - ContextCompat.getDrawable(this, R.drawable.circle_shape) - mSubscriberViewContainer.background = - ContextCompat.getDrawable(this, R.drawable.circle_shape) - } else { - videoCallContainer.setBackgroundColor( - ContextCompat.getColor( - this, - R.color.text_color - ) - ) - mSubscriberViewContainer.setBackgroundColor( - ContextCompat.getColor( - this, - R.color.remoteBackground - ) - ) - } - } - - if (isCircle) { - controlPanel.visibility = View.GONE - layoutMini.visibility = View.GONE - } else { - controlPanel.visibility = View.VISIBLE - layoutMini.visibility = View.VISIBLE - } - - handleVideoViewHeight() - } - - private fun showControlPanelTemporarily() { - if (!isCircle) { - controlPanel.visibility = View.VISIBLE - mVolHandler!!.removeCallbacks(mVolRunnable!!) - mVolHandler!!.postDelayed(mVolRunnable!!, (5 * 1000).toLong()) - } - } - - private fun miniCircleDoubleTap() { - if (isCircle) { - onMiniCircleClicked() - } - } - - fun closeVideoCall() { - onCallClicked() - } - - /*** - * Session Listener - */ - - override fun onConnected(session: Session?) { - Log.i(TAG, "Session Connected") - mPublisher = Publisher.Builder(this) -// .name("publisher") -// .renderer(ThumbnailCircleVideoRenderer(requireContext())) - .build() - mPublisher!!.setPublisherListener(this) - mPublisher!!.audioFallbackEnabled = false - if (mPublisher!!.view is GLSurfaceView) { - (mPublisher!!.view as GLSurfaceView).setZOrderOnTop(true) - } - - mPublisherViewContainer.addView(mPublisher!!.view) - - mSession!!.publish(mPublisher) - - // start call timer to show on top - mCallFirstTime = Date() - mCallTimerHandler!!.postDelayed(mCallTimerRunnable!!, 1000L) - - videoCallResponseListener?.minimizeVideoEvent(true) - } - - override fun onDisconnected(session: Session) { - Log.d(TAG, "onDisconnected: disconnected from session " + session.sessionId) -// mSession = null -// cmTimer.stop() -// disconnectSession() -// videoCallResponseListener?.minimizeVideoEvent(false) - } - - override fun onError(session: Session, opentokError: OpentokError) { - Log.d(TAG, "onError: Error (" + opentokError.message + ") in session " + session.sessionId) - } - - override fun onStreamReceived(session: Session, stream: Stream) { - Log.d( - TAG, - "onStreamReceived: New stream " + stream.streamId + " in session " + session.sessionId - ) - - if (mSubscriber != null) { - isConnected = true - return - } - isConnected = true - subscribeToStream(stream) - if (mConnectedHandler != null && mConnectedRunnable != null) - mConnectedHandler!!.removeCallbacks(mConnectedRunnable!!) - videoCallPresenter.callChangeCallStatus( - ChangeCallStatusRequestModel( - 3, - sessionStatusModel!!.doctorId, - sessionStatusModel!!.generalid, - token, - sessionStatusModel!!.vcid - ) - ) - } - - override fun onStreamDropped(session: Session, stream: Stream) { - Log.d( - TAG, - "onStreamDropped: Stream " + stream.streamId + " dropped from session " + session.sessionId - ) - if (mSubscriber == null) { - return - } - if (mSubscriber!!.stream == stream) { - mSubscriberViewContainer.removeView(mSubscriber!!.view) - mSubscriber!!.destroy() - mSubscriber = null - } -// disconnectSession() - } - - private fun disconnectSession() { - if (mSession == null) { - videoCallResponseListener?.onCallFinished(Activity.RESULT_CANCELED) - stopService() - return - } - - if (mSubscriber != null) { - mSubscriberViewContainer.removeView(mSubscriber!!.view) - mSession!!.unsubscribe(mSubscriber) - mSubscriber!!.destroy() - mSubscriber = null - } - if (mPublisher != null) { - mPublisherViewContainer.removeView(mPublisher!!.view) - mSession!!.unpublish(mPublisher) - mPublisher!!.destroy() - mPublisher = null - } - mSession!!.disconnect() - - videoCallPresenter.callChangeCallStatus( - ChangeCallStatusRequestModel( - 16, - sessionStatusModel!!.doctorId, - sessionStatusModel!!.generalid, - token, - sessionStatusModel!!.vcid - ) - ) -// stopService() - onCallChangeCallStatusSuccessful() - } - - private fun subscribeToStream(stream: Stream) { - mSubscriber = Subscriber.Builder(this, stream) - .renderer(DynamicVideoRenderer(this)) - .build() - mSubscriber!!.setVideoListener(this) - mSession!!.subscribe(mSubscriber) - } - - /** - * Publish Listener - */ - - override fun onStreamCreated(publisherKit: PublisherKit?, stream: Stream) { - Log.d(TAG, "onStreamCreated: Own stream " + stream.streamId + " created") - } - - override fun onStreamDestroyed(publisherKit: PublisherKit?, stream: Stream) { - Log.d(TAG, "onStreamDestroyed: Own stream " + stream.streamId + " destroyed") - } - - override fun onError(publisherKit: PublisherKit?, opentokError: OpentokError) { - Log.d(TAG, "onError: Error (" + opentokError.message + ") in publisher") - // videoCallResponseListener?.errorHandle("Error (" + opentokError.message + ") in publisher") -// dialog?.dismiss() - } - - /** - * Video Listener - */ - - override fun onVideoDataReceived(subscriberKit: SubscriberKit?) { - if (mSubscriber == null) { - return - } - mSubscriber!!.setStyle( - BaseVideoRenderer.STYLE_VIDEO_SCALE, - BaseVideoRenderer.STYLE_VIDEO_FILL - ) - (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(false) - mSubscriberViewContainer.addView(mSubscriber!!.view) -// switchToThumbnailCircle() - } - - override fun onVideoDisabled(subscriberKit: SubscriberKit?, s: String?) { - Log.d(TAG, "onVideoDisabled: Error ($s)") - -// if (isCircle) { -// videoCallContainer.background = ContextCompat.getDrawable(requireContext(), R.drawable.circle_shape) -// mSubscriberViewContainer.background = ContextCompat.getDrawable(requireContext(), R.drawable.circle_shape) -// } else { -// videoCallContainer.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.text_color)) -// mSubscriberViewContainer.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.remoteBackground)) -// } - } - - override fun onVideoEnabled(subscriberKit: SubscriberKit?, s: String?) { - Log.d(TAG, "onVideoEnabled: Error ($s)") - -// if (mSubscriber != null) { -// (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(isCircle) -// } - } - - override fun onVideoDisableWarning(subscriberKit: SubscriberKit?) {} - - override fun onVideoDisableWarningLifted(subscriberKit: SubscriberKit?) {} - - private fun switchToThumbnailCircle() { - thumbnail_container.postDelayed({ - val view = mSubscriber!!.view - if (view.parent != null) { - (view.parent as ViewGroup).removeView(view) - } - if (view is GLSurfaceView) { - view.setZOrderOnTop(true) - if (mSubscriber!!.renderer is DynamicVideoRenderer) { - (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(true) - thumbnail_container.addView(view) - } - } - switchToFullScreenView() - }, 4000) - } - - private fun switchToFullScreenView() { - mSubscriberViewContainer.postDelayed({ - val view = mSubscriber!!.view - if (view.parent != null) { - (view.parent as ViewGroup).removeView(view) - } - if (view is GLSurfaceView) { - view.setZOrderOnTop(false) - if (mSubscriber!!.renderer is DynamicVideoRenderer) { - (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(false) - mSubscriberViewContainer.addView(view) - } - } - switchToThumbnailCircle() - }, 4000) - } - - /** - * Video call viewListener - */ - - override fun onCallSuccessful(sessionStatusModel: SessionStatusModel) { - if (sessionStatusModel.sessionStatus == 2 || sessionStatusModel.sessionStatus == 3) { - val returnIntent = Intent() - returnIntent.putExtra("sessionStatusNotRespond", sessionStatusModel) - disconnectSession() - videoCallResponseListener?.onCallFinished(Activity.RESULT_OK, returnIntent) - stopService() - } - } - - private fun onCallChangeCallStatusSuccessful() { - val returnIntent = Intent() - returnIntent.putExtra("CallEnd", sessionStatusModel) - videoCallResponseListener?.onCallFinished(Activity.RESULT_CANCELED, returnIntent) - stopService() - } - - override fun onCallChangeCallStatusSuccessful(sessionStatusModel: SessionStatusModel?) {} - - override fun onFailure() {} - - /*** - * Notification methods - */ - - private fun addForegroundService() { - mNotificationManagerCompat = NotificationManagerCompat.from(applicationContext) - val areNotificationsEnabled = mNotificationManagerCompat!!.areNotificationsEnabled() - if (!areNotificationsEnabled) { - Toast.makeText( - this, - "You need to enable notifications for this app", - Toast.LENGTH_SHORT - ).show() - // Links to this app's notification settings - NotificationUtil.openNotificationSettingsForApp(applicationContext) - return - } - generateBigTextStyleNotification() - } - - private fun generateBigTextStyleNotification() { - notificationData = - NotificationVideoModel( - sessionStatusModel!!.patientName, - "Tap to return to call", - CHANNEL_DEFAULT_IMPORTANCE, - CHANNEL_DEFAULT_NAME, - "Video call stream background", - mSummaryText = formattedCallTime - ) - // 1. Create/Retrieve Notification Channel for O and beyond devices (26+). - val notificationChannelId: String = - NotificationUtil.createNotificationChannel(this, notificationData) - - // 2. Build the BIG_TEXT_STYLE. - val bigTextStyle = NotificationUtil.setNotificationBigStyle(notificationData) - - // 3. Set up main Intent for notification. - val pendingIntent: PendingIntent = - Intent(this, VideoStreamFloatingWidgetService::class.java) - .let { notificationIntent -> - notificationIntent.action = ACTION_MINIMIZE_CALL - PendingIntent.getService(this, 0, notificationIntent, PendingIntent.FLAG_MUTABLE ) - } - - // 4. Create additional Actions (Intents) for the Notification. - // Dismiss Action. - val endCallPendingIntent: PendingIntent = - Intent(this, VideoStreamFloatingWidgetService::class.java).apply { - action = ACTION_END_CALL - } - .let { notificationIntent -> - PendingIntent.getService(this, 0, notificationIntent, PendingIntent.FLAG_MUTABLE) - } - val endCallAction = NotificationCompat.Action.Builder( - R.drawable.ic_end_call, - "End Call", - endCallPendingIntent - ) - .build() - - // 5. Build and issue the notification. - // Notification Channel Id is ignored for Android pre O (26). - notificationCompatBuilder = notificationChannelId.let { - NotificationCompat.Builder( - applicationContext, it - ) - } - - notificationCompatBuilder - // BIG_TEXT_STYLE sets title and content for API 16 (4.1 and after). - .setStyle(bigTextStyle) - // Title for API <16 (4.0 and below) devices. - .setContentTitle(notificationData.mBigContentTitle) - // Content for API <24 (7.0 and below) devices. - .setContentText(notificationData.mContentText) - .setSmallIcon(R.mipmap.ic_launcher) - .setLargeIcon( - BitmapFactory.decodeResource( - resources, - R.mipmap.ic_launcher - ) - ) - /*.setCustomContentView(mRemoteViews) - .setCustomBigContentView(mRemoteViewsExpand)*/ - .setContentIntent(pendingIntent) -// .setDefaults(NotificationCompat.DEFAULT_ALL) - // Set primary color (important for Wear 2.0 Notifications). - .setColor(ContextCompat.getColor(applicationContext, R.color.colorPrimary)) - .setCategory(Notification.CATEGORY_SERVICE) - .setPriority(notificationData.mPriority) - .setVisibility(notificationData.mChannelLockscreenVisibility) - .addAction(endCallAction) // for version code < O, or for all versions if RemoteViews not used - .setUsesChronometer(true) - .setWhen(elapsedTime) - .setOnlyAlertOnce(true) // This will ensure that updates to an existing notification won't sound/vibrate https://stackoverflow.com/a/52349466/6246772 - .setSound(null) - .setOngoing(true) - .setCategory(NotificationCompat.CATEGORY_SERVICE) - .setColorized(true) - .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) //to show content in lock screen - - val notification = notificationCompatBuilder - .build() - - mNotificationManagerCompat!!.notify(ONGOING_NOTIFICATION_ID, notification) - startForeground(ONGOING_NOTIFICATION_ID, notification) - } - -} \ No newline at end of file +//package com.hmg.hmgDr.Service +// +//import android.annotation.SuppressLint +//import android.app.* +//import android.content.Intent +//import android.graphics.BitmapFactory +//import android.opengl.GLSurfaceView +//import android.os.* +//import android.util.Log +//import android.view.* +//import android.widget.* +//import androidx.constraintlayout.widget.ConstraintLayout +//import androidx.core.app.NotificationCompat +//import androidx.core.app.NotificationManagerCompat +//import androidx.core.content.ContextCompat +//import androidx.core.view.GestureDetectorCompat +//import com.hmg.hmgDr.Model.ChangeCallStatusRequestModel +//import com.hmg.hmgDr.Model.GetSessionStatusModel +//import com.hmg.hmgDr.Model.SessionStatusModel +//import com.hmg.hmgDr.R +//import com.hmg.hmgDr.Model.* +//import com.hmg.hmgDr.ui.VideoCallContract +//import com.hmg.hmgDr.ui.VideoCallPresenterImpl +//import com.hmg.hmgDr.ui.VideoCallResponseListener +//import com.hmg.hmgDr.util.DateUtils +//import com.hmg.hmgDr.util.opentok.DynamicVideoRenderer +//import com.hmg.hmgDr.util.NotificationUtil +//import com.hmg.hmgDr.util.ViewsUtil +//import com.hmg.hmgDr.util.audio.CustomAudioDevice +//import com.opentok.android.* +//import java.util.* +// +// +//class VideoStreamFloatingWidgetService : BaseMovingFloatingWidget(), Session.SessionListener, +// PublisherKit.PublisherListener, +// SubscriberKit.VideoListener, VideoCallContract.VideoCallView { +//// +//// companion object { +//// @JvmStatic +//// +//// private val TAG = VideoStreamFloatingWidgetService::class.java.simpleName +//// +//// const val CHANNEL_DEFAULT_IMPORTANCE = "Video_stream_channel" +//// const val CHANNEL_DEFAULT_NAME = "Video cAll" +//// const val ONGOING_NOTIFICATION_ID = 1 +//// +//// const val ACTION_START_CALL = "com.hmg.hmgDr.Service.action.startCall" +//// const val ACTION_MINIMIZE_CALL = "com.hmg.hmgDr.Service.action.minimizeCall" +//// const val ACTION_END_CALL = "com.hmg.hmgDr.Service.action.endCall" +//// const val ACTION_CHANGE_EXPANDED_COLLAPSED = +//// "com.hmg.hmgDr.Service.action.changeExpandedCollapsed" +//// const val NOTIFICATION_IS_EXPANDED = "is_expanded" +//// } +//// +//// var arguments: Bundle? = null +//// var serviceRunning: Boolean = false +//// +//// private val serviceBinder: IBinder = VideoStreamBinder() +//// private lateinit var videoCallPresenter: VideoCallContract.VideoCallPresenter +//// var videoCallResponseListener: VideoCallResponseListener? = null +//// +//// private lateinit var recordContainer: FrameLayout +//// private lateinit var thumbnail_container: FrameLayout +//// private lateinit var activity_clingo_video_call: RelativeLayout +//// private lateinit var mPublisherViewContainer: FrameLayout +//// private lateinit var mPublisherViewIcon: View +//// private lateinit var mSubscriberViewContainer: FrameLayout +//// private lateinit var mSubscriberViewIcon: ImageView +//// private lateinit var controlPanel: ConstraintLayout +//// +//// private lateinit var parentView: View +//// private lateinit var videoCallContainer: ConstraintLayout +//// private lateinit var layoutName: RelativeLayout +//// private lateinit var layoutMini: RelativeLayout +//// private lateinit var icMini: ImageButton +//// private lateinit var mCallBtn: ImageView +//// private lateinit var btnMinimize: ImageView +//// private lateinit var mCameraBtn: ImageView +//// private lateinit var mSwitchCameraBtn: ImageView +//// private lateinit var mspeckerBtn: ImageView +//// private lateinit var mMicBtn: ImageView +//// private lateinit var patientName: TextView +//// private lateinit var tvTimer: TextView +////// private lateinit var cmTimer: Chronometer +//// +//// private var mSession: Session? = null +//// private var mPublisher: Publisher? = null +//// private var mSubscriber: Subscriber? = null +//// +//// private var mVolHandler: Handler? = null +//// private var mConnectedHandler: Handler? = null +//// private var mVolRunnable: Runnable? = null +//// private var mConnectedRunnable: Runnable? = null +//// private var isConnected = false +//// +//// private var mCallTimerHandler: Handler? = null +//// private var mCallTimerRunnable: Runnable? = null +//// private var mCallFirstTime: Date = Date() +//// +//// private var sessionStatusModel: GetSessionStatusModel? = null +//// +//// private var apiKey: String? = null +//// private var sessionId: String? = null +//// private var token: String? = null +//// private var appLang: String? = null +//// private var baseUrl: String? = null +//// private var isRecording: Boolean = true +//// +//// private var isSwitchCameraClicked = false +//// private var isCameraClicked = false +//// private var isSpeckerClicked = false +//// private var isMicClicked = false +//// private var elapsedTime: Long = 0 +//// private var formattedCallTime: String = "00:00" +//// private lateinit var notificationData: NotificationVideoModel +//// +//// var isFullScreen: Boolean = true +//// private var isCircle: Boolean = false +//// lateinit var customAudioDevice: CustomAudioDevice +//// +//// // Notification variables +//// private var mNotificationManagerCompat: NotificationManagerCompat? = null +//// private lateinit var notificationCompatBuilder: NotificationCompat.Builder +//// +//// override fun onBind(intent: Intent?): IBinder { +//// return serviceBinder +//// } +//// +//// override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { +//// if (intent != null) { +//// +//// val action = intent.action +//// +//// if (action == ACTION_START_CALL) { +//// if (intent.extras != null) { +//// arguments = intent.extras +//// arguments?.run { +//// apiKey = getString("apiKey") +//// sessionId = getString("sessionId") +//// token = getString("token") +//// appLang = getString("appLang") +//// baseUrl = getString("baseUrl") +//// sessionStatusModel = getParcelable("sessionStatusModel") +//// if (sessionStatusModel != null) +//// isRecording = sessionStatusModel!!.isRecording +//// } +//// +//// addFloatingWidgetView() +//// handleDragDialog() +//// addForegroundService() +//// } +//// } else if (action == ACTION_END_CALL) { +//// closeVideoCall() +//// } else if (action == ACTION_MINIMIZE_CALL) { +//// if (!isFullScreen) +//// onMinimizedClicked() +//// } else if (action == ACTION_CHANGE_EXPANDED_COLLAPSED) { +//// val isExpanded = intent.extras!!.getBoolean(NOTIFICATION_IS_EXPANDED) +//// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { +//// // No use channel importance +//// if (isExpanded) { +//// notificationCompatBuilder.priority = Notification.PRIORITY_LOW +//// } else { +//// notificationCompatBuilder.priority = Notification.PRIORITY_HIGH +//// } +//// } else { +//// if (isExpanded) { +//// notificationCompatBuilder.priority = Notification.PRIORITY_LOW +//// } else { +//// notificationCompatBuilder.priority = Notification.PRIORITY_HIGH +//// } +//// } +//// mNotificationManagerCompat?.notify( +//// ONGOING_NOTIFICATION_ID, +//// notificationCompatBuilder.build() +//// ) +//// } +//// +//// } +//// return START_STICKY +//// } +//// +//// inner class VideoStreamBinder : Binder() { +//// val service: VideoStreamFloatingWidgetService +//// get() = this@VideoStreamFloatingWidgetService +//// } +//// +//// override fun onDestroy() { +//// try { +//// mWindowManager?.removeView(floatingWidgetView) +//// floatingWidgetView = null +//// mSession = null +//// mWindowManager = null +//// +//// } catch (e: Exception) { +//// Log.e("onDestroyService", "${e.localizedMessage}.") +//// } +//// super.onDestroy() +//// } +//// +//// private fun stopService() { +//// AudioDeviceManager.getAudioDevice().onPause() +//// +//// mCallTimerRunnable?.let { +//// mCallTimerHandler?.removeCallbacks(it) +//// mCallTimerHandler = null +//// mCallTimerRunnable = null +//// } +//// +//// // because problem that timer still continue longer a bit than service so notification called again +//// mNotificationManagerCompat = null +//// stopForeground(true) +//// stopSelf() +//// videoCallResponseListener?.minimizeVideoEvent(false) +//// try { +//// mWindowManager?.removeView(floatingWidgetView) +//// } catch (e: Exception) { +//// Log.e("stopService", "${e.localizedMessage}.") +//// } +//// } +//// +//// override fun addFloatingWidgetView() { +//// super.addFloatingWidgetView() +//// +//// init(floatingWidgetView!!) +//// +//// //Add the view to the window +//// mWindowManager?.addView(floatingWidgetView, windowManagerParams) +//// } +//// +//// @SuppressLint("ClickableViewAccessibility", "RestrictedApi") +//// private fun init(view: View) { +//// initUI(view) +//// +//// patientName.text = sessionStatusModel!!.patientName +//// +//// if (isRecording) { +//// recordContainer.visibility = View.VISIBLE +//// } else { +//// recordContainer.visibility = View.GONE +//// } +//// +//// videoCallPresenter = VideoCallPresenterImpl(this, baseUrl) +//// +//// checkClientConnected() +//// setCallStartTimer() +//// handleVideoViewHeight() +//// +//// mDetector = GestureDetectorCompat( +//// this, +//// MyGestureListener( +//// { showControlPanelTemporarily() }, +//// { miniCircleDoubleTap() }) +//// ) +//// try { +//// // Add a custom audio device before session initialization, +//// // so when the service is destroyed it will not be errors that receivers is still in memory +//// customAudioDevice = CustomAudioDevice(this) +//// customAudioDevice.setRendererMute(false) +//// if (AudioDeviceManager.getAudioDevice() == null) { +//// AudioDeviceManager.setAudioDevice(customAudioDevice) +//// } else { +//// AudioDeviceManager.getAudioDevice().onResume() +//// } +//// +//// mSession = Session.Builder(this, apiKey, sessionId).build() +//// mSession!!.setSessionListener(this) +//// mSession!!.connect(token) +//// mSession!!.setReconnectionListener(object : Session.ReconnectionListener { +//// override fun onReconnecting(session: Session?) { +//// +//// } +//// +//// override fun onReconnected(session: Session?) { +//// session?.connect(token) +//// session?.onResume() +//// } +//// }) +//// } catch (e: Exception) { +//// e.printStackTrace() +//// } +//// } +//// +//// private fun initUI(view: View) { +//// videoCallContainer = view.findViewById(R.id.video_call_ll) +//// floatingViewContainer = videoCallContainer +//// +//// layoutName = view.findViewById(R.id.layout_name) as RelativeLayout +//// layoutMini = view.findViewById(R.id.layout_mini) +//// icMini = view.findViewById(R.id.ic_mini) +//// recordContainer = view.findViewById(R.id.record_container) +//// activity_clingo_video_call = view.findViewById(R.id.activity_clingo_video_call) +//// +//// thumbnail_container = view.findViewById(R.id.thumbnail_container) +//// mPublisherViewContainer = view.findViewById(R.id.local_video_view_container) +//// mPublisherViewIcon = view.findViewById(R.id.local_video_view_icon) +//// mSubscriberViewIcon = view.findViewById(R.id.remote_video_view_icon) +//// mSubscriberViewContainer = view.findViewById(R.id.remote_video_view_container) +//// +//// patientName = view.findViewById(R.id.patient_name) +//// tvTimer = view.findViewById(R.id.tv_timer) +//// +//// controlPanel = view.findViewById(R.id.control_panel) +//// mCallBtn = view.findViewById(R.id.btn_call) +//// btnMinimize = view.findViewById(R.id.btn_minimize) +//// mCameraBtn = view.findViewById(R.id.btn_camera) +//// mSwitchCameraBtn = view.findViewById(R.id.btn_switch_camera) +//// mspeckerBtn = view.findViewById(R.id.btn_specker) +//// mMicBtn = view.findViewById(R.id.btn_mic) +//// +//// mCallBtn.setOnClickListener { +//// onCallClicked() +//// } +//// btnMinimize.setOnClickListener { +//// onMinimizedClicked() +//// } +//// mCameraBtn.setOnClickListener { +//// onCameraClicked(it) +//// } +//// mSwitchCameraBtn.setOnClickListener { +//// onSwitchCameraClicked(it) +//// } +//// mspeckerBtn.setOnClickListener { +//// onSpeckerClicked(it) +//// } +//// mMicBtn.setOnClickListener { +//// onMicClicked(it) +//// } +//// icMini.setOnClickListener { +//// onMiniCircleClicked() +//// } +//// } +//// +//// private fun checkClientConnected() { +//// mConnectedHandler = Handler((Looper.getMainLooper())) +//// mConnectedRunnable = Runnable { +//// if (!isConnected) { +//// videoCallPresenter.callClintConnected(sessionStatusModel) +//// } +//// } +//// mConnectedHandler!!.postDelayed( +//// mConnectedRunnable!!, +//// (55 * 1000).toLong() +//// ) +//// } +//// +//// private fun setCallStartTimer() { +//// mCallTimerHandler = Handler((Looper.getMainLooper())) +//// mCallTimerRunnable = Runnable { +//// formattedCallTime = DateUtils.differentDateTimeBetweenDateAndNow(mCallFirstTime) +//// tvTimer.text = formattedCallTime +//// +//// // for change notification timer +//// if (mNotificationManagerCompat != null) { +//// notificationData.mSummaryText = formattedCallTime +//// val bigTextStyle = NotificationUtil.setNotificationBigStyle(notificationData) +//// notificationCompatBuilder.setStyle(bigTextStyle) +//// mNotificationManagerCompat?.notify( +//// ONGOING_NOTIFICATION_ID, +//// notificationCompatBuilder.build() +//// ) +//// } +//// mCallTimerHandler!!.postDelayed(mCallTimerRunnable!!, 1000L) +//// } +//// +//// } +//// +//// private fun handleVideoViewHeight() { +//// val layoutNameParam: ConstraintLayout.LayoutParams = +//// layoutName.layoutParams as ConstraintLayout.LayoutParams +//// val layoutMiniParam: ConstraintLayout.LayoutParams = +//// layoutMini.layoutParams as ConstraintLayout.LayoutParams +//// val controlPanelParam: ConstraintLayout.LayoutParams = +//// controlPanel.layoutParams as ConstraintLayout.LayoutParams +//// +//// val layoutNameHeight: Int = +//// resources.getDimension(R.dimen.layout_name_height).toInt() +//// val layoutMiniHeight: Int = +//// resources.getDimension(R.dimen.layout_mini_height).toInt() +//// val panelHeight: Int = resources.getDimension(R.dimen.layout_panel_height).toInt() +//// val panelHeightSmall: Int = +//// resources.getDimension(R.dimen.layout_panel_height_small).toInt() +//// +//// val panelPadding: Int = +//// resources.getDimension(R.dimen.padding_space_big).toInt() +//// val panelPaddingMedium: Int = +//// resources.getDimension(R.dimen.padding_space_medium).toInt() +//// +//// val temp = ViewsUtil.getStatusBarHeight(applicationContext) / 2 +//// +//// val screenWidth: Float +//// val screenHeight: Float +//// +//// if (isFullScreen) { +//// screenWidth = ViewsUtil.getWidthDp(this) +//// screenHeight = ViewsUtil.getHeightDp(this) +//// +//// layoutNameParam.height = layoutNameHeight + temp +//// layoutMiniParam.height = 0 +//// controlPanelParam.height = panelHeight + temp +//// +//// controlPanel.setPadding(panelPadding, panelPadding, panelPadding, panelPadding) +//// } else { +//// +//// if (isCircle) { +//// screenWidth = 300F +//// screenHeight = 300F +//// +//// layoutNameParam.height = 0 +//// layoutMiniParam.height = 0 +//// controlPanelParam.height = 0 +//// } else { +//// screenWidth = 400F +//// screenHeight = 600F +//// +//// layoutNameParam.height = 0 +//// layoutMiniParam.height = layoutMiniHeight +//// controlPanelParam.height = panelHeightSmall +//// } +//// +//// controlPanel.setPadding( +//// panelPaddingMedium, +//// panelPaddingMedium, +//// panelPaddingMedium, +//// panelPaddingMedium +//// ) +//// } +//// +//// layoutName.layoutParams = layoutNameParam +//// layoutMini.layoutParams = layoutMiniParam +//// controlPanel.layoutParams = controlPanelParam +//// +//// var videoStreamHeight = +//// screenHeight - controlPanelParam.height - layoutNameParam.height - layoutMiniParam.height +//// +//// if (isFullScreen) { +////// videoStreamHeight -= getStatusBarHeight() / 2 +//// } +//// +//// val callLayoutParam: ConstraintLayout.LayoutParams = +//// activity_clingo_video_call.layoutParams as ConstraintLayout.LayoutParams +//// +//// callLayoutParam.height = videoStreamHeight.toInt() +//// callLayoutParam.width = screenWidth.toInt() +//// } +//// +//// private fun setViewsVisibility() { +//// val btnMinimizeLayoutParam: ConstraintLayout.LayoutParams = +//// btnMinimize.layoutParams as ConstraintLayout.LayoutParams +//// val mCallBtnLayoutParam: ConstraintLayout.LayoutParams = +//// mCallBtn.layoutParams as ConstraintLayout.LayoutParams +//// +//// val iconSize: Int = resources.getDimension(R.dimen.video_icon_size).toInt() +//// val iconSizeSmall: Int = +//// resources.getDimension(R.dimen.video_icon_size_small).toInt() +//// +//// val localPreviewMargin: Int = +//// resources.getDimension(R.dimen.local_preview_margin_top).toInt() +//// val localPreviewWidth: Int = +//// resources.getDimension(R.dimen.local_preview_width).toInt() +//// val localPreviewHeight: Int = +//// resources.getDimension(R.dimen.local_preview_height).toInt() +//// val localPreviewLayoutParam: RelativeLayout.LayoutParams = +//// mPublisherViewContainer.layoutParams as RelativeLayout.LayoutParams +//// +//// val remotePreviewIconSize: Int = +//// resources.getDimension(R.dimen.remote_back_icon_size).toInt() +//// val remotePreviewIconSizeSmall: Int = +//// resources.getDimension(R.dimen.remote_back_icon_size_small).toInt() +//// val remotePreviewLayoutParam: FrameLayout.LayoutParams = +//// mSubscriberViewIcon.layoutParams as FrameLayout.LayoutParams +//// +//// if (isFullScreen) { +//// layoutName.visibility = View.VISIBLE +//// layoutMini.visibility = View.GONE +//// mCameraBtn.visibility = View.VISIBLE +//// mSwitchCameraBtn.visibility = View.VISIBLE +////// mspeckerBtn.visibility = View.VISIBLE +//// mMicBtn.visibility = View.VISIBLE +//// +//// btnMinimizeLayoutParam.width = iconSize +//// btnMinimizeLayoutParam.height = iconSize +//// mCallBtnLayoutParam.width = iconSize +//// mCallBtnLayoutParam.height = iconSize +////// localPreviewLayoutIconParam = FrameLayout.LayoutParams(localPreviewIconSize, localPreviewIconSize) +//////// localPreviewLayoutParam = RelativeLayout.LayoutParams(localPreviewWidth, localPreviewHeight) +//// localPreviewLayoutParam.width = localPreviewWidth +//// localPreviewLayoutParam.height = localPreviewHeight +//// localPreviewLayoutParam.setMargins(0, localPreviewMargin, localPreviewMargin, 0) +//// if (mPublisher != null && mPublisher!!.view.parent == null) { +//// mPublisherViewContainer.addView(mPublisher!!.view) +//// } +//// mPublisherViewContainer.visibility = View.VISIBLE +//// +////// remotePreviewLayoutParam = FrameLayout.LayoutParams(remotePreviewIconSize, remotePreviewIconSize) +//// remotePreviewLayoutParam.width = remotePreviewIconSize +//// remotePreviewLayoutParam.height = remotePreviewIconSize +//// } else { +//// layoutName.visibility = View.GONE +//// layoutMini.visibility = View.VISIBLE +//// mCameraBtn.visibility = View.GONE +//// mSwitchCameraBtn.visibility = View.GONE +////// mspeckerBtn.visibility = View.GONE +//// mMicBtn.visibility = View.GONE +////// mPublisherViewContainer.visibility = View.GONE +////// mPublisherViewIcon.visibility = View.GONE +//// +////// layoutParam = ConstraintLayout.LayoutParams(iconSizeSmall, iconSizeSmall) +//// btnMinimizeLayoutParam.width = iconSizeSmall +//// btnMinimizeLayoutParam.height = iconSizeSmall +//// mCallBtnLayoutParam.width = iconSizeSmall +//// mCallBtnLayoutParam.height = iconSizeSmall +//// +//// localPreviewLayoutParam.width = 0 +//// localPreviewLayoutParam.height = 0 +//// localPreviewLayoutParam.setMargins(0, localPreviewMargin / 2, localPreviewMargin / 2, 0) +//// +//// if (mPublisher != null) { +//// mPublisherViewContainer.removeView(mPublisher!!.view) +//// } +//// mPublisherViewContainer.visibility = View.GONE +////// localPreviewLayoutIconParam = FrameLayout.LayoutParams(localPreviewIconSmall, localPreviewIconSmall) +//////// localPreviewLayoutParam = RelativeLayout.LayoutParams(localPreviewWidthSmall, localPreviewHeightSmall) +////// localPreviewLayoutParam.width = localPreviewWidthSmall +////// localPreviewLayoutParam.height = localPreviewWidthSmall +////// localPreviewLayoutParam.setMargins(0,localPreviewMarginSmall, localPreviewMarginSmall, 0) +////// remotePreviewLayoutParam = FrameLayout.LayoutParams(remotePreviewIconSizeSmall, remotePreviewIconSizeSmall) +//// remotePreviewLayoutParam.width = remotePreviewIconSizeSmall +//// remotePreviewLayoutParam.height = remotePreviewIconSizeSmall +//// +//// if (isCircle) { +//// controlPanel.visibility = View.GONE +//// layoutMini.visibility = View.GONE +//// } else { +//// controlPanel.visibility = View.VISIBLE +//// layoutMini.visibility = View.VISIBLE +//// } +//// } +//// +//// mPublisherViewContainer.layoutParams = localPreviewLayoutParam +////// mPublisherViewIcon.layoutParams = localPreviewLayoutIconParam +//// mSubscriberViewIcon.layoutParams = remotePreviewLayoutParam +//// +//// btnMinimize.layoutParams = btnMinimizeLayoutParam +//// mCallBtn.layoutParams = mCallBtnLayoutParam +//// +//// handleVideoViewHeight() +//// } +//// +//// @SuppressLint("ClickableViewAccessibility") +//// private fun handleDragDialog() { +//// getWindowManagerDefaultDisplay() +//// +//// videoCallContainer.setOnTouchListener(dragListener) +//// mSubscriberViewContainer.setOnTouchListener(dragListener) +//// } +//// +//// /*** +//// * Click Listener +//// */ +//// +//// fun onCallClicked() { +//// disconnectSession() +//// } +//// +//// fun onMinimizedClicked() { +//// if (isCircle) { +//// onMiniCircleClicked() +//// } +//// if (isFullScreen) { +//// windowManagerParams.width = 400 +//// windowManagerParams.height = 600 +//// +//// try { +//// mWindowManager?.updateViewLayout(floatingWidgetView, windowManagerParams) +//// } catch (e: Exception) { +//// } +//// recordContainer.visibility = View.GONE +//// } else { +//// windowManagerParams.width = WindowManager.LayoutParams.MATCH_PARENT +//// windowManagerParams.height = WindowManager.LayoutParams.MATCH_PARENT +//// +//// try { +//// mWindowManager?.updateViewLayout(floatingWidgetView, windowManagerParams) +//// } catch (e: Exception) { +//// } +//// +//// if (isRecording) { +//// recordContainer.visibility = View.VISIBLE +//// } else { +//// recordContainer.visibility = View.GONE +//// } +//// } +//// isFullScreen = !isFullScreen +//// +//// val res = if (isFullScreen) R.drawable.reducing else R.drawable.expand +//// btnMinimize.setImageResource(res) +//// setViewsVisibility() +//// +////// videoCallResponseListener?.minimizeVideoEvent(!isFullScreen) +//// } +//// +//// private fun onCameraClicked(view: View?) { +//// if (mPublisher != null) { +//// isCameraClicked = !isCameraClicked +//// mPublisher!!.publishVideo = !isCameraClicked +//// val res = if (isCameraClicked) R.drawable.video_disabled else R.drawable.video_enabled +//// mCameraBtn.setImageResource(res) +//// } +//// } +//// +//// private fun onSwitchCameraClicked(view: View?) { +//// if (mPublisher != null) { +//// isSwitchCameraClicked = !isSwitchCameraClicked +//// mPublisher!!.cycleCamera() +//// val res = if (isSwitchCameraClicked) R.drawable.camera_front else R.drawable.camera_back +//// mSwitchCameraBtn.setImageResource(res) +//// } +//// } +//// +//// private fun onSpeckerClicked(view: View?) { +//// if (mSubscriber != null) { +//// isSpeckerClicked = !isSpeckerClicked +//// mSubscriber!!.subscribeToAudio = !isSpeckerClicked +//// val res = if (isSpeckerClicked) R.drawable.audio_disabled else R.drawable.audio_enabled +//// mspeckerBtn.setImageResource(res) +//// } +//// } +//// +//// private fun onMicClicked(view: View?) { +//// if (mPublisher != null) { +//// isMicClicked = !isMicClicked +//// mPublisher!!.publishAudio = !isMicClicked +//// val res = if (isMicClicked) R.drawable.mic_disabled else R.drawable.mic_enabled +//// mMicBtn.setImageResource(res) +//// } +//// } +//// +//// private fun onMiniCircleClicked() { +//// if (isCircle) { +//// windowManagerParams.width = 400 +//// windowManagerParams.height = 600 +//// +//// try { +//// mWindowManager?.updateViewLayout(floatingWidgetView, windowManagerParams) +//// } catch (e: Exception) { +//// } +//// } else { +//// windowManagerParams.width = 300 +//// windowManagerParams.height = 300 +//// +//// try { +//// mWindowManager?.updateViewLayout(floatingWidgetView, windowManagerParams) +//// } catch (e: Exception) { +//// } +//// } +//// isCircle = !isCircle +//// +//// +//// if (mSubscriber != null) { +//// (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(isCircle) +//// } else { +//// if (isCircle) { +//// videoCallContainer.background = +//// ContextCompat.getDrawable(this, R.drawable.circle_shape) +//// mSubscriberViewContainer.background = +//// ContextCompat.getDrawable(this, R.drawable.circle_shape) +//// } else { +//// videoCallContainer.setBackgroundColor( +//// ContextCompat.getColor( +//// this, +//// R.color.text_color +//// ) +//// ) +//// mSubscriberViewContainer.setBackgroundColor( +//// ContextCompat.getColor( +//// this, +//// R.color.remoteBackground +//// ) +//// ) +//// } +//// } +//// +//// if (isCircle) { +//// controlPanel.visibility = View.GONE +//// layoutMini.visibility = View.GONE +//// } else { +//// controlPanel.visibility = View.VISIBLE +//// layoutMini.visibility = View.VISIBLE +//// } +//// +//// handleVideoViewHeight() +//// } +//// +//// private fun showControlPanelTemporarily() { +//// if (!isCircle) { +//// controlPanel.visibility = View.VISIBLE +//// mVolHandler!!.removeCallbacks(mVolRunnable!!) +//// mVolHandler!!.postDelayed(mVolRunnable!!, (5 * 1000).toLong()) +//// } +//// } +//// +//// private fun miniCircleDoubleTap() { +//// if (isCircle) { +//// onMiniCircleClicked() +//// } +//// } +//// +//// fun closeVideoCall() { +//// onCallClicked() +//// } +//// +//// /*** +//// * Session Listener +//// */ +//// +//// override fun onConnected(session: Session?) { +//// Log.i(TAG, "Session Connected") +//// mPublisher = Publisher.Builder(this) +////// .name("publisher") +////// .renderer(ThumbnailCircleVideoRenderer(requireContext())) +//// .build() +//// mPublisher!!.setPublisherListener(this) +//// mPublisher!!.audioFallbackEnabled = false +//// if (mPublisher!!.view is GLSurfaceView) { +//// (mPublisher!!.view as GLSurfaceView).setZOrderOnTop(true) +//// } +//// +//// mPublisherViewContainer.addView(mPublisher!!.view) +//// +//// mSession!!.publish(mPublisher) +//// +//// // start call timer to show on top +//// mCallFirstTime = Date() +//// mCallTimerHandler!!.postDelayed(mCallTimerRunnable!!, 1000L) +//// +//// videoCallResponseListener?.minimizeVideoEvent(true) +//// } +//// +//// override fun onDisconnected(session: Session) { +//// Log.d(TAG, "onDisconnected: disconnected from session " + session.sessionId) +////// mSession = null +////// cmTimer.stop() +////// disconnectSession() +////// videoCallResponseListener?.minimizeVideoEvent(false) +//// } +//// +//// override fun onError(session: Session, opentokError: OpentokError) { +//// Log.d(TAG, "onError: Error (" + opentokError.message + ") in session " + session.sessionId) +//// } +//// +//// override fun onStreamReceived(session: Session, stream: Stream) { +//// Log.d( +//// TAG, +//// "onStreamReceived: New stream " + stream.streamId + " in session " + session.sessionId +//// ) +//// +//// if (mSubscriber != null) { +//// isConnected = true +//// return +//// } +//// isConnected = true +//// subscribeToStream(stream) +//// if (mConnectedHandler != null && mConnectedRunnable != null) +//// mConnectedHandler!!.removeCallbacks(mConnectedRunnable!!) +//// videoCallPresenter.callChangeCallStatus( +//// ChangeCallStatusRequestModel( +//// 3, +//// sessionStatusModel!!.doctorId, +//// sessionStatusModel!!.generalid, +//// token, +//// sessionStatusModel!!.vcid +//// ) +//// ) +//// } +//// +//// override fun onStreamDropped(session: Session, stream: Stream) { +//// Log.d( +//// TAG, +//// "onStreamDropped: Stream " + stream.streamId + " dropped from session " + session.sessionId +//// ) +//// if (mSubscriber == null) { +//// return +//// } +//// if (mSubscriber!!.stream == stream) { +//// mSubscriberViewContainer.removeView(mSubscriber!!.view) +//// mSubscriber!!.destroy() +//// mSubscriber = null +//// } +////// disconnectSession() +//// } +//// +//// private fun disconnectSession() { +//// if (mSession == null) { +//// videoCallResponseListener?.onCallFinished(Activity.RESULT_CANCELED) +//// stopService() +//// return +//// } +//// +//// if (mSubscriber != null) { +//// mSubscriberViewContainer.removeView(mSubscriber!!.view) +//// mSession!!.unsubscribe(mSubscriber) +//// mSubscriber!!.destroy() +//// mSubscriber = null +//// } +//// if (mPublisher != null) { +//// mPublisherViewContainer.removeView(mPublisher!!.view) +//// mSession!!.unpublish(mPublisher) +//// mPublisher!!.destroy() +//// mPublisher = null +//// } +//// mSession!!.disconnect() +//// +//// videoCallPresenter.callChangeCallStatus( +//// ChangeCallStatusRequestModel( +//// 16, +//// sessionStatusModel!!.doctorId, +//// sessionStatusModel!!.generalid, +//// token, +//// sessionStatusModel!!.vcid +//// ) +//// ) +////// stopService() +//// onCallChangeCallStatusSuccessful() +//// } +//// +//// private fun subscribeToStream(stream: Stream) { +//// mSubscriber = Subscriber.Builder(this, stream) +//// .renderer(DynamicVideoRenderer(this)) +//// .build() +//// mSubscriber!!.setVideoListener(this) +//// mSession!!.subscribe(mSubscriber) +//// } +//// +//// /** +//// * Publish Listener +//// */ +//// +//// override fun onStreamCreated(publisherKit: PublisherKit?, stream: Stream) { +//// Log.d(TAG, "onStreamCreated: Own stream " + stream.streamId + " created") +//// } +//// +//// override fun onStreamDestroyed(publisherKit: PublisherKit?, stream: Stream) { +//// Log.d(TAG, "onStreamDestroyed: Own stream " + stream.streamId + " destroyed") +//// } +//// +//// override fun onError(publisherKit: PublisherKit?, opentokError: OpentokError) { +//// Log.d(TAG, "onError: Error (" + opentokError.message + ") in publisher") +//// // videoCallResponseListener?.errorHandle("Error (" + opentokError.message + ") in publisher") +////// dialog?.dismiss() +//// } +//// +//// /** +//// * Video Listener +//// */ +//// +//// override fun onVideoDataReceived(subscriberKit: SubscriberKit?) { +//// if (mSubscriber == null) { +//// return +//// } +//// mSubscriber!!.setStyle( +//// BaseVideoRenderer.STYLE_VIDEO_SCALE, +//// BaseVideoRenderer.STYLE_VIDEO_FILL +//// ) +//// (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(false) +//// mSubscriberViewContainer.addView(mSubscriber!!.view) +////// switchToThumbnailCircle() +//// } +//// +//// override fun onVideoDisabled(subscriberKit: SubscriberKit?, s: String?) { +//// Log.d(TAG, "onVideoDisabled: Error ($s)") +//// +////// if (isCircle) { +////// videoCallContainer.background = ContextCompat.getDrawable(requireContext(), R.drawable.circle_shape) +////// mSubscriberViewContainer.background = ContextCompat.getDrawable(requireContext(), R.drawable.circle_shape) +////// } else { +////// videoCallContainer.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.text_color)) +////// mSubscriberViewContainer.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.remoteBackground)) +////// } +//// } +//// +//// override fun onVideoEnabled(subscriberKit: SubscriberKit?, s: String?) { +//// Log.d(TAG, "onVideoEnabled: Error ($s)") +//// +////// if (mSubscriber != null) { +////// (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(isCircle) +////// } +//// } +//// +//// override fun onVideoDisableWarning(subscriberKit: SubscriberKit?) {} +//// +//// override fun onVideoDisableWarningLifted(subscriberKit: SubscriberKit?) {} +//// +//// private fun switchToThumbnailCircle() { +//// thumbnail_container.postDelayed({ +//// val view = mSubscriber!!.view +//// if (view.parent != null) { +//// (view.parent as ViewGroup).removeView(view) +//// } +//// if (view is GLSurfaceView) { +//// view.setZOrderOnTop(true) +//// if (mSubscriber!!.renderer is DynamicVideoRenderer) { +//// (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(true) +//// thumbnail_container.addView(view) +//// } +//// } +//// switchToFullScreenView() +//// }, 4000) +//// } +//// +//// private fun switchToFullScreenView() { +//// mSubscriberViewContainer.postDelayed({ +//// val view = mSubscriber!!.view +//// if (view.parent != null) { +//// (view.parent as ViewGroup).removeView(view) +//// } +//// if (view is GLSurfaceView) { +//// view.setZOrderOnTop(false) +//// if (mSubscriber!!.renderer is DynamicVideoRenderer) { +//// (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(false) +//// mSubscriberViewContainer.addView(view) +//// } +//// } +//// switchToThumbnailCircle() +//// }, 4000) +//// } +//// +//// /** +//// * Video call viewListener +//// */ +//// +//// override fun onCallSuccessful(sessionStatusModel: SessionStatusModel) { +//// if (sessionStatusModel.sessionStatus == 2 || sessionStatusModel.sessionStatus == 3) { +//// val returnIntent = Intent() +//// returnIntent.putExtra("sessionStatusNotRespond", sessionStatusModel) +//// disconnectSession() +//// videoCallResponseListener?.onCallFinished(Activity.RESULT_OK, returnIntent) +//// stopService() +//// } +//// } +//// +//// private fun onCallChangeCallStatusSuccessful() { +//// val returnIntent = Intent() +//// returnIntent.putExtra("CallEnd", sessionStatusModel) +//// videoCallResponseListener?.onCallFinished(Activity.RESULT_CANCELED, returnIntent) +//// stopService() +//// } +//// +//// override fun onCallChangeCallStatusSuccessful(sessionStatusModel: SessionStatusModel?) {} +//// +//// override fun onFailure() {} +//// +//// /*** +//// * Notification methods +//// */ +//// +//// private fun addForegroundService() { +//// mNotificationManagerCompat = NotificationManagerCompat.from(applicationContext) +//// val areNotificationsEnabled = mNotificationManagerCompat!!.areNotificationsEnabled() +//// if (!areNotificationsEnabled) { +//// Toast.makeText( +//// this, +//// "You need to enable notifications for this app", +//// Toast.LENGTH_SHORT +//// ).show() +//// // Links to this app's notification settings +//// NotificationUtil.openNotificationSettingsForApp(applicationContext) +//// return +//// } +//// generateBigTextStyleNotification() +//// } +//// +//// private fun generateBigTextStyleNotification() { +//// notificationData = +//// NotificationVideoModel( +//// sessionStatusModel!!.patientName, +//// "Tap to return to call", +//// CHANNEL_DEFAULT_IMPORTANCE, +//// CHANNEL_DEFAULT_NAME, +//// "Video call stream background", +//// mSummaryText = formattedCallTime +//// ) +//// // 1. Create/Retrieve Notification Channel for O and beyond devices (26+). +//// val notificationChannelId: String = +//// NotificationUtil.createNotificationChannel(this, notificationData) +//// +//// // 2. Build the BIG_TEXT_STYLE. +//// val bigTextStyle = NotificationUtil.setNotificationBigStyle(notificationData) +//// +//// // 3. Set up main Intent for notification. +//// val pendingIntent: PendingIntent = +//// Intent(this, VideoStreamFloatingWidgetService::class.java) +//// .let { notificationIntent -> +//// notificationIntent.action = ACTION_MINIMIZE_CALL +//// PendingIntent.getService(this, 0, notificationIntent, PendingIntent.FLAG_MUTABLE ) +//// } +//// +//// // 4. Create additional Actions (Intents) for the Notification. +//// // Dismiss Action. +//// val endCallPendingIntent: PendingIntent = +//// Intent(this, VideoStreamFloatingWidgetService::class.java).apply { +//// action = ACTION_END_CALL +//// } +//// .let { notificationIntent -> +//// PendingIntent.getService(this, 0, notificationIntent, PendingIntent.FLAG_MUTABLE) +//// } +//// val endCallAction = NotificationCompat.Action.Builder( +//// R.drawable.ic_end_call, +//// "End Call", +//// endCallPendingIntent +//// ) +//// .build() +//// +//// // 5. Build and issue the notification. +//// // Notification Channel Id is ignored for Android pre O (26). +//// notificationCompatBuilder = notificationChannelId.let { +//// NotificationCompat.Builder( +//// applicationContext, it +//// ) +//// } +//// +//// notificationCompatBuilder +//// // BIG_TEXT_STYLE sets title and content for API 16 (4.1 and after). +//// .setStyle(bigTextStyle) +//// // Title for API <16 (4.0 and below) devices. +//// .setContentTitle(notificationData.mBigContentTitle) +//// // Content for API <24 (7.0 and below) devices. +//// .setContentText(notificationData.mContentText) +//// .setSmallIcon(R.mipmap.ic_launcher) +//// .setLargeIcon( +//// BitmapFactory.decodeResource( +//// resources, +//// R.mipmap.ic_launcher +//// ) +//// ) +//// /*.setCustomContentView(mRemoteViews) +//// .setCustomBigContentView(mRemoteViewsExpand)*/ +//// .setContentIntent(pendingIntent) +////// .setDefaults(NotificationCompat.DEFAULT_ALL) +//// // Set primary color (important for Wear 2.0 Notifications). +//// .setColor(ContextCompat.getColor(applicationContext, R.color.colorPrimary)) +//// .setCategory(Notification.CATEGORY_SERVICE) +//// .setPriority(notificationData.mPriority) +//// .setVisibility(notificationData.mChannelLockscreenVisibility) +//// .addAction(endCallAction) // for version code < O, or for all versions if RemoteViews not used +//// .setUsesChronometer(true) +//// .setWhen(elapsedTime) +//// .setOnlyAlertOnce(true) // This will ensure that updates to an existing notification won't sound/vibrate https://stackoverflow.com/a/52349466/6246772 +//// .setSound(null) +//// .setOngoing(true) +//// .setCategory(NotificationCompat.CATEGORY_SERVICE) +//// .setColorized(true) +//// .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) //to show content in lock screen +//// +//// val notification = notificationCompatBuilder +//// .build() +//// +//// mNotificationManagerCompat!!.notify(ONGOING_NOTIFICATION_ID, notification) +//// startForeground(ONGOING_NOTIFICATION_ID, notification) +//// } +// +//} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/ui/fragment/VideoCallFragment.kt b/android/app/src/main/kotlin/com/hmg/hmgDr/ui/fragment/VideoCallFragment.kt index 2ed27dab..ddc967ea 100644 --- a/android/app/src/main/kotlin/com/hmg/hmgDr/ui/fragment/VideoCallFragment.kt +++ b/android/app/src/main/kotlin/com/hmg/hmgDr/ui/fragment/VideoCallFragment.kt @@ -1,1176 +1,1176 @@ -package com.hmg.hmgDr.ui.fragment - -import android.Manifest -import android.annotation.SuppressLint -import android.app.Activity -import android.app.Dialog -import android.content.Context -import android.content.Intent -import android.graphics.Color -import android.graphics.Point -import android.graphics.drawable.ColorDrawable -import android.opengl.GLSurfaceView -import android.os.* -import android.util.Log -import android.view.* -import android.widget.* -import androidx.annotation.Nullable -import androidx.appcompat.app.AlertDialog -import androidx.constraintlayout.widget.ConstraintLayout -import androidx.core.content.ContextCompat -import androidx.core.view.GestureDetectorCompat -import androidx.fragment.app.DialogFragment -import com.hmg.hmgDr.Model.ChangeCallStatusRequestModel -import com.hmg.hmgDr.Model.GetSessionStatusModel -import com.hmg.hmgDr.Model.SessionStatusModel -import com.hmg.hmgDr.R -import com.hmg.hmgDr.ui.VideoCallContract.VideoCallPresenter -import com.hmg.hmgDr.ui.VideoCallContract.VideoCallView -import com.hmg.hmgDr.ui.VideoCallPresenterImpl -import com.hmg.hmgDr.ui.VideoCallResponseListener -import com.hmg.hmgDr.util.opentok.DynamicVideoRenderer -import com.hmg.hmgDr.util.ViewsUtil -import com.opentok.android.* -import com.opentok.android.PublisherKit.PublisherListener -//import pub.devrel.easypermissions.AfterPermissionGranted -//import pub.devrel.easypermissions.AppSettingsDialog -//import pub.devrel.easypermissions.EasyPermissions -//import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks -import kotlin.math.ceil - -// check this if it works to solve keyboard not work when dialog is opened -// https://stackoverflow.com/questions/55066977/how-to-prevent-custom-dialogfragment-from-hiding-keyboard-when-being-shown -class VideoCallFragment : DialogFragment(), Session.SessionListener, - PublisherListener, - SubscriberKit.VideoListener, VideoCallView { - - private var isFullScreen: Boolean = true - private var isCircle: Boolean = false - private var x_init_cord = 0 - private var y_init_cord: Int = 0 - private var x_init_margin: Int = 0 - private var y_init_margin: Int = 0 - private val szWindow: Point = Point() - private lateinit var mWindowManager: WindowManager - private var isLeft = true - - private lateinit var videoCallPresenter: VideoCallPresenter - - private var mSession: Session? = null - private var mPublisher: Publisher? = null - private var mSubscriber: Subscriber? = null - - private var mVolHandler: Handler? = null - private var mConnectedHandler: Handler? = null - private var mVolRunnable: Runnable? = null - private var mConnectedRunnable: Runnable? = null - - private lateinit var recordContainer: FrameLayout - private lateinit var thumbnail_container: FrameLayout - private lateinit var activity_clingo_video_call: RelativeLayout - private lateinit var mPublisherViewContainer: FrameLayout - private lateinit var mPublisherViewIcon: View - private lateinit var mSubscriberViewContainer: FrameLayout - private lateinit var mSubscriberViewIcon: ImageView - private lateinit var controlPanel: ConstraintLayout - - private var apiKey: String? = null - private var sessionId: String? = null - private var token: String? = null - private var appLang: String? = null - private var baseUrl: String? = null - private var isRecording: Boolean = true - - private var isSwitchCameraClicked = false - private var isCameraClicked = false - private var isSpeckerClicked = false - private var isMicClicked = false - - private lateinit var parentView: View - private lateinit var videoCallContainer: ConstraintLayout - private lateinit var layoutName: RelativeLayout - private lateinit var layoutMini: RelativeLayout - private lateinit var icMini: ImageButton - private lateinit var mCallBtn: ImageView - private lateinit var btnMinimize: ImageView - private lateinit var mCameraBtn: ImageView - private lateinit var mSwitchCameraBtn: ImageView - private lateinit var mspeckerBtn: ImageView - private lateinit var mMicBtn: ImageView - private lateinit var patientName: TextView - private lateinit var cmTimer: Chronometer - - private var elapsedTime: Long = 0 - private var resume = false - - private val progressBar: ProgressBar? = null - private val countDownTimer: CountDownTimer? = null - private val progressBarTextView: TextView? = null - private val - progressBarLayout: RelativeLayout? = null - - private var isConnected = false - - private var sessionStatusModel: GetSessionStatusModel? = null - private var videoCallResponseListener: VideoCallResponseListener? = null - private lateinit var mDetector: GestureDetectorCompat - - override fun onCreate(savedInstanceState: Bundle?) { - requireActivity().setTheme(R.style.AppTheme) - super.onCreate(savedInstanceState) - } - - override fun onStart() { - super.onStart() - -// val params: ViewGroup.LayoutParams = dialog!!.window!!.attributes -// params.width = WindowManager.LayoutParams.MATCH_PARENT -// params.height = WindowManager.LayoutParams.MATCH_PARENT -// dialog!!.window!!.attributes = params as WindowManager.LayoutParams - - dialog?.window?.setLayout( - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.MATCH_PARENT - ) -// val parentLayoutParam: FrameLayout.LayoutParams = /*parentView.layoutParams as*/ FrameLayout.LayoutParams( -// LinearLayout.LayoutParams.MATCH_PARENT, -// LinearLayout.LayoutParams.MATCH_PARENT -// ) -// parentView.layoutParams = parentLayoutParam - } - - override fun getTheme(): Int { - return R.style.dialogTheme - } - - @SuppressLint("UseRequireInsteadOfGet") - override fun onCreateDialog(@Nullable savedInstanceState: Bundle?): Dialog {// FullScreenVideoTheme - val layoutInflater = requireActivity().layoutInflater - this.parentView = onCreateView(layoutInflater, null) - - val alertDialogBuilder: AlertDialog.Builder = - AlertDialog.Builder(requireContext(), R.style.dialogTheme) -// .setTitle(android.R.string.select_a_color) - .setView(this.parentView) -// .setPositiveButton(android.R.string.ok, { dialogInterface, i -> }) - alertDialogBuilder.setOnKeyListener { _, keyCode, keyEvent -> - // getAction to make sure this doesn't double fire - if (keyCode == KeyEvent.KEYCODE_BACK && keyEvent.action == KeyEvent.ACTION_UP) { - videoCallResponseListener?.onBackHandle() - false // Capture onKey - } else true - // Don't capture - } - return alertDialogBuilder.create() -/* - - val dialog: Dialog = super.onCreateDialog(savedInstanceState) - // Add back button listener - dialog.setOnKeyListener { _, keyCode, keyEvent -> - // getAction to make sure this doesn't double fire - if (keyCode == KeyEvent.KEYCODE_BACK && keyEvent.action == KeyEvent.ACTION_UP) { - videoCallResponseListener?.onBackHandle() - false // Capture onKey - } else true - // Don't capture - } - - return dialog -*/ - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - // This is done in a post() since the dialog must be drawn before locating. - requireView().post { - val dialogWindow = dialog!!.window - - if (dialog != null && dialogWindow != null) { - dialogWindow.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)); - } - - // Make the dialog possible to be outside touch - dialogWindow!!.setFlags( - WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, - WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL - ) - dialogWindow.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND) - requireView().invalidate() - } - } - - - fun setCallListener(videoCallResponseListener: VideoCallResponseListener) { - this.videoCallResponseListener = videoCallResponseListener - } - - private fun onCreateView( - inflater: LayoutInflater, container: ViewGroup? - ): View { - val view = inflater.inflate(R.layout.activity_video_call, container, false) - -// val parentViewLayoutParam: ConstraintLayout.LayoutParams = ConstraintLayout.LayoutParams( -// ConstraintLayout.LayoutParams.MATCH_PARENT, -// ConstraintLayout.LayoutParams.MATCH_PARENT -// ) -// parentView.layoutParams = parentViewLayoutParam - // Objects.requireNonNull(requireActivity().actionBar)!!.hide() - arguments?.run { - apiKey = getString("apiKey") - sessionId = getString("sessionId") - token = getString("token") - appLang = getString("appLang") - baseUrl = getString("baseUrl") - sessionStatusModel = getParcelable("sessionStatusModel") - if (sessionStatusModel != null) - isRecording = sessionStatusModel!!.isRecording - } - initUI(view) - requestPermissions() - - handleDragDialog() - mDetector = GestureDetectorCompat( - requireContext(), - MyGestureListener({ showControlPanelTemporarily() }, { miniCircleDoubleTap() }) - ) - - return view - } - - override fun onCreateView( - inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - return this.parentView - } - - override fun onPause() { - super.onPause() - if (mSession == null) { - return - } - mSession!!.onPause() - if (requireActivity().isFinishing) { - disconnectSession() - } - } - - override fun onResume() { - super.onResume() - if (mSession == null) { - return - } - mSession!!.onResume() - } - - override fun onDestroy() { - disconnectSession() - cmTimer.stop() - super.onDestroy() - } - - @SuppressLint("ClickableViewAccessibility") - private fun initUI(view: View) { - videoCallContainer = view.findViewById(R.id.video_call_ll) - - layoutName = view.findViewById(R.id.layout_name) - layoutMini = view.findViewById(R.id.layout_mini) - icMini = view.findViewById(R.id.ic_mini) - recordContainer = view.findViewById(R.id.record_container) - activity_clingo_video_call = view.findViewById(R.id.activity_clingo_video_call) - - thumbnail_container = view.findViewById(R.id.thumbnail_container) - mPublisherViewContainer = view.findViewById(R.id.local_video_view_container) - mPublisherViewIcon = view.findViewById(R.id.local_video_view_icon) - mSubscriberViewIcon = view.findViewById(R.id.remote_video_view_icon) - mSubscriberViewContainer = view.findViewById(R.id.remote_video_view_container) - - patientName = view.findViewById(R.id.patient_name) - patientName.text = sessionStatusModel!!.patientName - - if (isRecording) { - recordContainer.visibility = View.VISIBLE - } else { - recordContainer.visibility = View.GONE - } - -// cmTimer = view.findViewById(R.id.cmTimer) - cmTimer.format = "mm:ss" - cmTimer.onChronometerTickListener = - Chronometer.OnChronometerTickListener { arg0: Chronometer? -> -// val f: NumberFormat = DecimalFormat("00") -// f.format(minutes) - val minutes: Long - val seconds: Long - if (!resume) { - minutes = (SystemClock.elapsedRealtime() - cmTimer.base) / 1000 / 60 - seconds = (SystemClock.elapsedRealtime() - cmTimer.base) / 1000 % 60 - elapsedTime = SystemClock.elapsedRealtime() - } else { - minutes = (elapsedTime - cmTimer.base) / 1000 / 60 - seconds = (elapsedTime - cmTimer.base) / 1000 % 60 - elapsedTime += 1000 - } - val format = "%1$02d:%2$02d" // two digits - - arg0?.text = String.format(format, minutes, seconds) - Log.d(TAG, "onChronometerTick: $minutes : $seconds") - } - - icMini.setOnClickListener { - onMiniCircleClicked() - } - - controlPanel = view.findViewById(R.id.control_panel) - videoCallPresenter = VideoCallPresenterImpl(this, baseUrl) - mCallBtn = view.findViewById(R.id.btn_call) - mCallBtn.setOnClickListener { - onCallClicked() - } - btnMinimize = view.findViewById(R.id.btn_minimize) - btnMinimize.setOnClickListener { - onMinimizedClicked(it) - } - mCameraBtn = view.findViewById(R.id.btn_camera) - mCameraBtn.setOnClickListener { - onCameraClicked(it) - } - mSwitchCameraBtn = view.findViewById(R.id.btn_switch_camera) - mSwitchCameraBtn.setOnClickListener { - onSwitchCameraClicked(it) - } - mspeckerBtn = view.findViewById(R.id.btn_specker) - mspeckerBtn.setOnClickListener { - onSpeckerClicked(it) - } - mMicBtn = view.findViewById(R.id.btn_mic) - mMicBtn.setOnClickListener { - onMicClicked(it) - } - // progressBarLayout=findViewById(R.id.progressBar); - // progressBar=findViewById(R.id.progress_bar); -// progressBarTextView=findViewById(R.id.progress_bar_text); -// progressBar.setVisibility(View.GONE); -// hiddenButtons() - checkClientConnected() - handleVideoViewHeight(true) - - - - if (appLang == "ar") { - progressBarLayout!!.layoutDirection = View.LAYOUT_DIRECTION_RTL - } - } - - private fun checkClientConnected() { - mConnectedHandler = Handler((Looper.getMainLooper())) - mConnectedRunnable = Runnable { - if (!isConnected) { - videoCallPresenter.callClintConnected(sessionStatusModel) - } - } - mConnectedHandler!!.postDelayed(mConnectedRunnable!!, (55 * 1000).toLong()) - } - - private fun hiddenButtons() { - mVolHandler = Handler() - mVolRunnable = Runnable { controlPanel.visibility = View.GONE } - mVolHandler!!.postDelayed(mVolRunnable!!, (5 * 1000).toLong()) - } - - override fun onRequestPermissionsResult( - requestCode: Int, - permissions: Array, - grantResults: IntArray - ) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults) -// EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) - } - -// override fun onPermissionsGranted(requestCode: Int, perms: List) { -// Log.d(TAG, "onPermissionsGranted:" + requestCode + ":" + perms.size) -// } +//package com.hmg.hmgDr.ui.fragment // -// override fun onPermissionsDenied(requestCode: Int, perms: List) { -// Log.d(TAG, "onPermissionsDenied:" + requestCode + ":" + perms.size) -// if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) { -// AppSettingsDialog.Builder(this) -// .setTitle(getString(R.string.title_settings_dialog)) -// .setRationale(getString(R.string.rationale_ask_again)) -// .setPositiveButton(getString(R.string.setting)) -// .setNegativeButton(getString(R.string.cancel)) -// .setRequestCode(RC_SETTINGS_SCREEN_PERM) -// .build() -// .show() -// } -// } - -// @AfterPermissionGranted(RC_VIDEO_APP_PERM) - private fun requestPermissions() { -// val perms = arrayOf( -// Manifest.permission.INTERNET, -// Manifest.permission.CAMERA, -// Manifest.permission.RECORD_AUDIO, -// Manifest.permission.MODIFY_AUDIO_SETTINGS, -// Manifest.permission.CALL_PHONE -// ) -// if (EasyPermissions.hasPermissions(requireContext(), *perms)) { -// try { -// mSession = Session.Builder(context, apiKey, sessionId).build() -// mSession!!.setSessionListener(this) -// mSession!!.connect(token) +//import android.Manifest +//import android.annotation.SuppressLint +//import android.app.Activity +//import android.app.Dialog +//import android.content.Context +//import android.content.Intent +//import android.graphics.Color +//import android.graphics.Point +//import android.graphics.drawable.ColorDrawable +//import android.opengl.GLSurfaceView +//import android.os.* +//import android.util.Log +//import android.view.* +//import android.widget.* +//import androidx.annotation.Nullable +//import androidx.appcompat.app.AlertDialog +//import androidx.constraintlayout.widget.ConstraintLayout +//import androidx.core.content.ContextCompat +//import androidx.core.view.GestureDetectorCompat +//import androidx.fragment.app.DialogFragment +//import com.hmg.hmgDr.Model.ChangeCallStatusRequestModel +//import com.hmg.hmgDr.Model.GetSessionStatusModel +//import com.hmg.hmgDr.Model.SessionStatusModel +//import com.hmg.hmgDr.R +//import com.hmg.hmgDr.ui.VideoCallContract.VideoCallPresenter +//import com.hmg.hmgDr.ui.VideoCallContract.VideoCallView +//import com.hmg.hmgDr.ui.VideoCallPresenterImpl +//import com.hmg.hmgDr.ui.VideoCallResponseListener +//import com.hmg.hmgDr.util.opentok.DynamicVideoRenderer +//import com.hmg.hmgDr.util.ViewsUtil +//import com.opentok.android.* +//import com.opentok.android.PublisherKit.PublisherListener +////import pub.devrel.easypermissions.AfterPermissionGranted +////import pub.devrel.easypermissions.AppSettingsDialog +////import pub.devrel.easypermissions.EasyPermissions +////import pub.devrel.easypermissions.EasyPermissions.PermissionCallbacks +//import kotlin.math.ceil // -// mSession!!.setReconnectionListener(object :Session.ReconnectionListener{ -// override fun onReconnecting(p0: Session?) { +//// check this if it works to solve keyboard not work when dialog is opened +//// https://stackoverflow.com/questions/55066977/how-to-prevent-custom-dialogfragment-from-hiding-keyboard-when-being-shown +//class VideoCallFragment : DialogFragment(), Session.SessionListener, +// PublisherListener, +// SubscriberKit.VideoListener, VideoCallView { // -// } -// -// override fun onReconnected(session: Session?) { -// session?.connect(token) -// } -// -// -// }) -// -// -// } catch (e: Exception) { -// e.printStackTrace() -// } -// } else { -// EasyPermissions.requestPermissions( -// this, -// getString(R.string.remaining_ar), -// RC_VIDEO_APP_PERM, -// *perms -// ) -// } - } - - override fun onConnected(session: Session?) { - Log.i(TAG, "Session Connected") - mPublisher = Publisher.Builder(requireContext()) -// .name("publisher") -// .renderer(ThumbnailCircleVideoRenderer(requireContext())) - .build() - mPublisher!!.setPublisherListener(this) - if (mPublisher!!.view is GLSurfaceView) { - (mPublisher!!.view as GLSurfaceView).setZOrderOnTop(true) - } - - mPublisherViewContainer.addView(mPublisher!!.view) - - mSession!!.publish(mPublisher) - - if (!resume) { - cmTimer.base = SystemClock.elapsedRealtime() - } - cmTimer.start() - videoCallResponseListener?.minimizeVideoEvent(true) - } - - override fun onDisconnected(session: Session) { - Log.d(TAG, "onDisconnected: disconnected from session " + session.sessionId) -// mSession = null -// cmTimer.stop() -// disconnectSession() -// videoCallResponseListener?.minimizeVideoEvent(false) - } - - override fun onError(session: Session, opentokError: OpentokError) { - Log.d(TAG, "onError: Error (" + opentokError.message + ") in session " + session.sessionId) - - // videoCallResponseListener?.errorHandle("Error (" + opentokError.message + ") in session ") -// dialog?.dismiss() - } - - override fun onStreamReceived(session: Session, stream: Stream) { - Log.d(TAG, "onStreamReceived: New stream " + stream.streamId + " in session " + session.sessionId) - if (mSubscriber != null) { - isConnected = true - return - } - isConnected = true - subscribeToStream(stream) - if (mConnectedHandler != null && mConnectedRunnable != null) - mConnectedHandler!!.removeCallbacks(mConnectedRunnable!!) - videoCallPresenter.callChangeCallStatus( - ChangeCallStatusRequestModel( - 3, - sessionStatusModel!!.doctorId, - sessionStatusModel!!.generalid, - token, - sessionStatusModel!!.vcid - ) - ) - } - - override fun onStreamDropped(session: Session, stream: Stream) { - Log.d( - TAG, - "onStreamDropped: Stream " + stream.streamId + " dropped from session " + session.sessionId - ) - if (mSubscriber == null) { - return - } - if (mSubscriber!!.stream == stream) { - mSubscriberViewContainer.removeView(mSubscriber!!.view) - mSubscriber!!.destroy() - mSubscriber = null - } - //disconnectSession() - } - - override fun onStreamCreated(publisherKit: PublisherKit?, stream: Stream) { - Log.d(TAG, "onStreamCreated: Own stream " + stream.streamId + " created") - } - - override fun onStreamDestroyed(publisherKit: PublisherKit?, stream: Stream) { - Log.d(TAG, "onStreamDestroyed: Own stream " + stream.streamId + " destroyed") - } - - override fun onError(publisherKit: PublisherKit?, opentokError: OpentokError) { - Log.d(VideoCallFragment.TAG, "onError: Error (" + opentokError.message + ") in publisher") - // videoCallResponseListener?.errorHandle("Error (" + opentokError.message + ") in publisher") -// dialog?.dismiss() - } - - override fun onVideoDataReceived(subscriberKit: SubscriberKit?) { - mSubscriber!!.setStyle( - BaseVideoRenderer.STYLE_VIDEO_SCALE, - BaseVideoRenderer.STYLE_VIDEO_FILL - ) - (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(false) - mSubscriberViewContainer.addView(mSubscriber!!.view) -// switchToThumbnailCircle() - } - - fun switchToThumbnailCircle() { - thumbnail_container.postDelayed({ - val view = mSubscriber!!.view - if (view.parent != null) { - (view.parent as ViewGroup).removeView(view) - } - if (view is GLSurfaceView) { - view.setZOrderOnTop(true) - if (mSubscriber!!.renderer is DynamicVideoRenderer) { - (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(true) - thumbnail_container.addView(view) - } - } - switchToFullScreenView() - }, 4000) - } - - fun switchToFullScreenView() { - mSubscriberViewContainer.postDelayed({ - val view = mSubscriber!!.view - if (view.parent != null) { - (view.parent as ViewGroup).removeView(view) - } - if (view is GLSurfaceView) { - view.setZOrderOnTop(false) - if (mSubscriber!!.renderer is DynamicVideoRenderer) { - (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(false) - mSubscriberViewContainer.addView(view) - } - } - switchToThumbnailCircle() - }, 4000) - } - - override fun onVideoDisabled(subscriberKit: SubscriberKit?, s: String?) { - Log.d(VideoCallFragment.TAG, "onVideoDisabled: Error ($s)") - -// if (isCircle) { -// videoCallContainer.background = ContextCompat.getDrawable(requireContext(), R.drawable.circle_shape) -// mSubscriberViewContainer.background = ContextCompat.getDrawable(requireContext(), R.drawable.circle_shape) -// } else { -// videoCallContainer.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.text_color)) -// mSubscriberViewContainer.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.remoteBackground)) -// } - } - - override fun onVideoEnabled(subscriberKit: SubscriberKit?, s: String?) { - Log.d(VideoCallFragment.TAG, "onVideoEnabled: Error ($s)") - -// if (mSubscriber != null) { -// (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(isCircle) -// } - } - - override fun onVideoDisableWarning(subscriberKit: SubscriberKit?) {} - - override fun onVideoDisableWarningLifted(subscriberKit: SubscriberKit?) {} - - private fun subscribeToStream(stream: Stream) { - mSubscriber = Subscriber.Builder(requireContext(), stream) - .renderer(DynamicVideoRenderer(requireContext())) - .build() - mSubscriber!!.setVideoListener(this) - mSession!!.subscribe(mSubscriber) - } - - private fun disconnectSession() { - if (mSession == null) { - videoCallResponseListener?.onCallFinished(Activity.RESULT_CANCELED) -// requireActivity().setResult(Activity.RESULT_CANCELED) - dialog?.dismiss() - return - } - - if (mSubscriber != null) { - mSubscriberViewContainer.removeView(mSubscriber!!.view) - mSession!!.unsubscribe(mSubscriber) - mSubscriber!!.destroy() - mSubscriber = null - } - if (mPublisher != null) { - mPublisherViewContainer.removeView(mPublisher!!.view) - mSession!!.unpublish(mPublisher) - mPublisher!!.destroy() - mPublisher = null - } - mSession!!.disconnect() - countDownTimer?.cancel() - - videoCallPresenter.callChangeCallStatus( - ChangeCallStatusRequestModel( - 16, - sessionStatusModel!!.doctorId, - sessionStatusModel!!.generalid, - token, - sessionStatusModel!!.vcid - ) - ) -// if(isDismiss) -// dialog?.dismiss() -// else - onCallChangeCallStatusSuccessful() - } - - fun onCallChangeCallStatusSuccessful(){ - val returnIntent = Intent() - returnIntent.putExtra("CallEnd", sessionStatusModel) - videoCallResponseListener?.onCallFinished(Activity.RESULT_CANCELED, returnIntent) - dialog?.dismiss() - } - - override fun onCallSuccessful(sessionStatusModel: SessionStatusModel) { - if (sessionStatusModel.sessionStatus == 2 || sessionStatusModel.sessionStatus == 3) { - val returnIntent = Intent() - returnIntent.putExtra("sessionStatusNotRespond", sessionStatusModel) - videoCallResponseListener?.onCallFinished(Activity.RESULT_OK, returnIntent) -// requireActivity().setResult(Activity.RESULT_OK, returnIntent) - dialog?.dismiss() - } - } - - override fun onCallChangeCallStatusSuccessful(sessionStatusModel: SessionStatusModel?) {} - - override fun onFailure() {} - - private fun onSwitchCameraClicked(view: View?) { - if (mPublisher != null) { - isSwitchCameraClicked = !isSwitchCameraClicked - mPublisher!!.cycleCamera() - val res = if (isSwitchCameraClicked) R.drawable.camera_front else R.drawable.camera_back - mSwitchCameraBtn.setImageResource(res) - } - } - - fun onCallClicked() { - disconnectSession() - } - - private fun miniCircleDoubleTap() { - if (isCircle) { - onMiniCircleClicked() - } - } - - private fun onMiniCircleClicked() { - if (isCircle) { - dialog?.window?.setLayout( - 400, - 600 - ) - - } else { - dialog?.window?.setLayout( - 300, - 300 - ) - } - isCircle = !isCircle - - - if (mSubscriber != null) { - (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(isCircle) - } else { - if (isCircle) { - videoCallContainer.background = - ContextCompat.getDrawable(requireContext(), R.drawable.circle_shape) - mSubscriberViewContainer.background = - ContextCompat.getDrawable(requireContext(), R.drawable.circle_shape) - } else { - videoCallContainer.setBackgroundColor( - ContextCompat.getColor( - requireContext(), - R.color.text_color - ) - ) - mSubscriberViewContainer.setBackgroundColor( - ContextCompat.getColor( - requireContext(), - R.color.remoteBackground - ) - ) - } - } - - if (isCircle) { - controlPanel.visibility = View.GONE - layoutMini.visibility = View.GONE - } else { - controlPanel.visibility = View.VISIBLE - layoutMini.visibility = View.VISIBLE - } - - handleVideoViewHeight(isFullScreen) - } - - private fun onMinimizedClicked(view: View?) { - if (isFullScreen) { - dialog?.window?.setLayout( - 400, - 600 - ) - recordContainer.visibility = View.GONE - } else { - dialog?.window?.setLayout( - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.MATCH_PARENT - ) - if (isRecording) { - recordContainer.visibility = View.VISIBLE - } else { - recordContainer.visibility = View.GONE - } - } - isFullScreen = !isFullScreen - - val res = if (isFullScreen) R.drawable.reducing else R.drawable.expand - btnMinimize.setImageResource(res) - setViewsVisibility() - -// videoCallResponseListener?.minimizeVideoEvent(!isFullScreen) - } - - private fun setViewsVisibility() { - val btnMinimizeLayoutParam: ConstraintLayout.LayoutParams = - btnMinimize.layoutParams as ConstraintLayout.LayoutParams - val mCallBtnLayoutParam: ConstraintLayout.LayoutParams = - mCallBtn.layoutParams as ConstraintLayout.LayoutParams - - val iconSize: Int = requireContext().resources.getDimension(R.dimen.video_icon_size).toInt() - val iconSizeSmall: Int = - requireContext().resources.getDimension(R.dimen.video_icon_size_small).toInt() - - val localPreviewMargin: Int = - requireContext().resources.getDimension(R.dimen.local_preview_margin_top).toInt() - val localPreviewWidth: Int = - requireContext().resources.getDimension(R.dimen.local_preview_width).toInt() - val localPreviewHeight: Int = - requireContext().resources.getDimension(R.dimen.local_preview_height).toInt() -// val localPreviewIconSize: Int = context!!.resources.getDimension(R.dimen.local_back_icon_size).toInt() -// val localPreviewMarginSmall : Int = context!!.resources.getDimension(R.dimen.local_preview_margin_small).toInt() -// val localPreviewWidthSmall : Int = context!!.resources.getDimension(R.dimen.local_preview_width_small).toInt() -// val localPreviewHeightSmall : Int = context!!.resources.getDimension(R.dimen.local_preview_height_small).toInt() -// val localPreviewIconSmall: Int = context!!.resources.getDimension(R.dimen.local_back_icon_size_small).toInt() -// val localPreviewLayoutIconParam : FrameLayout.LayoutParams - val localPreviewLayoutParam: RelativeLayout.LayoutParams = - mPublisherViewContainer.layoutParams as RelativeLayout.LayoutParams - - val remotePreviewIconSize: Int = - requireContext().resources.getDimension(R.dimen.remote_back_icon_size).toInt() - val remotePreviewIconSizeSmall: Int = - requireContext().resources.getDimension(R.dimen.remote_back_icon_size_small).toInt() - val remotePreviewLayoutParam: FrameLayout.LayoutParams = - mSubscriberViewIcon.layoutParams as FrameLayout.LayoutParams - - if (isFullScreen) { - layoutName.visibility = View.VISIBLE - layoutMini.visibility = View.GONE - mCameraBtn.visibility = View.VISIBLE - mSwitchCameraBtn.visibility = View.VISIBLE -// mspeckerBtn.visibility = View.VISIBLE - mMicBtn.visibility = View.VISIBLE - - btnMinimizeLayoutParam.width = iconSize - btnMinimizeLayoutParam.height = iconSize - mCallBtnLayoutParam.width = iconSize - mCallBtnLayoutParam.height = iconSize -// localPreviewLayoutIconParam = FrameLayout.LayoutParams(localPreviewIconSize, localPreviewIconSize) -//// localPreviewLayoutParam = RelativeLayout.LayoutParams(localPreviewWidth, localPreviewHeight) - localPreviewLayoutParam.width = localPreviewWidth - localPreviewLayoutParam.height = localPreviewHeight - localPreviewLayoutParam.setMargins(0, localPreviewMargin, localPreviewMargin, 0) - if (mPublisher != null && mPublisher!!.view.parent == null) { - mPublisherViewContainer.addView(mPublisher!!.view) - } - mPublisherViewContainer.visibility = View.VISIBLE - -// remotePreviewLayoutParam = FrameLayout.LayoutParams(remotePreviewIconSize, remotePreviewIconSize) - remotePreviewLayoutParam.width = remotePreviewIconSize - remotePreviewLayoutParam.height = remotePreviewIconSize - } else { - layoutName.visibility = View.GONE - layoutMini.visibility = View.VISIBLE - mCameraBtn.visibility = View.GONE - mSwitchCameraBtn.visibility = View.GONE -// mspeckerBtn.visibility = View.GONE - mMicBtn.visibility = View.GONE -// mPublisherViewContainer.visibility = View.GONE -// mPublisherViewIcon.visibility = View.GONE - -// layoutParam = ConstraintLayout.LayoutParams(iconSizeSmall, iconSizeSmall) - btnMinimizeLayoutParam.width = iconSizeSmall - btnMinimizeLayoutParam.height = iconSizeSmall - mCallBtnLayoutParam.width = iconSizeSmall - mCallBtnLayoutParam.height = iconSizeSmall - - localPreviewLayoutParam.width = 0 - localPreviewLayoutParam.height = 0 - localPreviewLayoutParam.setMargins(0, localPreviewMargin / 2, localPreviewMargin / 2, 0) - - if (mPublisher != null) { - mPublisherViewContainer.removeView(mPublisher!!.view) - } - mPublisherViewContainer.visibility = View.GONE -// localPreviewLayoutIconParam = FrameLayout.LayoutParams(localPreviewIconSmall, localPreviewIconSmall) -//// localPreviewLayoutParam = RelativeLayout.LayoutParams(localPreviewWidthSmall, localPreviewHeightSmall) -// localPreviewLayoutParam.width = localPreviewWidthSmall -// localPreviewLayoutParam.height = localPreviewWidthSmall -// localPreviewLayoutParam.setMargins(0,localPreviewMarginSmall, localPreviewMarginSmall, 0) -// remotePreviewLayoutParam = FrameLayout.LayoutParams(remotePreviewIconSizeSmall, remotePreviewIconSizeSmall) - remotePreviewLayoutParam.width = remotePreviewIconSizeSmall - remotePreviewLayoutParam.height = remotePreviewIconSizeSmall - - if (isCircle) { - controlPanel.visibility = View.GONE - layoutMini.visibility = View.GONE - } else { - controlPanel.visibility = View.VISIBLE - layoutMini.visibility = View.VISIBLE - } - } - - mPublisherViewContainer.layoutParams = localPreviewLayoutParam -// mPublisherViewIcon.layoutParams = localPreviewLayoutIconParam - mSubscriberViewIcon.layoutParams = remotePreviewLayoutParam - - btnMinimize.layoutParams = btnMinimizeLayoutParam - mCallBtn.layoutParams = mCallBtnLayoutParam - - handleVideoViewHeight(isFullScreen) - } - - private fun handleVideoViewHeight(isFullScreen: Boolean) { - val layoutNameParam: ConstraintLayout.LayoutParams = - layoutName.layoutParams as ConstraintLayout.LayoutParams - val layoutMiniParam: ConstraintLayout.LayoutParams = - layoutMini.layoutParams as ConstraintLayout.LayoutParams - val controlPanelParam: ConstraintLayout.LayoutParams = - controlPanel.layoutParams as ConstraintLayout.LayoutParams - - val layoutNameHeight: Int = - requireContext().resources.getDimension(R.dimen.layout_name_height).toInt() - val layoutMiniHeight: Int = - requireContext().resources.getDimension(R.dimen.layout_mini_height).toInt() - val panelHeight: Int = requireContext().resources.getDimension(R.dimen.layout_panel_height).toInt() - val panelHeightSmall: Int = - requireContext().resources.getDimension(R.dimen.layout_panel_height_small).toInt() - - val panelPadding: Int = - requireContext().resources.getDimension(R.dimen.padding_space_big).toInt() - val panelPaddingMedium: Int = - requireContext().resources.getDimension(R.dimen.padding_space_medium).toInt() - - val temp = getStatusBarHeight() / 2 - - val screenWidth: Float - val screenHeight: Float - - if (isFullScreen) { - screenWidth = ViewsUtil.getWidthDp(requireContext()) - screenHeight = ViewsUtil.getHeightDp(requireContext()) - - layoutNameParam.height = layoutNameHeight + temp - layoutMiniParam.height = 0 - controlPanelParam.height = panelHeight + temp - - controlPanel.setPadding(panelPadding, panelPadding, panelPadding, panelPadding) - } else { - - if (isCircle) { - screenWidth = 300F - screenHeight = 300F - - layoutNameParam.height = 0 - layoutMiniParam.height = 0 - controlPanelParam.height = 0 - } else { - screenWidth = 400F - screenHeight = 600F - - layoutNameParam.height = 0 - layoutMiniParam.height = layoutMiniHeight - controlPanelParam.height = panelHeightSmall - } - - controlPanel.setPadding( - panelPaddingMedium, - panelPaddingMedium, - panelPaddingMedium, - panelPaddingMedium - ) - } - - layoutName.layoutParams = layoutNameParam - layoutMini.layoutParams = layoutMiniParam - controlPanel.layoutParams = controlPanelParam - - var videoStreamHeight = - screenHeight - controlPanelParam.height - layoutNameParam.height - layoutMiniParam.height - - if (isFullScreen) { -// videoStreamHeight -= getStatusBarHeight() / 2 - } - - val callLayoutParam: ConstraintLayout.LayoutParams = - activity_clingo_video_call.layoutParams as ConstraintLayout.LayoutParams - - callLayoutParam.height = videoStreamHeight.toInt() - callLayoutParam.width = screenWidth.toInt() - } - - private fun onCameraClicked(view: View?) { - if (mPublisher != null) { - isCameraClicked = !isCameraClicked - mPublisher!!.publishVideo = !isCameraClicked - val res = if (isCameraClicked) R.drawable.video_disabled else R.drawable.video_enabled - mCameraBtn.setImageResource(res) - -// if (!isCameraClicked) { -// videoCallContainer.background = ContextCompat.getDrawable(requireContext(), R.drawable.circle_shape) -// mSubscriberViewContainer.background = ContextCompat.getDrawable(requireContext(), R.drawable.circle_shape) -// } else { -// videoCallContainer.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.text_color)) -// mSubscriberViewContainer.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.remoteBackground)) -// } - } - } - - private fun onMicClicked(view: View?) { - if (mPublisher != null) { - isMicClicked = !isMicClicked - mPublisher!!.publishAudio = !isMicClicked - val res = if (isMicClicked) R.drawable.mic_disabled else R.drawable.mic_enabled - mMicBtn!!.setImageResource(res) - } - } - - private fun onSpeckerClicked(view: View?) { - if (mSubscriber != null) { - isSpeckerClicked = !isSpeckerClicked - mSubscriber!!.subscribeToAudio = !isSpeckerClicked - val res = if (isSpeckerClicked) R.drawable.audio_disabled else R.drawable.audio_enabled - mspeckerBtn.setImageResource(res) - } - } - - @SuppressLint("ClickableViewAccessibility") - private fun handleDragDialog() { - mWindowManager = requireActivity().getSystemService(Context.WINDOW_SERVICE) as WindowManager - getWindowManagerDefaultDisplay() - - videoCallContainer.setOnTouchListener(dragListener) - mSubscriberViewContainer.setOnTouchListener(dragListener) - } - - @SuppressLint("ClickableViewAccessibility") - private val dragListener: View.OnTouchListener = View.OnTouchListener { _, event -> - mDetector.onTouchEvent(event) - - //Get Floating widget view params - val layoutParams: WindowManager.LayoutParams = dialog!!.window!!.attributes - //get the touch location coordinates - val x_cord = event.rawX.toInt() - val y_cord = event.rawY.toInt() - val x_cord_Destination: Int - var y_cord_Destination: Int - - when (event.action) { - MotionEvent.ACTION_DOWN -> { - x_init_cord = x_cord - y_init_cord = y_cord - - //remember the initial position. - x_init_margin = layoutParams.x - y_init_margin = layoutParams.y - } - MotionEvent.ACTION_UP -> { - //Get the difference between initial coordinate and current coordinate - val x_diff: Int = x_cord - x_init_cord - val y_diff: Int = y_cord - y_init_cord - - y_cord_Destination = y_init_margin + y_diff - val barHeight: Int = getStatusBarHeight() - if (y_cord_Destination < 0) { -// y_cord_Destination = 0 -// y_cord_Destination = -// -(szWindow.y - (videoCallContainer.height /*+ barHeight*/)) - y_cord_Destination = -(szWindow.y / 2) - } else if (y_cord_Destination + (videoCallContainer.height + barHeight) > szWindow.y) { -// y_cord_Destination = szWindow.y - (videoCallContainer.height + barHeight) - y_cord_Destination = (szWindow.y / 2) - } - layoutParams.y = y_cord_Destination - - //reset position if user drags the floating view - resetPosition(x_cord) - } - MotionEvent.ACTION_MOVE -> { - val x_diff_move: Int = x_cord - x_init_cord - val y_diff_move: Int = y_cord - y_init_cord - x_cord_Destination = x_init_margin + x_diff_move - y_cord_Destination = y_init_margin + y_diff_move - - layoutParams.x = x_cord_Destination - layoutParams.y = y_cord_Destination - - dialog!!.window!!.attributes = layoutParams - } - } - true - } - - private fun showControlPanelTemporarily() { - if (!isCircle) { - controlPanel.visibility = View.VISIBLE - mVolHandler!!.removeCallbacks(mVolRunnable!!) - mVolHandler!!.postDelayed(mVolRunnable!!, (5 * 1000).toLong()) - } - } - - /* Reset position of Floating Widget view on dragging */ - private fun resetPosition(x_cord_now: Int) { - if (x_cord_now <= szWindow.x / 2) { - isLeft = true - moveToLeft(x_cord_now) - } else { - isLeft = false - moveToRight(x_cord_now) - } - } - - /* Method to move the Floating widget view to Left */ - private fun moveToLeft(current_x_cord: Int) { - - var mParams: WindowManager.LayoutParams = dialog!!.window!!.attributes - - mParams.x = - (szWindow.x - current_x_cord * current_x_cord - videoCallContainer.width).toInt() - - dialog!!.window!!.attributes = mParams - val x = szWindow.x - current_x_cord - object : CountDownTimer(500, 5) { - //get params of Floating Widget view - var mParams: WindowManager.LayoutParams = dialog!!.window!!.attributes - override fun onTick(t: Long) { - val step = (500 - t) / 5 - // mParams.x = 0 - (current_x_cord * current_x_cord * step).toInt() - mParams.x = - (szWindow.x - current_x_cord * current_x_cord * step - videoCallContainer.width).toInt() - - dialog?.window?.attributes = mParams - } - - override fun onFinish() { - mParams.x = -(szWindow.x - videoCallContainer.width) - - dialog?.window!!.attributes = mParams - } - }.start() - } - - /* Method to move the Floating widget view to Right */ - private fun moveToRight(current_x_cord: Int) { -// var mParams : WindowManager.LayoutParams = dialog!!.window!!.attributes -// mParams.x = -// (szWindow.x + current_x_cord * current_x_cord - videoCallContainer.width).toInt() -// -// dialog!!.window!!.attributes = mParams - object : CountDownTimer(500, 5) { - //get params of Floating Widget view - var mParams: WindowManager.LayoutParams = dialog!!.window!!.attributes - override fun onTick(t: Long) { - val step = (500 - t) / 5 - mParams.x = - (szWindow.x + current_x_cord * current_x_cord * step - videoCallContainer.width).toInt() - - dialog!!.window!!.attributes = mParams - } - - override fun onFinish() { - mParams.x = szWindow.x - videoCallContainer.width - - dialog?.window!!.attributes = mParams - } - }.start() - } - - private fun getWindowManagerDefaultDisplay() { - mWindowManager.getDefaultDisplay() - .getSize(szWindow) - } - - /* return status bar height on basis of device display metrics */ - private fun getStatusBarHeight(): Int { - return ceil( - (25 * requireActivity().applicationContext.resources.displayMetrics.density).toDouble() - ).toInt() - } - - private class MyGestureListener( - val onTabCall: () -> Unit, - val miniCircleDoubleTap: () -> Unit - ) : GestureDetector.SimpleOnGestureListener() { - - override fun onSingleTapConfirmed(event: MotionEvent): Boolean { -// onTabCall() - return true - } - -// override fun onDoubleTap(e: MotionEvent?): Boolean { -// miniCircleDoubleTap() -// return super.onDoubleTap(e) -// } - - } - - companion object { - @JvmStatic - fun newInstance(args: Bundle) = - VideoCallFragment().apply { - arguments = args - } - - private val TAG = VideoCallFragment::class.java.simpleName - - private const val RC_SETTINGS_SCREEN_PERM = 123 - private const val RC_VIDEO_APP_PERM = 124 - - } -} \ No newline at end of file +//// private var isFullScreen: Boolean = true +//// private var isCircle: Boolean = false +//// private var x_init_cord = 0 +//// private var y_init_cord: Int = 0 +//// private var x_init_margin: Int = 0 +//// private var y_init_margin: Int = 0 +//// private val szWindow: Point = Point() +//// private lateinit var mWindowManager: WindowManager +//// private var isLeft = true +//// +//// private lateinit var videoCallPresenter: VideoCallPresenter +//// +//// private var mSession: Session? = null +//// private var mPublisher: Publisher? = null +//// private var mSubscriber: Subscriber? = null +//// +//// private var mVolHandler: Handler? = null +//// private var mConnectedHandler: Handler? = null +//// private var mVolRunnable: Runnable? = null +//// private var mConnectedRunnable: Runnable? = null +//// +//// private lateinit var recordContainer: FrameLayout +//// private lateinit var thumbnail_container: FrameLayout +//// private lateinit var activity_clingo_video_call: RelativeLayout +//// private lateinit var mPublisherViewContainer: FrameLayout +//// private lateinit var mPublisherViewIcon: View +//// private lateinit var mSubscriberViewContainer: FrameLayout +//// private lateinit var mSubscriberViewIcon: ImageView +//// private lateinit var controlPanel: ConstraintLayout +//// +//// private var apiKey: String? = null +//// private var sessionId: String? = null +//// private var token: String? = null +//// private var appLang: String? = null +//// private var baseUrl: String? = null +//// private var isRecording: Boolean = true +//// +//// private var isSwitchCameraClicked = false +//// private var isCameraClicked = false +//// private var isSpeckerClicked = false +//// private var isMicClicked = false +//// +//// private lateinit var parentView: View +//// private lateinit var videoCallContainer: ConstraintLayout +//// private lateinit var layoutName: RelativeLayout +//// private lateinit var layoutMini: RelativeLayout +//// private lateinit var icMini: ImageButton +//// private lateinit var mCallBtn: ImageView +//// private lateinit var btnMinimize: ImageView +//// private lateinit var mCameraBtn: ImageView +//// private lateinit var mSwitchCameraBtn: ImageView +//// private lateinit var mspeckerBtn: ImageView +//// private lateinit var mMicBtn: ImageView +//// private lateinit var patientName: TextView +//// private lateinit var cmTimer: Chronometer +//// +//// private var elapsedTime: Long = 0 +//// private var resume = false +//// +//// private val progressBar: ProgressBar? = null +//// private val countDownTimer: CountDownTimer? = null +//// private val progressBarTextView: TextView? = null +//// private val +//// progressBarLayout: RelativeLayout? = null +//// +//// private var isConnected = false +//// +//// private var sessionStatusModel: GetSessionStatusModel? = null +//// private var videoCallResponseListener: VideoCallResponseListener? = null +//// private lateinit var mDetector: GestureDetectorCompat +//// +//// override fun onCreate(savedInstanceState: Bundle?) { +//// requireActivity().setTheme(R.style.AppTheme) +//// super.onCreate(savedInstanceState) +//// } +//// +//// override fun onStart() { +//// super.onStart() +//// +////// val params: ViewGroup.LayoutParams = dialog!!.window!!.attributes +////// params.width = WindowManager.LayoutParams.MATCH_PARENT +////// params.height = WindowManager.LayoutParams.MATCH_PARENT +////// dialog!!.window!!.attributes = params as WindowManager.LayoutParams +//// +//// dialog?.window?.setLayout( +//// LinearLayout.LayoutParams.MATCH_PARENT, +//// LinearLayout.LayoutParams.MATCH_PARENT +//// ) +////// val parentLayoutParam: FrameLayout.LayoutParams = /*parentView.layoutParams as*/ FrameLayout.LayoutParams( +////// LinearLayout.LayoutParams.MATCH_PARENT, +////// LinearLayout.LayoutParams.MATCH_PARENT +////// ) +////// parentView.layoutParams = parentLayoutParam +//// } +//// +//// override fun getTheme(): Int { +//// return R.style.dialogTheme +//// } +//// +//// @SuppressLint("UseRequireInsteadOfGet") +//// override fun onCreateDialog(@Nullable savedInstanceState: Bundle?): Dialog {// FullScreenVideoTheme +//// val layoutInflater = requireActivity().layoutInflater +//// this.parentView = onCreateView(layoutInflater, null) +//// +//// val alertDialogBuilder: AlertDialog.Builder = +//// AlertDialog.Builder(requireContext(), R.style.dialogTheme) +////// .setTitle(android.R.string.select_a_color) +//// .setView(this.parentView) +////// .setPositiveButton(android.R.string.ok, { dialogInterface, i -> }) +//// alertDialogBuilder.setOnKeyListener { _, keyCode, keyEvent -> +//// // getAction to make sure this doesn't double fire +//// if (keyCode == KeyEvent.KEYCODE_BACK && keyEvent.action == KeyEvent.ACTION_UP) { +//// videoCallResponseListener?.onBackHandle() +//// false // Capture onKey +//// } else true +//// // Don't capture +//// } +//// return alertDialogBuilder.create() +/////* +//// +//// val dialog: Dialog = super.onCreateDialog(savedInstanceState) +//// // Add back button listener +//// dialog.setOnKeyListener { _, keyCode, keyEvent -> +//// // getAction to make sure this doesn't double fire +//// if (keyCode == KeyEvent.KEYCODE_BACK && keyEvent.action == KeyEvent.ACTION_UP) { +//// videoCallResponseListener?.onBackHandle() +//// false // Capture onKey +//// } else true +//// // Don't capture +//// } +//// +//// return dialog +////*/ +//// } +//// +//// override fun onViewCreated(view: View, savedInstanceState: Bundle?) { +//// super.onViewCreated(view, savedInstanceState) +//// +//// // This is done in a post() since the dialog must be drawn before locating. +//// requireView().post { +//// val dialogWindow = dialog!!.window +//// +//// if (dialog != null && dialogWindow != null) { +//// dialogWindow.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)); +//// } +//// +//// // Make the dialog possible to be outside touch +//// dialogWindow!!.setFlags( +//// WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, +//// WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL +//// ) +//// dialogWindow.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND) +//// requireView().invalidate() +//// } +//// } +//// +//// +//// fun setCallListener(videoCallResponseListener: VideoCallResponseListener) { +//// this.videoCallResponseListener = videoCallResponseListener +//// } +//// +//// private fun onCreateView( +//// inflater: LayoutInflater, container: ViewGroup? +//// ): View { +//// val view = inflater.inflate(R.layout.activity_video_call, container, false) +//// +////// val parentViewLayoutParam: ConstraintLayout.LayoutParams = ConstraintLayout.LayoutParams( +////// ConstraintLayout.LayoutParams.MATCH_PARENT, +////// ConstraintLayout.LayoutParams.MATCH_PARENT +////// ) +////// parentView.layoutParams = parentViewLayoutParam +//// // Objects.requireNonNull(requireActivity().actionBar)!!.hide() +//// arguments?.run { +//// apiKey = getString("apiKey") +//// sessionId = getString("sessionId") +//// token = getString("token") +//// appLang = getString("appLang") +//// baseUrl = getString("baseUrl") +//// sessionStatusModel = getParcelable("sessionStatusModel") +//// if (sessionStatusModel != null) +//// isRecording = sessionStatusModel!!.isRecording +//// } +//// initUI(view) +//// requestPermissions() +//// +//// handleDragDialog() +//// mDetector = GestureDetectorCompat( +//// requireContext(), +//// MyGestureListener({ showControlPanelTemporarily() }, { miniCircleDoubleTap() }) +//// ) +//// +//// return view +//// } +//// +//// override fun onCreateView( +//// inflater: LayoutInflater, container: ViewGroup?, +//// savedInstanceState: Bundle? +//// ): View { +//// return this.parentView +//// } +//// +//// override fun onPause() { +//// super.onPause() +//// if (mSession == null) { +//// return +//// } +//// mSession!!.onPause() +//// if (requireActivity().isFinishing) { +//// disconnectSession() +//// } +//// } +//// +//// override fun onResume() { +//// super.onResume() +//// if (mSession == null) { +//// return +//// } +//// mSession!!.onResume() +//// } +//// +//// override fun onDestroy() { +//// disconnectSession() +//// cmTimer.stop() +//// super.onDestroy() +//// } +//// +//// @SuppressLint("ClickableViewAccessibility") +//// private fun initUI(view: View) { +//// videoCallContainer = view.findViewById(R.id.video_call_ll) +//// +//// layoutName = view.findViewById(R.id.layout_name) +//// layoutMini = view.findViewById(R.id.layout_mini) +//// icMini = view.findViewById(R.id.ic_mini) +//// recordContainer = view.findViewById(R.id.record_container) +//// activity_clingo_video_call = view.findViewById(R.id.activity_clingo_video_call) +//// +//// thumbnail_container = view.findViewById(R.id.thumbnail_container) +//// mPublisherViewContainer = view.findViewById(R.id.local_video_view_container) +//// mPublisherViewIcon = view.findViewById(R.id.local_video_view_icon) +//// mSubscriberViewIcon = view.findViewById(R.id.remote_video_view_icon) +//// mSubscriberViewContainer = view.findViewById(R.id.remote_video_view_container) +//// +//// patientName = view.findViewById(R.id.patient_name) +//// patientName.text = sessionStatusModel!!.patientName +//// +//// if (isRecording) { +//// recordContainer.visibility = View.VISIBLE +//// } else { +//// recordContainer.visibility = View.GONE +//// } +//// +////// cmTimer = view.findViewById(R.id.cmTimer) +//// cmTimer.format = "mm:ss" +//// cmTimer.onChronometerTickListener = +//// Chronometer.OnChronometerTickListener { arg0: Chronometer? -> +////// val f: NumberFormat = DecimalFormat("00") +////// f.format(minutes) +//// val minutes: Long +//// val seconds: Long +//// if (!resume) { +//// minutes = (SystemClock.elapsedRealtime() - cmTimer.base) / 1000 / 60 +//// seconds = (SystemClock.elapsedRealtime() - cmTimer.base) / 1000 % 60 +//// elapsedTime = SystemClock.elapsedRealtime() +//// } else { +//// minutes = (elapsedTime - cmTimer.base) / 1000 / 60 +//// seconds = (elapsedTime - cmTimer.base) / 1000 % 60 +//// elapsedTime += 1000 +//// } +//// val format = "%1$02d:%2$02d" // two digits +//// +//// arg0?.text = String.format(format, minutes, seconds) +//// Log.d(TAG, "onChronometerTick: $minutes : $seconds") +//// } +//// +//// icMini.setOnClickListener { +//// onMiniCircleClicked() +//// } +//// +//// controlPanel = view.findViewById(R.id.control_panel) +//// videoCallPresenter = VideoCallPresenterImpl(this, baseUrl) +//// mCallBtn = view.findViewById(R.id.btn_call) +//// mCallBtn.setOnClickListener { +//// onCallClicked() +//// } +//// btnMinimize = view.findViewById(R.id.btn_minimize) +//// btnMinimize.setOnClickListener { +//// onMinimizedClicked(it) +//// } +//// mCameraBtn = view.findViewById(R.id.btn_camera) +//// mCameraBtn.setOnClickListener { +//// onCameraClicked(it) +//// } +//// mSwitchCameraBtn = view.findViewById(R.id.btn_switch_camera) +//// mSwitchCameraBtn.setOnClickListener { +//// onSwitchCameraClicked(it) +//// } +//// mspeckerBtn = view.findViewById(R.id.btn_specker) +//// mspeckerBtn.setOnClickListener { +//// onSpeckerClicked(it) +//// } +//// mMicBtn = view.findViewById(R.id.btn_mic) +//// mMicBtn.setOnClickListener { +//// onMicClicked(it) +//// } +//// // progressBarLayout=findViewById(R.id.progressBar); +//// // progressBar=findViewById(R.id.progress_bar); +////// progressBarTextView=findViewById(R.id.progress_bar_text); +////// progressBar.setVisibility(View.GONE); +////// hiddenButtons() +//// checkClientConnected() +//// handleVideoViewHeight(true) +//// +//// +//// +//// if (appLang == "ar") { +//// progressBarLayout!!.layoutDirection = View.LAYOUT_DIRECTION_RTL +//// } +//// } +//// +//// private fun checkClientConnected() { +//// mConnectedHandler = Handler((Looper.getMainLooper())) +//// mConnectedRunnable = Runnable { +//// if (!isConnected) { +//// videoCallPresenter.callClintConnected(sessionStatusModel) +//// } +//// } +//// mConnectedHandler!!.postDelayed(mConnectedRunnable!!, (55 * 1000).toLong()) +//// } +//// +//// private fun hiddenButtons() { +//// mVolHandler = Handler() +//// mVolRunnable = Runnable { controlPanel.visibility = View.GONE } +//// mVolHandler!!.postDelayed(mVolRunnable!!, (5 * 1000).toLong()) +//// } +//// +//// override fun onRequestPermissionsResult( +//// requestCode: Int, +//// permissions: Array, +//// grantResults: IntArray +//// ) { +//// super.onRequestPermissionsResult(requestCode, permissions, grantResults) +////// EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this) +//// } +//// +////// override fun onPermissionsGranted(requestCode: Int, perms: List) { +////// Log.d(TAG, "onPermissionsGranted:" + requestCode + ":" + perms.size) +////// } +////// +////// override fun onPermissionsDenied(requestCode: Int, perms: List) { +////// Log.d(TAG, "onPermissionsDenied:" + requestCode + ":" + perms.size) +////// if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) { +////// AppSettingsDialog.Builder(this) +////// .setTitle(getString(R.string.title_settings_dialog)) +////// .setRationale(getString(R.string.rationale_ask_again)) +////// .setPositiveButton(getString(R.string.setting)) +////// .setNegativeButton(getString(R.string.cancel)) +////// .setRequestCode(RC_SETTINGS_SCREEN_PERM) +////// .build() +////// .show() +////// } +////// } +//// +////// @AfterPermissionGranted(RC_VIDEO_APP_PERM) +//// private fun requestPermissions() { +////// val perms = arrayOf( +////// Manifest.permission.INTERNET, +////// Manifest.permission.CAMERA, +////// Manifest.permission.RECORD_AUDIO, +////// Manifest.permission.MODIFY_AUDIO_SETTINGS, +////// Manifest.permission.CALL_PHONE +////// ) +////// if (EasyPermissions.hasPermissions(requireContext(), *perms)) { +////// try { +////// mSession = Session.Builder(context, apiKey, sessionId).build() +////// mSession!!.setSessionListener(this) +////// mSession!!.connect(token) +////// +////// mSession!!.setReconnectionListener(object :Session.ReconnectionListener{ +////// override fun onReconnecting(p0: Session?) { +////// +////// } +////// +////// override fun onReconnected(session: Session?) { +////// session?.connect(token) +////// } +////// +////// +////// }) +////// +////// +////// } catch (e: Exception) { +////// e.printStackTrace() +////// } +////// } else { +////// EasyPermissions.requestPermissions( +////// this, +////// getString(R.string.remaining_ar), +////// RC_VIDEO_APP_PERM, +////// *perms +////// ) +////// } +//// } +//// +//// override fun onConnected(session: Session?) { +//// Log.i(TAG, "Session Connected") +//// mPublisher = Publisher.Builder(requireContext()) +////// .name("publisher") +////// .renderer(ThumbnailCircleVideoRenderer(requireContext())) +//// .build() +//// mPublisher!!.setPublisherListener(this) +//// if (mPublisher!!.view is GLSurfaceView) { +//// (mPublisher!!.view as GLSurfaceView).setZOrderOnTop(true) +//// } +//// +//// mPublisherViewContainer.addView(mPublisher!!.view) +//// +//// mSession!!.publish(mPublisher) +//// +//// if (!resume) { +//// cmTimer.base = SystemClock.elapsedRealtime() +//// } +//// cmTimer.start() +//// videoCallResponseListener?.minimizeVideoEvent(true) +//// } +//// +//// override fun onDisconnected(session: Session) { +//// Log.d(TAG, "onDisconnected: disconnected from session " + session.sessionId) +////// mSession = null +////// cmTimer.stop() +////// disconnectSession() +////// videoCallResponseListener?.minimizeVideoEvent(false) +//// } +//// +//// override fun onError(session: Session, opentokError: OpentokError) { +//// Log.d(TAG, "onError: Error (" + opentokError.message + ") in session " + session.sessionId) +//// +//// // videoCallResponseListener?.errorHandle("Error (" + opentokError.message + ") in session ") +////// dialog?.dismiss() +//// } +//// +//// override fun onStreamReceived(session: Session, stream: Stream) { +//// Log.d(TAG, "onStreamReceived: New stream " + stream.streamId + " in session " + session.sessionId) +//// if (mSubscriber != null) { +//// isConnected = true +//// return +//// } +//// isConnected = true +//// subscribeToStream(stream) +//// if (mConnectedHandler != null && mConnectedRunnable != null) +//// mConnectedHandler!!.removeCallbacks(mConnectedRunnable!!) +//// videoCallPresenter.callChangeCallStatus( +//// ChangeCallStatusRequestModel( +//// 3, +//// sessionStatusModel!!.doctorId, +//// sessionStatusModel!!.generalid, +//// token, +//// sessionStatusModel!!.vcid +//// ) +//// ) +//// } +//// +//// override fun onStreamDropped(session: Session, stream: Stream) { +//// Log.d( +//// TAG, +//// "onStreamDropped: Stream " + stream.streamId + " dropped from session " + session.sessionId +//// ) +//// if (mSubscriber == null) { +//// return +//// } +//// if (mSubscriber!!.stream == stream) { +//// mSubscriberViewContainer.removeView(mSubscriber!!.view) +//// mSubscriber!!.destroy() +//// mSubscriber = null +//// } +//// //disconnectSession() +//// } +//// +//// override fun onStreamCreated(publisherKit: PublisherKit?, stream: Stream) { +//// Log.d(TAG, "onStreamCreated: Own stream " + stream.streamId + " created") +//// } +//// +//// override fun onStreamDestroyed(publisherKit: PublisherKit?, stream: Stream) { +//// Log.d(TAG, "onStreamDestroyed: Own stream " + stream.streamId + " destroyed") +//// } +//// +//// override fun onError(publisherKit: PublisherKit?, opentokError: OpentokError) { +//// Log.d(VideoCallFragment.TAG, "onError: Error (" + opentokError.message + ") in publisher") +//// // videoCallResponseListener?.errorHandle("Error (" + opentokError.message + ") in publisher") +////// dialog?.dismiss() +//// } +//// +//// override fun onVideoDataReceived(subscriberKit: SubscriberKit?) { +//// mSubscriber!!.setStyle( +//// BaseVideoRenderer.STYLE_VIDEO_SCALE, +//// BaseVideoRenderer.STYLE_VIDEO_FILL +//// ) +//// (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(false) +//// mSubscriberViewContainer.addView(mSubscriber!!.view) +////// switchToThumbnailCircle() +//// } +//// +//// fun switchToThumbnailCircle() { +//// thumbnail_container.postDelayed({ +//// val view = mSubscriber!!.view +//// if (view.parent != null) { +//// (view.parent as ViewGroup).removeView(view) +//// } +//// if (view is GLSurfaceView) { +//// view.setZOrderOnTop(true) +//// if (mSubscriber!!.renderer is DynamicVideoRenderer) { +//// (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(true) +//// thumbnail_container.addView(view) +//// } +//// } +//// switchToFullScreenView() +//// }, 4000) +//// } +//// +//// fun switchToFullScreenView() { +//// mSubscriberViewContainer.postDelayed({ +//// val view = mSubscriber!!.view +//// if (view.parent != null) { +//// (view.parent as ViewGroup).removeView(view) +//// } +//// if (view is GLSurfaceView) { +//// view.setZOrderOnTop(false) +//// if (mSubscriber!!.renderer is DynamicVideoRenderer) { +//// (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(false) +//// mSubscriberViewContainer.addView(view) +//// } +//// } +//// switchToThumbnailCircle() +//// }, 4000) +//// } +//// +//// override fun onVideoDisabled(subscriberKit: SubscriberKit?, s: String?) { +//// Log.d(VideoCallFragment.TAG, "onVideoDisabled: Error ($s)") +//// +////// if (isCircle) { +////// videoCallContainer.background = ContextCompat.getDrawable(requireContext(), R.drawable.circle_shape) +////// mSubscriberViewContainer.background = ContextCompat.getDrawable(requireContext(), R.drawable.circle_shape) +////// } else { +////// videoCallContainer.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.text_color)) +////// mSubscriberViewContainer.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.remoteBackground)) +////// } +//// } +//// +//// override fun onVideoEnabled(subscriberKit: SubscriberKit?, s: String?) { +//// Log.d(VideoCallFragment.TAG, "onVideoEnabled: Error ($s)") +//// +////// if (mSubscriber != null) { +////// (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(isCircle) +////// } +//// } +//// +//// override fun onVideoDisableWarning(subscriberKit: SubscriberKit?) {} +//// +//// override fun onVideoDisableWarningLifted(subscriberKit: SubscriberKit?) {} +//// +//// private fun subscribeToStream(stream: Stream) { +//// mSubscriber = Subscriber.Builder(requireContext(), stream) +//// .renderer(DynamicVideoRenderer(requireContext())) +//// .build() +//// mSubscriber!!.setVideoListener(this) +//// mSession!!.subscribe(mSubscriber) +//// } +//// +//// private fun disconnectSession() { +//// if (mSession == null) { +//// videoCallResponseListener?.onCallFinished(Activity.RESULT_CANCELED) +////// requireActivity().setResult(Activity.RESULT_CANCELED) +//// dialog?.dismiss() +//// return +//// } +//// +//// if (mSubscriber != null) { +//// mSubscriberViewContainer.removeView(mSubscriber!!.view) +//// mSession!!.unsubscribe(mSubscriber) +//// mSubscriber!!.destroy() +//// mSubscriber = null +//// } +//// if (mPublisher != null) { +//// mPublisherViewContainer.removeView(mPublisher!!.view) +//// mSession!!.unpublish(mPublisher) +//// mPublisher!!.destroy() +//// mPublisher = null +//// } +//// mSession!!.disconnect() +//// countDownTimer?.cancel() +//// +//// videoCallPresenter.callChangeCallStatus( +//// ChangeCallStatusRequestModel( +//// 16, +//// sessionStatusModel!!.doctorId, +//// sessionStatusModel!!.generalid, +//// token, +//// sessionStatusModel!!.vcid +//// ) +//// ) +////// if(isDismiss) +////// dialog?.dismiss() +////// else +//// onCallChangeCallStatusSuccessful() +//// } +//// +//// fun onCallChangeCallStatusSuccessful(){ +//// val returnIntent = Intent() +//// returnIntent.putExtra("CallEnd", sessionStatusModel) +//// videoCallResponseListener?.onCallFinished(Activity.RESULT_CANCELED, returnIntent) +//// dialog?.dismiss() +//// } +//// +//// override fun onCallSuccessful(sessionStatusModel: SessionStatusModel) { +//// if (sessionStatusModel.sessionStatus == 2 || sessionStatusModel.sessionStatus == 3) { +//// val returnIntent = Intent() +//// returnIntent.putExtra("sessionStatusNotRespond", sessionStatusModel) +//// videoCallResponseListener?.onCallFinished(Activity.RESULT_OK, returnIntent) +////// requireActivity().setResult(Activity.RESULT_OK, returnIntent) +//// dialog?.dismiss() +//// } +//// } +//// +//// override fun onCallChangeCallStatusSuccessful(sessionStatusModel: SessionStatusModel?) {} +//// +//// override fun onFailure() {} +//// +//// private fun onSwitchCameraClicked(view: View?) { +//// if (mPublisher != null) { +//// isSwitchCameraClicked = !isSwitchCameraClicked +//// mPublisher!!.cycleCamera() +//// val res = if (isSwitchCameraClicked) R.drawable.camera_front else R.drawable.camera_back +//// mSwitchCameraBtn.setImageResource(res) +//// } +//// } +//// +//// fun onCallClicked() { +//// disconnectSession() +//// } +//// +//// private fun miniCircleDoubleTap() { +//// if (isCircle) { +//// onMiniCircleClicked() +//// } +//// } +//// +//// private fun onMiniCircleClicked() { +//// if (isCircle) { +//// dialog?.window?.setLayout( +//// 400, +//// 600 +//// ) +//// +//// } else { +//// dialog?.window?.setLayout( +//// 300, +//// 300 +//// ) +//// } +//// isCircle = !isCircle +//// +//// +//// if (mSubscriber != null) { +//// (mSubscriber!!.renderer as DynamicVideoRenderer).enableThumbnailCircle(isCircle) +//// } else { +//// if (isCircle) { +//// videoCallContainer.background = +//// ContextCompat.getDrawable(requireContext(), R.drawable.circle_shape) +//// mSubscriberViewContainer.background = +//// ContextCompat.getDrawable(requireContext(), R.drawable.circle_shape) +//// } else { +//// videoCallContainer.setBackgroundColor( +//// ContextCompat.getColor( +//// requireContext(), +//// R.color.text_color +//// ) +//// ) +//// mSubscriberViewContainer.setBackgroundColor( +//// ContextCompat.getColor( +//// requireContext(), +//// R.color.remoteBackground +//// ) +//// ) +//// } +//// } +//// +//// if (isCircle) { +//// controlPanel.visibility = View.GONE +//// layoutMini.visibility = View.GONE +//// } else { +//// controlPanel.visibility = View.VISIBLE +//// layoutMini.visibility = View.VISIBLE +//// } +//// +//// handleVideoViewHeight(isFullScreen) +//// } +//// +//// private fun onMinimizedClicked(view: View?) { +//// if (isFullScreen) { +//// dialog?.window?.setLayout( +//// 400, +//// 600 +//// ) +//// recordContainer.visibility = View.GONE +//// } else { +//// dialog?.window?.setLayout( +//// LinearLayout.LayoutParams.MATCH_PARENT, +//// LinearLayout.LayoutParams.MATCH_PARENT +//// ) +//// if (isRecording) { +//// recordContainer.visibility = View.VISIBLE +//// } else { +//// recordContainer.visibility = View.GONE +//// } +//// } +//// isFullScreen = !isFullScreen +//// +//// val res = if (isFullScreen) R.drawable.reducing else R.drawable.expand +//// btnMinimize.setImageResource(res) +//// setViewsVisibility() +//// +////// videoCallResponseListener?.minimizeVideoEvent(!isFullScreen) +//// } +//// +//// private fun setViewsVisibility() { +//// val btnMinimizeLayoutParam: ConstraintLayout.LayoutParams = +//// btnMinimize.layoutParams as ConstraintLayout.LayoutParams +//// val mCallBtnLayoutParam: ConstraintLayout.LayoutParams = +//// mCallBtn.layoutParams as ConstraintLayout.LayoutParams +//// +//// val iconSize: Int = requireContext().resources.getDimension(R.dimen.video_icon_size).toInt() +//// val iconSizeSmall: Int = +//// requireContext().resources.getDimension(R.dimen.video_icon_size_small).toInt() +//// +//// val localPreviewMargin: Int = +//// requireContext().resources.getDimension(R.dimen.local_preview_margin_top).toInt() +//// val localPreviewWidth: Int = +//// requireContext().resources.getDimension(R.dimen.local_preview_width).toInt() +//// val localPreviewHeight: Int = +//// requireContext().resources.getDimension(R.dimen.local_preview_height).toInt() +////// val localPreviewIconSize: Int = context!!.resources.getDimension(R.dimen.local_back_icon_size).toInt() +////// val localPreviewMarginSmall : Int = context!!.resources.getDimension(R.dimen.local_preview_margin_small).toInt() +////// val localPreviewWidthSmall : Int = context!!.resources.getDimension(R.dimen.local_preview_width_small).toInt() +////// val localPreviewHeightSmall : Int = context!!.resources.getDimension(R.dimen.local_preview_height_small).toInt() +////// val localPreviewIconSmall: Int = context!!.resources.getDimension(R.dimen.local_back_icon_size_small).toInt() +////// val localPreviewLayoutIconParam : FrameLayout.LayoutParams +//// val localPreviewLayoutParam: RelativeLayout.LayoutParams = +//// mPublisherViewContainer.layoutParams as RelativeLayout.LayoutParams +//// +//// val remotePreviewIconSize: Int = +//// requireContext().resources.getDimension(R.dimen.remote_back_icon_size).toInt() +//// val remotePreviewIconSizeSmall: Int = +//// requireContext().resources.getDimension(R.dimen.remote_back_icon_size_small).toInt() +//// val remotePreviewLayoutParam: FrameLayout.LayoutParams = +//// mSubscriberViewIcon.layoutParams as FrameLayout.LayoutParams +//// +//// if (isFullScreen) { +//// layoutName.visibility = View.VISIBLE +//// layoutMini.visibility = View.GONE +//// mCameraBtn.visibility = View.VISIBLE +//// mSwitchCameraBtn.visibility = View.VISIBLE +////// mspeckerBtn.visibility = View.VISIBLE +//// mMicBtn.visibility = View.VISIBLE +//// +//// btnMinimizeLayoutParam.width = iconSize +//// btnMinimizeLayoutParam.height = iconSize +//// mCallBtnLayoutParam.width = iconSize +//// mCallBtnLayoutParam.height = iconSize +////// localPreviewLayoutIconParam = FrameLayout.LayoutParams(localPreviewIconSize, localPreviewIconSize) +//////// localPreviewLayoutParam = RelativeLayout.LayoutParams(localPreviewWidth, localPreviewHeight) +//// localPreviewLayoutParam.width = localPreviewWidth +//// localPreviewLayoutParam.height = localPreviewHeight +//// localPreviewLayoutParam.setMargins(0, localPreviewMargin, localPreviewMargin, 0) +//// if (mPublisher != null && mPublisher!!.view.parent == null) { +//// mPublisherViewContainer.addView(mPublisher!!.view) +//// } +//// mPublisherViewContainer.visibility = View.VISIBLE +//// +////// remotePreviewLayoutParam = FrameLayout.LayoutParams(remotePreviewIconSize, remotePreviewIconSize) +//// remotePreviewLayoutParam.width = remotePreviewIconSize +//// remotePreviewLayoutParam.height = remotePreviewIconSize +//// } else { +//// layoutName.visibility = View.GONE +//// layoutMini.visibility = View.VISIBLE +//// mCameraBtn.visibility = View.GONE +//// mSwitchCameraBtn.visibility = View.GONE +////// mspeckerBtn.visibility = View.GONE +//// mMicBtn.visibility = View.GONE +////// mPublisherViewContainer.visibility = View.GONE +////// mPublisherViewIcon.visibility = View.GONE +//// +////// layoutParam = ConstraintLayout.LayoutParams(iconSizeSmall, iconSizeSmall) +//// btnMinimizeLayoutParam.width = iconSizeSmall +//// btnMinimizeLayoutParam.height = iconSizeSmall +//// mCallBtnLayoutParam.width = iconSizeSmall +//// mCallBtnLayoutParam.height = iconSizeSmall +//// +//// localPreviewLayoutParam.width = 0 +//// localPreviewLayoutParam.height = 0 +//// localPreviewLayoutParam.setMargins(0, localPreviewMargin / 2, localPreviewMargin / 2, 0) +//// +//// if (mPublisher != null) { +//// mPublisherViewContainer.removeView(mPublisher!!.view) +//// } +//// mPublisherViewContainer.visibility = View.GONE +////// localPreviewLayoutIconParam = FrameLayout.LayoutParams(localPreviewIconSmall, localPreviewIconSmall) +//////// localPreviewLayoutParam = RelativeLayout.LayoutParams(localPreviewWidthSmall, localPreviewHeightSmall) +////// localPreviewLayoutParam.width = localPreviewWidthSmall +////// localPreviewLayoutParam.height = localPreviewWidthSmall +////// localPreviewLayoutParam.setMargins(0,localPreviewMarginSmall, localPreviewMarginSmall, 0) +////// remotePreviewLayoutParam = FrameLayout.LayoutParams(remotePreviewIconSizeSmall, remotePreviewIconSizeSmall) +//// remotePreviewLayoutParam.width = remotePreviewIconSizeSmall +//// remotePreviewLayoutParam.height = remotePreviewIconSizeSmall +//// +//// if (isCircle) { +//// controlPanel.visibility = View.GONE +//// layoutMini.visibility = View.GONE +//// } else { +//// controlPanel.visibility = View.VISIBLE +//// layoutMini.visibility = View.VISIBLE +//// } +//// } +//// +//// mPublisherViewContainer.layoutParams = localPreviewLayoutParam +////// mPublisherViewIcon.layoutParams = localPreviewLayoutIconParam +//// mSubscriberViewIcon.layoutParams = remotePreviewLayoutParam +//// +//// btnMinimize.layoutParams = btnMinimizeLayoutParam +//// mCallBtn.layoutParams = mCallBtnLayoutParam +//// +//// handleVideoViewHeight(isFullScreen) +//// } +//// +//// private fun handleVideoViewHeight(isFullScreen: Boolean) { +//// val layoutNameParam: ConstraintLayout.LayoutParams = +//// layoutName.layoutParams as ConstraintLayout.LayoutParams +//// val layoutMiniParam: ConstraintLayout.LayoutParams = +//// layoutMini.layoutParams as ConstraintLayout.LayoutParams +//// val controlPanelParam: ConstraintLayout.LayoutParams = +//// controlPanel.layoutParams as ConstraintLayout.LayoutParams +//// +//// val layoutNameHeight: Int = +//// requireContext().resources.getDimension(R.dimen.layout_name_height).toInt() +//// val layoutMiniHeight: Int = +//// requireContext().resources.getDimension(R.dimen.layout_mini_height).toInt() +//// val panelHeight: Int = requireContext().resources.getDimension(R.dimen.layout_panel_height).toInt() +//// val panelHeightSmall: Int = +//// requireContext().resources.getDimension(R.dimen.layout_panel_height_small).toInt() +//// +//// val panelPadding: Int = +//// requireContext().resources.getDimension(R.dimen.padding_space_big).toInt() +//// val panelPaddingMedium: Int = +//// requireContext().resources.getDimension(R.dimen.padding_space_medium).toInt() +//// +//// val temp = getStatusBarHeight() / 2 +//// +//// val screenWidth: Float +//// val screenHeight: Float +//// +//// if (isFullScreen) { +//// screenWidth = ViewsUtil.getWidthDp(requireContext()) +//// screenHeight = ViewsUtil.getHeightDp(requireContext()) +//// +//// layoutNameParam.height = layoutNameHeight + temp +//// layoutMiniParam.height = 0 +//// controlPanelParam.height = panelHeight + temp +//// +//// controlPanel.setPadding(panelPadding, panelPadding, panelPadding, panelPadding) +//// } else { +//// +//// if (isCircle) { +//// screenWidth = 300F +//// screenHeight = 300F +//// +//// layoutNameParam.height = 0 +//// layoutMiniParam.height = 0 +//// controlPanelParam.height = 0 +//// } else { +//// screenWidth = 400F +//// screenHeight = 600F +//// +//// layoutNameParam.height = 0 +//// layoutMiniParam.height = layoutMiniHeight +//// controlPanelParam.height = panelHeightSmall +//// } +//// +//// controlPanel.setPadding( +//// panelPaddingMedium, +//// panelPaddingMedium, +//// panelPaddingMedium, +//// panelPaddingMedium +//// ) +//// } +//// +//// layoutName.layoutParams = layoutNameParam +//// layoutMini.layoutParams = layoutMiniParam +//// controlPanel.layoutParams = controlPanelParam +//// +//// var videoStreamHeight = +//// screenHeight - controlPanelParam.height - layoutNameParam.height - layoutMiniParam.height +//// +//// if (isFullScreen) { +////// videoStreamHeight -= getStatusBarHeight() / 2 +//// } +//// +//// val callLayoutParam: ConstraintLayout.LayoutParams = +//// activity_clingo_video_call.layoutParams as ConstraintLayout.LayoutParams +//// +//// callLayoutParam.height = videoStreamHeight.toInt() +//// callLayoutParam.width = screenWidth.toInt() +//// } +//// +//// private fun onCameraClicked(view: View?) { +//// if (mPublisher != null) { +//// isCameraClicked = !isCameraClicked +//// mPublisher!!.publishVideo = !isCameraClicked +//// val res = if (isCameraClicked) R.drawable.video_disabled else R.drawable.video_enabled +//// mCameraBtn.setImageResource(res) +//// +////// if (!isCameraClicked) { +////// videoCallContainer.background = ContextCompat.getDrawable(requireContext(), R.drawable.circle_shape) +////// mSubscriberViewContainer.background = ContextCompat.getDrawable(requireContext(), R.drawable.circle_shape) +////// } else { +////// videoCallContainer.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.text_color)) +////// mSubscriberViewContainer.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.remoteBackground)) +////// } +//// } +//// } +//// +//// private fun onMicClicked(view: View?) { +//// if (mPublisher != null) { +//// isMicClicked = !isMicClicked +//// mPublisher!!.publishAudio = !isMicClicked +//// val res = if (isMicClicked) R.drawable.mic_disabled else R.drawable.mic_enabled +//// mMicBtn!!.setImageResource(res) +//// } +//// } +//// +//// private fun onSpeckerClicked(view: View?) { +//// if (mSubscriber != null) { +//// isSpeckerClicked = !isSpeckerClicked +//// mSubscriber!!.subscribeToAudio = !isSpeckerClicked +//// val res = if (isSpeckerClicked) R.drawable.audio_disabled else R.drawable.audio_enabled +//// mspeckerBtn.setImageResource(res) +//// } +//// } +//// +//// @SuppressLint("ClickableViewAccessibility") +//// private fun handleDragDialog() { +//// mWindowManager = requireActivity().getSystemService(Context.WINDOW_SERVICE) as WindowManager +//// getWindowManagerDefaultDisplay() +//// +//// videoCallContainer.setOnTouchListener(dragListener) +//// mSubscriberViewContainer.setOnTouchListener(dragListener) +//// } +//// +//// @SuppressLint("ClickableViewAccessibility") +//// private val dragListener: View.OnTouchListener = View.OnTouchListener { _, event -> +//// mDetector.onTouchEvent(event) +//// +//// //Get Floating widget view params +//// val layoutParams: WindowManager.LayoutParams = dialog!!.window!!.attributes +//// //get the touch location coordinates +//// val x_cord = event.rawX.toInt() +//// val y_cord = event.rawY.toInt() +//// val x_cord_Destination: Int +//// var y_cord_Destination: Int +//// +//// when (event.action) { +//// MotionEvent.ACTION_DOWN -> { +//// x_init_cord = x_cord +//// y_init_cord = y_cord +//// +//// //remember the initial position. +//// x_init_margin = layoutParams.x +//// y_init_margin = layoutParams.y +//// } +//// MotionEvent.ACTION_UP -> { +//// //Get the difference between initial coordinate and current coordinate +//// val x_diff: Int = x_cord - x_init_cord +//// val y_diff: Int = y_cord - y_init_cord +//// +//// y_cord_Destination = y_init_margin + y_diff +//// val barHeight: Int = getStatusBarHeight() +//// if (y_cord_Destination < 0) { +////// y_cord_Destination = 0 +////// y_cord_Destination = +////// -(szWindow.y - (videoCallContainer.height /*+ barHeight*/)) +//// y_cord_Destination = -(szWindow.y / 2) +//// } else if (y_cord_Destination + (videoCallContainer.height + barHeight) > szWindow.y) { +////// y_cord_Destination = szWindow.y - (videoCallContainer.height + barHeight) +//// y_cord_Destination = (szWindow.y / 2) +//// } +//// layoutParams.y = y_cord_Destination +//// +//// //reset position if user drags the floating view +//// resetPosition(x_cord) +//// } +//// MotionEvent.ACTION_MOVE -> { +//// val x_diff_move: Int = x_cord - x_init_cord +//// val y_diff_move: Int = y_cord - y_init_cord +//// x_cord_Destination = x_init_margin + x_diff_move +//// y_cord_Destination = y_init_margin + y_diff_move +//// +//// layoutParams.x = x_cord_Destination +//// layoutParams.y = y_cord_Destination +//// +//// dialog!!.window!!.attributes = layoutParams +//// } +//// } +//// true +//// } +//// +//// private fun showControlPanelTemporarily() { +//// if (!isCircle) { +//// controlPanel.visibility = View.VISIBLE +//// mVolHandler!!.removeCallbacks(mVolRunnable!!) +//// mVolHandler!!.postDelayed(mVolRunnable!!, (5 * 1000).toLong()) +//// } +//// } +//// +//// /* Reset position of Floating Widget view on dragging */ +//// private fun resetPosition(x_cord_now: Int) { +//// if (x_cord_now <= szWindow.x / 2) { +//// isLeft = true +//// moveToLeft(x_cord_now) +//// } else { +//// isLeft = false +//// moveToRight(x_cord_now) +//// } +//// } +//// +//// /* Method to move the Floating widget view to Left */ +//// private fun moveToLeft(current_x_cord: Int) { +//// +//// var mParams: WindowManager.LayoutParams = dialog!!.window!!.attributes +//// +//// mParams.x = +//// (szWindow.x - current_x_cord * current_x_cord - videoCallContainer.width).toInt() +//// +//// dialog!!.window!!.attributes = mParams +//// val x = szWindow.x - current_x_cord +//// object : CountDownTimer(500, 5) { +//// //get params of Floating Widget view +//// var mParams: WindowManager.LayoutParams = dialog!!.window!!.attributes +//// override fun onTick(t: Long) { +//// val step = (500 - t) / 5 +//// // mParams.x = 0 - (current_x_cord * current_x_cord * step).toInt() +//// mParams.x = +//// (szWindow.x - current_x_cord * current_x_cord * step - videoCallContainer.width).toInt() +//// +//// dialog?.window?.attributes = mParams +//// } +//// +//// override fun onFinish() { +//// mParams.x = -(szWindow.x - videoCallContainer.width) +//// +//// dialog?.window!!.attributes = mParams +//// } +//// }.start() +//// } +//// +//// /* Method to move the Floating widget view to Right */ +//// private fun moveToRight(current_x_cord: Int) { +////// var mParams : WindowManager.LayoutParams = dialog!!.window!!.attributes +////// mParams.x = +////// (szWindow.x + current_x_cord * current_x_cord - videoCallContainer.width).toInt() +////// +////// dialog!!.window!!.attributes = mParams +//// object : CountDownTimer(500, 5) { +//// //get params of Floating Widget view +//// var mParams: WindowManager.LayoutParams = dialog!!.window!!.attributes +//// override fun onTick(t: Long) { +//// val step = (500 - t) / 5 +//// mParams.x = +//// (szWindow.x + current_x_cord * current_x_cord * step - videoCallContainer.width).toInt() +//// +//// dialog!!.window!!.attributes = mParams +//// } +//// +//// override fun onFinish() { +//// mParams.x = szWindow.x - videoCallContainer.width +//// +//// dialog?.window!!.attributes = mParams +//// } +//// }.start() +//// } +//// +//// private fun getWindowManagerDefaultDisplay() { +//// mWindowManager.getDefaultDisplay() +//// .getSize(szWindow) +//// } +//// +//// /* return status bar height on basis of device display metrics */ +//// private fun getStatusBarHeight(): Int { +//// return ceil( +//// (25 * requireActivity().applicationContext.resources.displayMetrics.density).toDouble() +//// ).toInt() +//// } +//// +//// private class MyGestureListener( +//// val onTabCall: () -> Unit, +//// val miniCircleDoubleTap: () -> Unit +//// ) : GestureDetector.SimpleOnGestureListener() { +//// +//// override fun onSingleTapConfirmed(event: MotionEvent): Boolean { +////// onTabCall() +//// return true +//// } +//// +////// override fun onDoubleTap(e: MotionEvent?): Boolean { +////// miniCircleDoubleTap() +////// return super.onDoubleTap(e) +////// } +//// +//// } +//// +//// companion object { +//// @JvmStatic +//// fun newInstance(args: Bundle) = +//// VideoCallFragment().apply { +//// arguments = args +//// } +//// +//// private val TAG = VideoCallFragment::class.java.simpleName +//// +//// private const val RC_SETTINGS_SCREEN_PERM = 123 +//// private const val RC_VIDEO_APP_PERM = 124 +//// +//// } +//} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/util/opentok/DynamicVideoRenderer.kt b/android/app/src/main/kotlin/com/hmg/hmgDr/util/opentok/DynamicVideoRenderer.kt index 818b231a..6184bde2 100644 --- a/android/app/src/main/kotlin/com/hmg/hmgDr/util/opentok/DynamicVideoRenderer.kt +++ b/android/app/src/main/kotlin/com/hmg/hmgDr/util/opentok/DynamicVideoRenderer.kt @@ -1,379 +1,379 @@ -package com.hmg.hmgDr.util.opentok - -import android.content.Context -import android.content.res.Resources -import android.graphics.PixelFormat -import android.opengl.GLES20 -import android.opengl.GLSurfaceView -import android.opengl.Matrix -import android.view.View -import com.opentok.android.BaseVideoRenderer -import java.nio.ByteBuffer -import java.nio.ByteOrder -import java.nio.FloatBuffer -import java.nio.ShortBuffer -import java.util.concurrent.locks.ReentrantLock -import javax.microedition.khronos.egl.EGLConfig -import javax.microedition.khronos.opengles.GL10 - -/* -* https://nhancv.medium.com/android-how-to-make-a-circular-view-as-a-thumbnail-of-opentok-27992aee15c9 -* to solve make circle video stream -* */ - -class DynamicVideoRenderer(private val mContext: Context) : BaseVideoRenderer() { - private val mView: GLSurfaceView = GLSurfaceView(mContext) - private val mRenderer: MyRenderer - - interface DynamicVideoRendererMetadataListener { - fun onMetadataReady(metadata: ByteArray?) - } - - fun setDynamicVideoRendererMetadataListener(metadataListener: DynamicVideoRendererMetadataListener?) { - mRenderer.metadataListener = metadataListener - } - - fun enableThumbnailCircle(enable: Boolean) { - mRenderer.requestEnableThumbnailCircle = enable - } - - internal class MyRenderer : GLSurfaceView.Renderer { - var mTextureIds = IntArray(3) - var mScaleMatrix = FloatArray(16) - private val mVertexBuffer: FloatBuffer - private val mTextureBuffer: FloatBuffer - private val mDrawListBuffer: ShortBuffer - var requestEnableThumbnailCircle = false - var mVideoFitEnabled = true - var mVideoDisabled = false - private val mVertexIndex = shortArrayOf(0, 1, 2, 0, 2, 3) // order to draw - - // vertices - private val vertexShaderCode = """uniform mat4 uMVPMatrix;attribute vec4 aPosition; -attribute vec2 aTextureCoord; -varying vec2 vTextureCoord; -void main() { - gl_Position = uMVPMatrix * aPosition; - vTextureCoord = aTextureCoord; -} -""" - private val fragmentShaderCode = """precision mediump float; -uniform sampler2D Ytex; -uniform sampler2D Utex,Vtex; -uniform int enableCircle; -uniform vec2 radiusDp; -varying vec2 vTextureCoord; -void main(void) { - float nx,ny,r,g,b,y,u,v; - mediump vec4 txl,ux,vx; nx=vTextureCoord[0]; - ny=vTextureCoord[1]; - y=texture2D(Ytex,vec2(nx,ny)).r; - u=texture2D(Utex,vec2(nx,ny)).r; - v=texture2D(Vtex,vec2(nx,ny)).r; - y=1.1643*(y-0.0625); - u=u-0.5; - v=v-0.5; - r=y+1.5958*v; - g=y-0.39173*u-0.81290*v; - b=y+2.017*u; - if (enableCircle > 0) { - float radius = 0.5; - vec4 color0 = vec4(0.0, 0.0, 0.0, 0.0); - vec4 color1 = vec4(r, g, b, 1.0); - vec2 st = (gl_FragCoord.xy/radiusDp.xy); float dist = radius - distance(st,vec2(0.5)); - float t = 1.0; - if (dist < 0.0) t = 0.0; - gl_FragColor = mix(color0, color1, t); - } - else { - gl_FragColor = vec4(r, g, b, 1.0); - } -} -""" - var mFrameLock = ReentrantLock() - var mCurrentFrame: Frame? = null - private var mProgram = 0 - private var mTextureWidth = 0 - private var mTextureHeight = 0 - private var mViewportWidth = 0 - private var mViewportHeight = 0 - override fun onSurfaceCreated(gl: GL10, config: EGLConfig) { - gl.glClearColor(0f, 0f, 0f, 1f) - GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT) - val vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, - vertexShaderCode) - val fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, - fragmentShaderCode) - mProgram = GLES20.glCreateProgram() // create empty OpenGL ES - // Program - GLES20.glAttachShader(mProgram, vertexShader) // add the vertex - // shader to program - GLES20.glAttachShader(mProgram, fragmentShader) // add the fragment - // shader to - // program - GLES20.glLinkProgram(mProgram) - val positionHandle = GLES20.glGetAttribLocation(mProgram, - "aPosition") - val textureHandle = GLES20.glGetAttribLocation(mProgram, - "aTextureCoord") - GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, - GLES20.GL_FLOAT, false, COORDS_PER_VERTEX * 4, - mVertexBuffer) - GLES20.glEnableVertexAttribArray(positionHandle) - GLES20.glVertexAttribPointer(textureHandle, - TEXTURECOORDS_PER_VERTEX, GLES20.GL_FLOAT, false, - TEXTURECOORDS_PER_VERTEX * 4, mTextureBuffer) - GLES20.glEnableVertexAttribArray(textureHandle) - GLES20.glUseProgram(mProgram) - var i = GLES20.glGetUniformLocation(mProgram, "Ytex") - GLES20.glUniform1i(i, 0) /* Bind Ytex to texture unit 0 */ - i = GLES20.glGetUniformLocation(mProgram, "Utex") - GLES20.glUniform1i(i, 1) /* Bind Utex to texture unit 1 */ - i = GLES20.glGetUniformLocation(mProgram, "Vtex") - GLES20.glUniform1i(i, 2) /* Bind Vtex to texture unit 2 */ - val radiusDpLocation = GLES20.glGetUniformLocation(mProgram, "radiusDp") - val radiusDp = (Resources.getSystem().displayMetrics.density * THUMBNAIL_SIZE).toInt() - GLES20.glUniform2f(radiusDpLocation, radiusDp.toFloat(), radiusDp.toFloat()) - mTextureWidth = 0 - mTextureHeight = 0 - } - - fun enableThumbnailCircle(enable: Boolean) { - GLES20.glUseProgram(mProgram) - val enableCircleLocation = GLES20.glGetUniformLocation(mProgram, "enableCircle") - GLES20.glUniform1i(enableCircleLocation, if (enable) 1 else 0) - } - - fun setupTextures(frame: Frame) { - if (mTextureIds[0] != 0) { - GLES20.glDeleteTextures(3, mTextureIds, 0) - } - GLES20.glGenTextures(3, mTextureIds, 0) - val w = frame.width - val h = frame.height - val hw = w + 1 shr 1 - val hh = h + 1 shr 1 - initializeTexture(GLES20.GL_TEXTURE0, mTextureIds[0], w, h) - initializeTexture(GLES20.GL_TEXTURE1, mTextureIds[1], hw, hh) - initializeTexture(GLES20.GL_TEXTURE2, mTextureIds[2], hw, hh) - mTextureWidth = frame.width - mTextureHeight = frame.height - } - - fun updateTextures(frame: Frame) { - val width = frame.width - val height = frame.height - val half_width = width + 1 shr 1 - val half_height = height + 1 shr 1 - val y_size = width * height - val uv_size = half_width * half_height - val bb = frame.buffer - // If we are reusing this frame, make sure we reset position and - // limit - bb.clear() - if (bb.remaining() == y_size + uv_size * 2) { - bb.position(0) - GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1) - GLES20.glPixelStorei(GLES20.GL_PACK_ALIGNMENT, 1) - GLES20.glActiveTexture(GLES20.GL_TEXTURE0) - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[0]) - GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, width, - height, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, - bb) - bb.position(y_size) - GLES20.glActiveTexture(GLES20.GL_TEXTURE1) - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[1]) - GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, - half_width, half_height, GLES20.GL_LUMINANCE, - GLES20.GL_UNSIGNED_BYTE, bb) - bb.position(y_size + uv_size) - GLES20.glActiveTexture(GLES20.GL_TEXTURE2) - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[2]) - GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, - half_width, half_height, GLES20.GL_LUMINANCE, - GLES20.GL_UNSIGNED_BYTE, bb) - } else { - mTextureWidth = 0 - mTextureHeight = 0 - } - } - - override fun onSurfaceChanged(gl: GL10, width: Int, height: Int) { - GLES20.glViewport(0, 0, width, height) - mViewportWidth = width - mViewportHeight = height - } - - var metadataListener: DynamicVideoRendererMetadataListener? = null - override fun onDrawFrame(gl: GL10) { - gl.glClearColor(0f, 0f, 0f, 0f) - GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT) - mFrameLock.lock() - if (mCurrentFrame != null && !mVideoDisabled) { - GLES20.glUseProgram(mProgram) - if (mTextureWidth != mCurrentFrame!!.width - || mTextureHeight != mCurrentFrame!!.height) { - setupTextures(mCurrentFrame!!) - } - updateTextures(mCurrentFrame!!) - Matrix.setIdentityM(mScaleMatrix, 0) - var scaleX = 1.0f - var scaleY = 1.0f - val ratio = (mCurrentFrame!!.width.toFloat() - / mCurrentFrame!!.height) - val vratio = mViewportWidth.toFloat() / mViewportHeight - if (mVideoFitEnabled) { - if (ratio > vratio) { - scaleY = vratio / ratio - } else { - scaleX = ratio / vratio - } - } else { - if (ratio < vratio) { - scaleY = vratio / ratio - } else { - scaleX = ratio / vratio - } - } - Matrix.scaleM(mScaleMatrix, 0, - scaleX * if (mCurrentFrame!!.isMirroredX) -1.0f else 1.0f, - scaleY, 1f) - metadataListener?.onMetadataReady(mCurrentFrame!!.metadata) - val mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, - "uMVPMatrix") - GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, - mScaleMatrix, 0) - enableThumbnailCircle(requestEnableThumbnailCircle) - GLES20.glDrawElements(GLES20.GL_TRIANGLES, mVertexIndex.size, - GLES20.GL_UNSIGNED_SHORT, mDrawListBuffer) - } else { - //black frame when video is disabled - gl.glClearColor(0f, 0f, 0f, 1f) - GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT) - } - mFrameLock.unlock() - } - - fun displayFrame(frame: Frame?) { - mFrameLock.lock() - if (mCurrentFrame != null) { - mCurrentFrame!!.recycle() - } - mCurrentFrame = frame - mFrameLock.unlock() - } - - fun disableVideo(b: Boolean) { - mFrameLock.lock() - mVideoDisabled = b - if (mVideoDisabled) { - if (mCurrentFrame != null) { - mCurrentFrame!!.recycle() - } - mCurrentFrame = null - } - mFrameLock.unlock() - } - - fun enableVideoFit(enableVideoFit: Boolean) { - mVideoFitEnabled = enableVideoFit - } - - companion object { - // number of coordinates per vertex in this array - const val COORDS_PER_VERTEX = 3 - const val TEXTURECOORDS_PER_VERTEX = 2 - var mXYZCoords = floatArrayOf( - -1.0f, 1.0f, 0.0f, // top left - -1.0f, -1.0f, 0.0f, // bottom left - 1.0f, -1.0f, 0.0f, // bottom right - 1.0f, 1.0f, 0.0f // top right - ) - var mUVCoords = floatArrayOf(0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f) - fun initializeTexture(name: Int, id: Int, width: Int, height: Int) { - GLES20.glActiveTexture(name) - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, id) - GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, - GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST.toFloat()) - GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, - GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR.toFloat()) - GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, - GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE.toFloat()) - GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, - GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE.toFloat()) - GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, - width, height, 0, GLES20.GL_LUMINANCE, - GLES20.GL_UNSIGNED_BYTE, null) - } - - fun loadShader(type: Int, shaderCode: String?): Int { - val shader = GLES20.glCreateShader(type) - GLES20.glShaderSource(shader, shaderCode) - GLES20.glCompileShader(shader) - return shader - } - } - - init { - val bb = ByteBuffer.allocateDirect(mXYZCoords.size * 4) - bb.order(ByteOrder.nativeOrder()) - mVertexBuffer = bb.asFloatBuffer() - mVertexBuffer.put(mXYZCoords) - mVertexBuffer.position(0) - val tb = ByteBuffer.allocateDirect(mUVCoords.size * 4) - tb.order(ByteOrder.nativeOrder()) - mTextureBuffer = tb.asFloatBuffer() - mTextureBuffer.put(mUVCoords) - mTextureBuffer.position(0) - val dlb = ByteBuffer.allocateDirect(mVertexIndex.size * 2) - dlb.order(ByteOrder.nativeOrder()) - mDrawListBuffer = dlb.asShortBuffer() - mDrawListBuffer.put(mVertexIndex) - mDrawListBuffer.position(0) - } - } - - override fun onFrame(frame: Frame) { - mRenderer.displayFrame(frame) - mView.requestRender() - } - - override fun setStyle(key: String, value: String) { - if (STYLE_VIDEO_SCALE == key) { - if (STYLE_VIDEO_FIT == value) { - mRenderer.enableVideoFit(true) - } else if (STYLE_VIDEO_FILL == value) { - mRenderer.enableVideoFit(false) - } - } - } - - override fun onVideoPropertiesChanged(videoEnabled: Boolean) { - mRenderer.disableVideo(!videoEnabled) - } - - override fun getView(): View { - return mView - } - - override fun onPause() { - mView.onPause() - } - - override fun onResume() { - mView.onResume() - } - - companion object { - private const val THUMBNAIL_SIZE = 90 //in dp - } - - init { - mView.setEGLContextClientVersion(2) - mView.setEGLConfigChooser(8, 8, 8, 8, 16, 0) - mView.holder.setFormat(PixelFormat.TRANSLUCENT) - mRenderer = MyRenderer() - mView.setRenderer(mRenderer) - mView.renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY - } -} \ No newline at end of file +//package com.hmg.hmgDr.util.opentok +// +//import android.content.Context +//import android.content.res.Resources +//import android.graphics.PixelFormat +//import android.opengl.GLES20 +//import android.opengl.GLSurfaceView +//import android.opengl.Matrix +//import android.view.View +//import com.opentok.android.BaseVideoRenderer +//import java.nio.ByteBuffer +//import java.nio.ByteOrder +//import java.nio.FloatBuffer +//import java.nio.ShortBuffer +//import java.util.concurrent.locks.ReentrantLock +//import javax.microedition.khronos.egl.EGLConfig +//import javax.microedition.khronos.opengles.GL10 +// +///* +//* https://nhancv.medium.com/android-how-to-make-a-circular-view-as-a-thumbnail-of-opentok-27992aee15c9 +//* to solve make circle video stream +//* */ +// +//class DynamicVideoRenderer(private val mContext: Context) : BaseVideoRenderer() { +//// private val mView: GLSurfaceView = GLSurfaceView(mContext) +//// private val mRenderer: MyRenderer +//// +//// interface DynamicVideoRendererMetadataListener { +//// fun onMetadataReady(metadata: ByteArray?) +////// } +//// +//// fun setDynamicVideoRendererMetadataListener(metadataListener: DynamicVideoRendererMetadataListener?) { +//// mRenderer.metadataListener = metadataListener +//// } +//// +//// fun enableThumbnailCircle(enable: Boolean) { +//// mRenderer.requestEnableThumbnailCircle = enable +//// } +//// +//// internal class MyRenderer : GLSurfaceView.Renderer { +//// var mTextureIds = IntArray(3) +//// var mScaleMatrix = FloatArray(16) +//// private val mVertexBuffer: FloatBuffer +//// private val mTextureBuffer: FloatBuffer +//// private val mDrawListBuffer: ShortBuffer +//// var requestEnableThumbnailCircle = false +//// var mVideoFitEnabled = true +//// var mVideoDisabled = false +//// private val mVertexIndex = shortArrayOf(0, 1, 2, 0, 2, 3) // order to draw +//// +//// // vertices +//// private val vertexShaderCode = """uniform mat4 uMVPMatrix;attribute vec4 aPosition; +////attribute vec2 aTextureCoord; +////varying vec2 vTextureCoord; +////void main() { +//// gl_Position = uMVPMatrix * aPosition; +//// vTextureCoord = aTextureCoord; +////} +////""" +//// private val fragmentShaderCode = """precision mediump float; +////uniform sampler2D Ytex; +////uniform sampler2D Utex,Vtex; +////uniform int enableCircle; +////uniform vec2 radiusDp; +////varying vec2 vTextureCoord; +////void main(void) { +//// float nx,ny,r,g,b,y,u,v; +//// mediump vec4 txl,ux,vx; nx=vTextureCoord[0]; +//// ny=vTextureCoord[1]; +//// y=texture2D(Ytex,vec2(nx,ny)).r; +//// u=texture2D(Utex,vec2(nx,ny)).r; +//// v=texture2D(Vtex,vec2(nx,ny)).r; +//// y=1.1643*(y-0.0625); +//// u=u-0.5; +//// v=v-0.5; +//// r=y+1.5958*v; +//// g=y-0.39173*u-0.81290*v; +//// b=y+2.017*u; +//// if (enableCircle > 0) { +//// float radius = 0.5; +//// vec4 color0 = vec4(0.0, 0.0, 0.0, 0.0); +//// vec4 color1 = vec4(r, g, b, 1.0); +//// vec2 st = (gl_FragCoord.xy/radiusDp.xy); float dist = radius - distance(st,vec2(0.5)); +//// float t = 1.0; +//// if (dist < 0.0) t = 0.0; +//// gl_FragColor = mix(color0, color1, t); +//// } +//// else { +//// gl_FragColor = vec4(r, g, b, 1.0); +//// } +////} +////""" +//// var mFrameLock = ReentrantLock() +//// var mCurrentFrame: Frame? = null +//// private var mProgram = 0 +//// private var mTextureWidth = 0 +//// private var mTextureHeight = 0 +//// private var mViewportWidth = 0 +//// private var mViewportHeight = 0 +//// override fun onSurfaceCreated(gl: GL10, config: EGLConfig) { +//// gl.glClearColor(0f, 0f, 0f, 1f) +//// GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT) +//// val vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, +//// vertexShaderCode) +//// val fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, +//// fragmentShaderCode) +//// mProgram = GLES20.glCreateProgram() // create empty OpenGL ES +//// // Program +//// GLES20.glAttachShader(mProgram, vertexShader) // add the vertex +//// // shader to program +//// GLES20.glAttachShader(mProgram, fragmentShader) // add the fragment +//// // shader to +//// // program +//// GLES20.glLinkProgram(mProgram) +//// val positionHandle = GLES20.glGetAttribLocation(mProgram, +//// "aPosition") +//// val textureHandle = GLES20.glGetAttribLocation(mProgram, +//// "aTextureCoord") +//// GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, +//// GLES20.GL_FLOAT, false, COORDS_PER_VERTEX * 4, +//// mVertexBuffer) +//// GLES20.glEnableVertexAttribArray(positionHandle) +//// GLES20.glVertexAttribPointer(textureHandle, +//// TEXTURECOORDS_PER_VERTEX, GLES20.GL_FLOAT, false, +//// TEXTURECOORDS_PER_VERTEX * 4, mTextureBuffer) +//// GLES20.glEnableVertexAttribArray(textureHandle) +//// GLES20.glUseProgram(mProgram) +//// var i = GLES20.glGetUniformLocation(mProgram, "Ytex") +//// GLES20.glUniform1i(i, 0) /* Bind Ytex to texture unit 0 */ +//// i = GLES20.glGetUniformLocation(mProgram, "Utex") +//// GLES20.glUniform1i(i, 1) /* Bind Utex to texture unit 1 */ +//// i = GLES20.glGetUniformLocation(mProgram, "Vtex") +//// GLES20.glUniform1i(i, 2) /* Bind Vtex to texture unit 2 */ +//// val radiusDpLocation = GLES20.glGetUniformLocation(mProgram, "radiusDp") +//// val radiusDp = (Resources.getSystem().displayMetrics.density * THUMBNAIL_SIZE).toInt() +//// GLES20.glUniform2f(radiusDpLocation, radiusDp.toFloat(), radiusDp.toFloat()) +//// mTextureWidth = 0 +//// mTextureHeight = 0 +//// } +//// +//// fun enableThumbnailCircle(enable: Boolean) { +//// GLES20.glUseProgram(mProgram) +//// val enableCircleLocation = GLES20.glGetUniformLocation(mProgram, "enableCircle") +//// GLES20.glUniform1i(enableCircleLocation, if (enable) 1 else 0) +//// } +//// +//// fun setupTextures(frame: Frame) { +//// if (mTextureIds[0] != 0) { +//// GLES20.glDeleteTextures(3, mTextureIds, 0) +//// } +//// GLES20.glGenTextures(3, mTextureIds, 0) +//// val w = frame.width +//// val h = frame.height +//// val hw = w + 1 shr 1 +//// val hh = h + 1 shr 1 +//// initializeTexture(GLES20.GL_TEXTURE0, mTextureIds[0], w, h) +//// initializeTexture(GLES20.GL_TEXTURE1, mTextureIds[1], hw, hh) +//// initializeTexture(GLES20.GL_TEXTURE2, mTextureIds[2], hw, hh) +//// mTextureWidth = frame.width +//// mTextureHeight = frame.height +//// } +//// +//// fun updateTextures(frame: Frame) { +//// val width = frame.width +//// val height = frame.height +//// val half_width = width + 1 shr 1 +//// val half_height = height + 1 shr 1 +//// val y_size = width * height +//// val uv_size = half_width * half_height +//// val bb = frame.buffer +//// // If we are reusing this frame, make sure we reset position and +//// // limit +//// bb.clear() +//// if (bb.remaining() == y_size + uv_size * 2) { +//// bb.position(0) +//// GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1) +//// GLES20.glPixelStorei(GLES20.GL_PACK_ALIGNMENT, 1) +//// GLES20.glActiveTexture(GLES20.GL_TEXTURE0) +//// GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[0]) +//// GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, width, +//// height, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, +//// bb) +//// bb.position(y_size) +//// GLES20.glActiveTexture(GLES20.GL_TEXTURE1) +//// GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[1]) +//// GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, +//// half_width, half_height, GLES20.GL_LUMINANCE, +//// GLES20.GL_UNSIGNED_BYTE, bb) +//// bb.position(y_size + uv_size) +//// GLES20.glActiveTexture(GLES20.GL_TEXTURE2) +//// GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[2]) +//// GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, +//// half_width, half_height, GLES20.GL_LUMINANCE, +//// GLES20.GL_UNSIGNED_BYTE, bb) +//// } else { +//// mTextureWidth = 0 +//// mTextureHeight = 0 +//// } +//// } +//// +//// override fun onSurfaceChanged(gl: GL10, width: Int, height: Int) { +//// GLES20.glViewport(0, 0, width, height) +//// mViewportWidth = width +//// mViewportHeight = height +//// } +//// +//// var metadataListener: DynamicVideoRendererMetadataListener? = null +//// override fun onDrawFrame(gl: GL10) { +//// gl.glClearColor(0f, 0f, 0f, 0f) +//// GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT) +//// mFrameLock.lock() +//// if (mCurrentFrame != null && !mVideoDisabled) { +//// GLES20.glUseProgram(mProgram) +//// if (mTextureWidth != mCurrentFrame!!.width +//// || mTextureHeight != mCurrentFrame!!.height) { +//// setupTextures(mCurrentFrame!!) +//// } +//// updateTextures(mCurrentFrame!!) +//// Matrix.setIdentityM(mScaleMatrix, 0) +//// var scaleX = 1.0f +//// var scaleY = 1.0f +//// val ratio = (mCurrentFrame!!.width.toFloat() +//// / mCurrentFrame!!.height) +//// val vratio = mViewportWidth.toFloat() / mViewportHeight +//// if (mVideoFitEnabled) { +//// if (ratio > vratio) { +//// scaleY = vratio / ratio +//// } else { +//// scaleX = ratio / vratio +//// } +//// } else { +//// if (ratio < vratio) { +//// scaleY = vratio / ratio +//// } else { +//// scaleX = ratio / vratio +//// } +//// } +//// Matrix.scaleM(mScaleMatrix, 0, +//// scaleX * if (mCurrentFrame!!.isMirroredX) -1.0f else 1.0f, +//// scaleY, 1f) +//// metadataListener?.onMetadataReady(mCurrentFrame!!.metadata) +//// val mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, +//// "uMVPMatrix") +//// GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, +//// mScaleMatrix, 0) +//// enableThumbnailCircle(requestEnableThumbnailCircle) +//// GLES20.glDrawElements(GLES20.GL_TRIANGLES, mVertexIndex.size, +//// GLES20.GL_UNSIGNED_SHORT, mDrawListBuffer) +//// } else { +//// //black frame when video is disabled +//// gl.glClearColor(0f, 0f, 0f, 1f) +//// GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT) +//// } +//// mFrameLock.unlock() +//// } +//// +//// fun displayFrame(frame: Frame?) { +//// mFrameLock.lock() +//// if (mCurrentFrame != null) { +//// mCurrentFrame!!.recycle() +//// } +//// mCurrentFrame = frame +//// mFrameLock.unlock() +//// } +//// +//// fun disableVideo(b: Boolean) { +//// mFrameLock.lock() +//// mVideoDisabled = b +//// if (mVideoDisabled) { +//// if (mCurrentFrame != null) { +//// mCurrentFrame!!.recycle() +//// } +//// mCurrentFrame = null +//// } +//// mFrameLock.unlock() +//// } +//// +//// fun enableVideoFit(enableVideoFit: Boolean) { +//// mVideoFitEnabled = enableVideoFit +//// } +//// +//// companion object { +//// // number of coordinates per vertex in this array +//// const val COORDS_PER_VERTEX = 3 +//// const val TEXTURECOORDS_PER_VERTEX = 2 +//// var mXYZCoords = floatArrayOf( +//// -1.0f, 1.0f, 0.0f, // top left +//// -1.0f, -1.0f, 0.0f, // bottom left +//// 1.0f, -1.0f, 0.0f, // bottom right +//// 1.0f, 1.0f, 0.0f // top right +//// ) +//// var mUVCoords = floatArrayOf(0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f) +//// fun initializeTexture(name: Int, id: Int, width: Int, height: Int) { +//// GLES20.glActiveTexture(name) +//// GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, id) +//// GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, +//// GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST.toFloat()) +//// GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, +//// GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR.toFloat()) +//// GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, +//// GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE.toFloat()) +//// GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, +//// GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE.toFloat()) +//// GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, +//// width, height, 0, GLES20.GL_LUMINANCE, +//// GLES20.GL_UNSIGNED_BYTE, null) +//// } +//// +//// fun loadShader(type: Int, shaderCode: String?): Int { +//// val shader = GLES20.glCreateShader(type) +//// GLES20.glShaderSource(shader, shaderCode) +//// GLES20.glCompileShader(shader) +//// return shader +//// } +//// } +//// +//// init { +//// val bb = ByteBuffer.allocateDirect(mXYZCoords.size * 4) +//// bb.order(ByteOrder.nativeOrder()) +//// mVertexBuffer = bb.asFloatBuffer() +//// mVertexBuffer.put(mXYZCoords) +//// mVertexBuffer.position(0) +//// val tb = ByteBuffer.allocateDirect(mUVCoords.size * 4) +//// tb.order(ByteOrder.nativeOrder()) +//// mTextureBuffer = tb.asFloatBuffer() +//// mTextureBuffer.put(mUVCoords) +//// mTextureBuffer.position(0) +//// val dlb = ByteBuffer.allocateDirect(mVertexIndex.size * 2) +//// dlb.order(ByteOrder.nativeOrder()) +//// mDrawListBuffer = dlb.asShortBuffer() +//// mDrawListBuffer.put(mVertexIndex) +//// mDrawListBuffer.position(0) +//// } +//// } +//// +//// override fun onFrame(frame: Frame) { +//// mRenderer.displayFrame(frame) +//// mView.requestRender() +//// } +//// +//// override fun setStyle(key: String, value: String) { +//// if (STYLE_VIDEO_SCALE == key) { +//// if (STYLE_VIDEO_FIT == value) { +//// mRenderer.enableVideoFit(true) +//// } else if (STYLE_VIDEO_FILL == value) { +//// mRenderer.enableVideoFit(false) +//// } +//// } +//// } +//// +//// override fun onVideoPropertiesChanged(videoEnabled: Boolean) { +//// mRenderer.disableVideo(!videoEnabled) +//// } +//// +//// override fun getView(): View { +//// return mView +//// } +//// +//// override fun onPause() { +//// mView.onPause() +//// } +//// +//// override fun onResume() { +//// mView.onResume() +//// } +//// +//// companion object { +//// private const val THUMBNAIL_SIZE = 90 //in dp +//// } +//// +//// init { +//// mView.setEGLContextClientVersion(2) +//// mView.setEGLConfigChooser(8, 8, 8, 8, 16, 0) +//// mView.holder.setFormat(PixelFormat.TRANSLUCENT) +//// mRenderer = MyRenderer() +//// mView.setRenderer(mRenderer) +//// mView.renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY +//// } +//} \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/hmg/hmgDr/util/opentok/ThumbnailCircleVideoRenderer.kt b/android/app/src/main/kotlin/com/hmg/hmgDr/util/opentok/ThumbnailCircleVideoRenderer.kt index 26630bea..4438f01e 100644 --- a/android/app/src/main/kotlin/com/hmg/hmgDr/util/opentok/ThumbnailCircleVideoRenderer.kt +++ b/android/app/src/main/kotlin/com/hmg/hmgDr/util/opentok/ThumbnailCircleVideoRenderer.kt @@ -1,357 +1,357 @@ -package com.hmg.hmgDr.util.opentok - -import android.content.Context -import android.content.res.Resources -import android.graphics.PixelFormat -import android.opengl.GLES20 -import android.opengl.GLSurfaceView -import android.opengl.Matrix -import android.view.View -import com.opentok.android.BaseVideoRenderer -import java.nio.ByteBuffer -import java.nio.ByteOrder -import java.nio.FloatBuffer -import java.nio.ShortBuffer -import java.util.concurrent.locks.ReentrantLock -import javax.microedition.khronos.egl.EGLConfig -import javax.microedition.khronos.opengles.GL10 - - -class ThumbnailCircleVideoRenderer(private val mContext: Context) : BaseVideoRenderer() { - private val mView: GLSurfaceView = GLSurfaceView(mContext) - private val mRenderer: MyRenderer - - interface ThumbnailCircleVideoRendererMetadataListener { - fun onMetadataReady(metadata: ByteArray?) - } - - fun setThumbnailCircleVideoRendererMetadataListener(metadataListener: ThumbnailCircleVideoRendererMetadataListener?) { - mRenderer.metadataListener = metadataListener - } - - internal class MyRenderer : GLSurfaceView.Renderer { - var mTextureIds = IntArray(3) - var mScaleMatrix = FloatArray(16) - private val mVertexBuffer: FloatBuffer - private val mTextureBuffer: FloatBuffer - private val mDrawListBuffer: ShortBuffer - var mVideoFitEnabled = true - var mVideoDisabled = false - private val mVertexIndex = shortArrayOf(0, 1, 2, 0, 2, 3) // order to draw - - // vertices - private val vertexShaderCode = """uniform mat4 uMVPMatrix;attribute vec4 aPosition; -attribute vec2 aTextureCoord; -varying vec2 vTextureCoord; -void main() { - gl_Position = uMVPMatrix * aPosition; - vTextureCoord = aTextureCoord; -} -""" - private val fragmentShaderCode = """precision mediump float; -uniform sampler2D Ytex; -uniform sampler2D Utex,Vtex; -uniform vec2 radiusDp; -varying vec2 vTextureCoord; -void main(void) { - float nx,ny,r,g,b,y,u,v; - mediump vec4 txl,ux,vx; nx=vTextureCoord[0]; - ny=vTextureCoord[1]; - y=texture2D(Ytex,vec2(nx,ny)).r; - u=texture2D(Utex,vec2(nx,ny)).r; - v=texture2D(Vtex,vec2(nx,ny)).r; - y=1.1643*(y-0.0625); - u=u-0.5; - v=v-0.5; - r=y+1.5958*v; - g=y-0.39173*u-0.81290*v; - b=y+2.017*u; - float radius = 0.5; - vec4 color0 = vec4(0.0, 0.0, 0.0, 0.0); - vec4 color1 = vec4(r, g, b, 1.0); - vec2 st = (gl_FragCoord.xy/radiusDp.xy); float dist = radius - distance(st,vec2(0.5)); - float t = 1.0; - if (dist < 0.0) t = 0.0; - gl_FragColor = mix(color0, color1, t); -} -""" - var mFrameLock = ReentrantLock() - var mCurrentFrame: Frame? = null - private var mProgram = 0 - private var mTextureWidth = 0 - private var mTextureHeight = 0 - private var mViewportWidth = 0 - private var mViewportHeight = 0 - override fun onSurfaceCreated(gl: GL10, config: EGLConfig) { - gl.glClearColor(0f, 0f, 0f, 1f) - GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT) - val vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, - vertexShaderCode) - val fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, - fragmentShaderCode) - mProgram = GLES20.glCreateProgram() // create empty OpenGL ES - // Program - GLES20.glAttachShader(mProgram, vertexShader) // add the vertex - // shader to program - GLES20.glAttachShader(mProgram, fragmentShader) // add the fragment - // shader to - // program - GLES20.glLinkProgram(mProgram) - val positionHandle = GLES20.glGetAttribLocation(mProgram, - "aPosition") - val textureHandle = GLES20.glGetAttribLocation(mProgram, - "aTextureCoord") - GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, - GLES20.GL_FLOAT, false, COORDS_PER_VERTEX * 4, - mVertexBuffer) - GLES20.glEnableVertexAttribArray(positionHandle) - GLES20.glVertexAttribPointer(textureHandle, - TEXTURECOORDS_PER_VERTEX, GLES20.GL_FLOAT, false, - TEXTURECOORDS_PER_VERTEX * 4, mTextureBuffer) - GLES20.glEnableVertexAttribArray(textureHandle) - GLES20.glUseProgram(mProgram) - var i = GLES20.glGetUniformLocation(mProgram, "Ytex") - GLES20.glUniform1i(i, 0) /* Bind Ytex to texture unit 0 */ - i = GLES20.glGetUniformLocation(mProgram, "Utex") - GLES20.glUniform1i(i, 1) /* Bind Utex to texture unit 1 */ - i = GLES20.glGetUniformLocation(mProgram, "Vtex") - GLES20.glUniform1i(i, 2) /* Bind Vtex to texture unit 2 */ - val radiusDpLocation = GLES20.glGetUniformLocation(mProgram, "radiusDp") - val radiusDp = (Resources.getSystem().displayMetrics.density * THUMBNAIL_SIZE).toInt() - GLES20.glUniform2f(radiusDpLocation, radiusDp.toFloat(), radiusDp.toFloat()) - mTextureWidth = 0 - mTextureHeight = 0 - } - - fun setupTextures(frame: Frame) { - if (mTextureIds[0] != 0) { - GLES20.glDeleteTextures(3, mTextureIds, 0) - } - GLES20.glGenTextures(3, mTextureIds, 0) - val w = frame.width - val h = frame.height - val hw = w + 1 shr 1 - val hh = h + 1 shr 1 - initializeTexture(GLES20.GL_TEXTURE0, mTextureIds[0], w, h) - initializeTexture(GLES20.GL_TEXTURE1, mTextureIds[1], hw, hh) - initializeTexture(GLES20.GL_TEXTURE2, mTextureIds[2], hw, hh) - mTextureWidth = frame.width - mTextureHeight = frame.height - } - - fun updateTextures(frame: Frame) { - val width = frame.width - val height = frame.height - val half_width = width + 1 shr 1 - val half_height = height + 1 shr 1 - val y_size = width * height - val uv_size = half_width * half_height - val bb = frame.buffer - // If we are reusing this frame, make sure we reset position and - // limit - bb.clear() - if (bb.remaining() == y_size + uv_size * 2) { - bb.position(0) - GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1) - GLES20.glPixelStorei(GLES20.GL_PACK_ALIGNMENT, 1) - GLES20.glActiveTexture(GLES20.GL_TEXTURE0) - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[0]) - GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, width, - height, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, - bb) - bb.position(y_size) - GLES20.glActiveTexture(GLES20.GL_TEXTURE1) - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[1]) - GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, - half_width, half_height, GLES20.GL_LUMINANCE, - GLES20.GL_UNSIGNED_BYTE, bb) - bb.position(y_size + uv_size) - GLES20.glActiveTexture(GLES20.GL_TEXTURE2) - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[2]) - GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, - half_width, half_height, GLES20.GL_LUMINANCE, - GLES20.GL_UNSIGNED_BYTE, bb) - } else { - mTextureWidth = 0 - mTextureHeight = 0 - } - } - - override fun onSurfaceChanged(gl: GL10, width: Int, height: Int) { - GLES20.glViewport(0, 0, width, height) - mViewportWidth = width - mViewportHeight = height - } - - var metadataListener: ThumbnailCircleVideoRendererMetadataListener? = null - override fun onDrawFrame(gl: GL10) { - gl.glClearColor(0f, 0f, 0f, 0f) - GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT) - mFrameLock.lock() - if (mCurrentFrame != null && !mVideoDisabled) { - GLES20.glUseProgram(mProgram) - if (mTextureWidth != mCurrentFrame!!.width - || mTextureHeight != mCurrentFrame!!.height) { - setupTextures(mCurrentFrame!!) - } - updateTextures(mCurrentFrame!!) - Matrix.setIdentityM(mScaleMatrix, 0) - var scaleX = 1.0f - var scaleY = 1.0f - val ratio = (mCurrentFrame!!.width.toFloat() - / mCurrentFrame!!.height) - val vratio = mViewportWidth.toFloat() / mViewportHeight - if (mVideoFitEnabled) { - if (ratio > vratio) { - scaleY = vratio / ratio - } else { - scaleX = ratio / vratio - } - } else { - if (ratio < vratio) { - scaleY = vratio / ratio - } else { - scaleX = ratio / vratio - } - } - Matrix.scaleM(mScaleMatrix, 0, - scaleX * if (mCurrentFrame!!.isMirroredX) -1.0f else 1.0f, - scaleY, 1f) - metadataListener?.onMetadataReady(mCurrentFrame!!.metadata) - val mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, - "uMVPMatrix") - GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, - mScaleMatrix, 0) - GLES20.glDrawElements(GLES20.GL_TRIANGLES, mVertexIndex.size, - GLES20.GL_UNSIGNED_SHORT, mDrawListBuffer) - } else { - //black frame when video is disabled - gl.glClearColor(0f, 0f, 0f, 1f) - GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT) - } - mFrameLock.unlock() - } - - fun displayFrame(frame: Frame?) { - mFrameLock.lock() - if (mCurrentFrame != null) { - mCurrentFrame!!.recycle() - } - mCurrentFrame = frame - mFrameLock.unlock() - } - - fun disableVideo(b: Boolean) { - mFrameLock.lock() - mVideoDisabled = b - if (mVideoDisabled) { - if (mCurrentFrame != null) { - mCurrentFrame!!.recycle() - } - mCurrentFrame = null - } - mFrameLock.unlock() - } - - fun enableVideoFit(enableVideoFit: Boolean) { - mVideoFitEnabled = enableVideoFit - } - - companion object { - // number of coordinates per vertex in this array - const val COORDS_PER_VERTEX = 3 - const val TEXTURECOORDS_PER_VERTEX = 2 - var mXYZCoords = floatArrayOf( - -1.0f, 1.0f, 0.0f, // top left - -1.0f, -1.0f, 0.0f, // bottom left - 1.0f, -1.0f, 0.0f, // bottom right - 1.0f, 1.0f, 0.0f // top right - ) - var mUVCoords = floatArrayOf(0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f) - fun initializeTexture(name: Int, id: Int, width: Int, height: Int) { - GLES20.glActiveTexture(name) - GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, id) - GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, - GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST.toFloat()) - GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, - GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR.toFloat()) - GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, - GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE.toFloat()) - GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, - GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE.toFloat()) - GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, - width, height, 0, GLES20.GL_LUMINANCE, - GLES20.GL_UNSIGNED_BYTE, null) - } - - fun loadShader(type: Int, shaderCode: String?): Int { - val shader = GLES20.glCreateShader(type) - GLES20.glShaderSource(shader, shaderCode) - GLES20.glCompileShader(shader) - return shader - } - } - - init { - val bb = ByteBuffer.allocateDirect(mXYZCoords.size * 4) - bb.order(ByteOrder.nativeOrder()) - mVertexBuffer = bb.asFloatBuffer() - mVertexBuffer.put(mXYZCoords) - mVertexBuffer.position(0) - val tb = ByteBuffer.allocateDirect(mUVCoords.size * 4) - tb.order(ByteOrder.nativeOrder()) - mTextureBuffer = tb.asFloatBuffer() - mTextureBuffer.put(mUVCoords) - mTextureBuffer.position(0) - val dlb = ByteBuffer.allocateDirect(mVertexIndex.size * 2) - dlb.order(ByteOrder.nativeOrder()) - mDrawListBuffer = dlb.asShortBuffer() - mDrawListBuffer.put(mVertexIndex) - mDrawListBuffer.position(0) - } - } - - override fun onFrame(frame: Frame) { - mRenderer.displayFrame(frame) - mView.requestRender() - } - - override fun setStyle(key: String, value: String) { - if (STYLE_VIDEO_SCALE == key) { - if (STYLE_VIDEO_FIT == value) { - mRenderer.enableVideoFit(true) - } else if (STYLE_VIDEO_FILL == value) { - mRenderer.enableVideoFit(false) - } - } - } - - override fun onVideoPropertiesChanged(videoEnabled: Boolean) { - mRenderer.disableVideo(!videoEnabled) - } - - override fun getView(): View { - return mView - } - - override fun onPause() { - mView.onPause() - } - - override fun onResume() { - mView.onResume() - } - - companion object { - private const val THUMBNAIL_SIZE = 90 //in dp - } - - init { - mView.setEGLContextClientVersion(2) - mView.setEGLConfigChooser(8, 8, 8, 8, 16, 0) - mView.holder.setFormat(PixelFormat.TRANSLUCENT) - mRenderer = MyRenderer() - mView.setRenderer(mRenderer) - mView.renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY - } -} +//package com.hmg.hmgDr.util.opentok +// +//import android.content.Context +//import android.content.res.Resources +//import android.graphics.PixelFormat +//import android.opengl.GLES20 +//import android.opengl.GLSurfaceView +//import android.opengl.Matrix +//import android.view.View +//import com.opentok.android.BaseVideoRenderer +//import java.nio.ByteBuffer +//import java.nio.ByteOrder +//import java.nio.FloatBuffer +//import java.nio.ShortBuffer +//import java.util.concurrent.locks.ReentrantLock +//import javax.microedition.khronos.egl.EGLConfig +//import javax.microedition.khronos.opengles.GL10 +// +// +//class ThumbnailCircleVideoRenderer(private val mContext: Context) : BaseVideoRenderer() { +//// private val mView: GLSurfaceView = GLSurfaceView(mContext) +//// private val mRenderer: MyRenderer +//// +//// interface ThumbnailCircleVideoRendererMetadataListener { +//// fun onMetadataReady(metadata: ByteArray?) +//// } +//// +//// fun setThumbnailCircleVideoRendererMetadataListener(metadataListener: ThumbnailCircleVideoRendererMetadataListener?) { +//// mRenderer.metadataListener = metadataListener +//// } +//// +//// internal class MyRenderer : GLSurfaceView.Renderer { +//// var mTextureIds = IntArray(3) +//// var mScaleMatrix = FloatArray(16) +//// private val mVertexBuffer: FloatBuffer +//// private val mTextureBuffer: FloatBuffer +//// private val mDrawListBuffer: ShortBuffer +//// var mVideoFitEnabled = true +//// var mVideoDisabled = false +//// private val mVertexIndex = shortArrayOf(0, 1, 2, 0, 2, 3) // order to draw +//// +//// // vertices +//// private val vertexShaderCode = """uniform mat4 uMVPMatrix;attribute vec4 aPosition; +////attribute vec2 aTextureCoord; +////varying vec2 vTextureCoord; +////void main() { +//// gl_Position = uMVPMatrix * aPosition; +//// vTextureCoord = aTextureCoord; +////} +////""" +//// private val fragmentShaderCode = """precision mediump float; +////uniform sampler2D Ytex; +////uniform sampler2D Utex,Vtex; +////uniform vec2 radiusDp; +////varying vec2 vTextureCoord; +////void main(void) { +//// float nx,ny,r,g,b,y,u,v; +//// mediump vec4 txl,ux,vx; nx=vTextureCoord[0]; +//// ny=vTextureCoord[1]; +//// y=texture2D(Ytex,vec2(nx,ny)).r; +//// u=texture2D(Utex,vec2(nx,ny)).r; +//// v=texture2D(Vtex,vec2(nx,ny)).r; +//// y=1.1643*(y-0.0625); +//// u=u-0.5; +//// v=v-0.5; +//// r=y+1.5958*v; +//// g=y-0.39173*u-0.81290*v; +//// b=y+2.017*u; +//// float radius = 0.5; +//// vec4 color0 = vec4(0.0, 0.0, 0.0, 0.0); +//// vec4 color1 = vec4(r, g, b, 1.0); +//// vec2 st = (gl_FragCoord.xy/radiusDp.xy); float dist = radius - distance(st,vec2(0.5)); +//// float t = 1.0; +//// if (dist < 0.0) t = 0.0; +//// gl_FragColor = mix(color0, color1, t); +////} +////""" +//// var mFrameLock = ReentrantLock() +//// var mCurrentFrame: Frame? = null +//// private var mProgram = 0 +//// private var mTextureWidth = 0 +//// private var mTextureHeight = 0 +//// private var mViewportWidth = 0 +//// private var mViewportHeight = 0 +//// override fun onSurfaceCreated(gl: GL10, config: EGLConfig) { +//// gl.glClearColor(0f, 0f, 0f, 1f) +//// GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT) +//// val vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, +//// vertexShaderCode) +//// val fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, +//// fragmentShaderCode) +//// mProgram = GLES20.glCreateProgram() // create empty OpenGL ES +//// // Program +//// GLES20.glAttachShader(mProgram, vertexShader) // add the vertex +//// // shader to program +//// GLES20.glAttachShader(mProgram, fragmentShader) // add the fragment +//// // shader to +//// // program +//// GLES20.glLinkProgram(mProgram) +//// val positionHandle = GLES20.glGetAttribLocation(mProgram, +//// "aPosition") +//// val textureHandle = GLES20.glGetAttribLocation(mProgram, +//// "aTextureCoord") +//// GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, +//// GLES20.GL_FLOAT, false, COORDS_PER_VERTEX * 4, +//// mVertexBuffer) +//// GLES20.glEnableVertexAttribArray(positionHandle) +//// GLES20.glVertexAttribPointer(textureHandle, +//// TEXTURECOORDS_PER_VERTEX, GLES20.GL_FLOAT, false, +//// TEXTURECOORDS_PER_VERTEX * 4, mTextureBuffer) +//// GLES20.glEnableVertexAttribArray(textureHandle) +//// GLES20.glUseProgram(mProgram) +//// var i = GLES20.glGetUniformLocation(mProgram, "Ytex") +//// GLES20.glUniform1i(i, 0) /* Bind Ytex to texture unit 0 */ +//// i = GLES20.glGetUniformLocation(mProgram, "Utex") +//// GLES20.glUniform1i(i, 1) /* Bind Utex to texture unit 1 */ +//// i = GLES20.glGetUniformLocation(mProgram, "Vtex") +//// GLES20.glUniform1i(i, 2) /* Bind Vtex to texture unit 2 */ +//// val radiusDpLocation = GLES20.glGetUniformLocation(mProgram, "radiusDp") +//// val radiusDp = (Resources.getSystem().displayMetrics.density * THUMBNAIL_SIZE).toInt() +//// GLES20.glUniform2f(radiusDpLocation, radiusDp.toFloat(), radiusDp.toFloat()) +//// mTextureWidth = 0 +//// mTextureHeight = 0 +//// } +//// +//// fun setupTextures(frame: Frame) { +//// if (mTextureIds[0] != 0) { +//// GLES20.glDeleteTextures(3, mTextureIds, 0) +//// } +//// GLES20.glGenTextures(3, mTextureIds, 0) +//// val w = frame.width +//// val h = frame.height +//// val hw = w + 1 shr 1 +//// val hh = h + 1 shr 1 +//// initializeTexture(GLES20.GL_TEXTURE0, mTextureIds[0], w, h) +//// initializeTexture(GLES20.GL_TEXTURE1, mTextureIds[1], hw, hh) +//// initializeTexture(GLES20.GL_TEXTURE2, mTextureIds[2], hw, hh) +//// mTextureWidth = frame.width +//// mTextureHeight = frame.height +//// } +//// +//// fun updateTextures(frame: Frame) { +//// val width = frame.width +//// val height = frame.height +//// val half_width = width + 1 shr 1 +//// val half_height = height + 1 shr 1 +//// val y_size = width * height +//// val uv_size = half_width * half_height +//// val bb = frame.buffer +//// // If we are reusing this frame, make sure we reset position and +//// // limit +//// bb.clear() +//// if (bb.remaining() == y_size + uv_size * 2) { +//// bb.position(0) +//// GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1) +//// GLES20.glPixelStorei(GLES20.GL_PACK_ALIGNMENT, 1) +//// GLES20.glActiveTexture(GLES20.GL_TEXTURE0) +//// GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[0]) +//// GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, width, +//// height, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, +//// bb) +//// bb.position(y_size) +//// GLES20.glActiveTexture(GLES20.GL_TEXTURE1) +//// GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[1]) +//// GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, +//// half_width, half_height, GLES20.GL_LUMINANCE, +//// GLES20.GL_UNSIGNED_BYTE, bb) +//// bb.position(y_size + uv_size) +//// GLES20.glActiveTexture(GLES20.GL_TEXTURE2) +//// GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureIds[2]) +//// GLES20.glTexSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, +//// half_width, half_height, GLES20.GL_LUMINANCE, +//// GLES20.GL_UNSIGNED_BYTE, bb) +//// } else { +//// mTextureWidth = 0 +//// mTextureHeight = 0 +//// } +//// } +//// +//// override fun onSurfaceChanged(gl: GL10, width: Int, height: Int) { +//// GLES20.glViewport(0, 0, width, height) +//// mViewportWidth = width +//// mViewportHeight = height +//// } +//// +//// var metadataListener: ThumbnailCircleVideoRendererMetadataListener? = null +//// override fun onDrawFrame(gl: GL10) { +//// gl.glClearColor(0f, 0f, 0f, 0f) +//// GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT) +//// mFrameLock.lock() +//// if (mCurrentFrame != null && !mVideoDisabled) { +//// GLES20.glUseProgram(mProgram) +//// if (mTextureWidth != mCurrentFrame!!.width +//// || mTextureHeight != mCurrentFrame!!.height) { +//// setupTextures(mCurrentFrame!!) +//// } +//// updateTextures(mCurrentFrame!!) +//// Matrix.setIdentityM(mScaleMatrix, 0) +//// var scaleX = 1.0f +//// var scaleY = 1.0f +//// val ratio = (mCurrentFrame!!.width.toFloat() +//// / mCurrentFrame!!.height) +//// val vratio = mViewportWidth.toFloat() / mViewportHeight +//// if (mVideoFitEnabled) { +//// if (ratio > vratio) { +//// scaleY = vratio / ratio +//// } else { +//// scaleX = ratio / vratio +//// } +//// } else { +//// if (ratio < vratio) { +//// scaleY = vratio / ratio +//// } else { +//// scaleX = ratio / vratio +//// } +//// } +//// Matrix.scaleM(mScaleMatrix, 0, +//// scaleX * if (mCurrentFrame!!.isMirroredX) -1.0f else 1.0f, +//// scaleY, 1f) +//// metadataListener?.onMetadataReady(mCurrentFrame!!.metadata) +//// val mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, +//// "uMVPMatrix") +//// GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, +//// mScaleMatrix, 0) +//// GLES20.glDrawElements(GLES20.GL_TRIANGLES, mVertexIndex.size, +//// GLES20.GL_UNSIGNED_SHORT, mDrawListBuffer) +//// } else { +//// //black frame when video is disabled +//// gl.glClearColor(0f, 0f, 0f, 1f) +//// GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT) +//// } +//// mFrameLock.unlock() +//// } +//// +//// fun displayFrame(frame: Frame?) { +//// mFrameLock.lock() +//// if (mCurrentFrame != null) { +//// mCurrentFrame!!.recycle() +//// } +//// mCurrentFrame = frame +//// mFrameLock.unlock() +//// } +//// +//// fun disableVideo(b: Boolean) { +//// mFrameLock.lock() +//// mVideoDisabled = b +//// if (mVideoDisabled) { +//// if (mCurrentFrame != null) { +//// mCurrentFrame!!.recycle() +//// } +//// mCurrentFrame = null +//// } +//// mFrameLock.unlock() +//// } +//// +//// fun enableVideoFit(enableVideoFit: Boolean) { +//// mVideoFitEnabled = enableVideoFit +//// } +//// +//// companion object { +//// // number of coordinates per vertex in this array +//// const val COORDS_PER_VERTEX = 3 +//// const val TEXTURECOORDS_PER_VERTEX = 2 +//// var mXYZCoords = floatArrayOf( +//// -1.0f, 1.0f, 0.0f, // top left +//// -1.0f, -1.0f, 0.0f, // bottom left +//// 1.0f, -1.0f, 0.0f, // bottom right +//// 1.0f, 1.0f, 0.0f // top right +//// ) +//// var mUVCoords = floatArrayOf(0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f) +//// fun initializeTexture(name: Int, id: Int, width: Int, height: Int) { +//// GLES20.glActiveTexture(name) +//// GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, id) +//// GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, +//// GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST.toFloat()) +//// GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, +//// GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR.toFloat()) +//// GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, +//// GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE.toFloat()) +//// GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, +//// GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE.toFloat()) +//// GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, +//// width, height, 0, GLES20.GL_LUMINANCE, +//// GLES20.GL_UNSIGNED_BYTE, null) +//// } +//// +//// fun loadShader(type: Int, shaderCode: String?): Int { +//// val shader = GLES20.glCreateShader(type) +//// GLES20.glShaderSource(shader, shaderCode) +//// GLES20.glCompileShader(shader) +//// return shader +//// } +//// } +//// +//// init { +//// val bb = ByteBuffer.allocateDirect(mXYZCoords.size * 4) +//// bb.order(ByteOrder.nativeOrder()) +//// mVertexBuffer = bb.asFloatBuffer() +//// mVertexBuffer.put(mXYZCoords) +//// mVertexBuffer.position(0) +//// val tb = ByteBuffer.allocateDirect(mUVCoords.size * 4) +//// tb.order(ByteOrder.nativeOrder()) +//// mTextureBuffer = tb.asFloatBuffer() +//// mTextureBuffer.put(mUVCoords) +//// mTextureBuffer.position(0) +//// val dlb = ByteBuffer.allocateDirect(mVertexIndex.size * 2) +//// dlb.order(ByteOrder.nativeOrder()) +//// mDrawListBuffer = dlb.asShortBuffer() +//// mDrawListBuffer.put(mVertexIndex) +//// mDrawListBuffer.position(0) +//// } +//// } +//// +//// override fun onFrame(frame: Frame) { +//// mRenderer.displayFrame(frame) +//// mView.requestRender() +//// } +//// +//// override fun setStyle(key: String, value: String) { +//// if (STYLE_VIDEO_SCALE == key) { +//// if (STYLE_VIDEO_FIT == value) { +//// mRenderer.enableVideoFit(true) +//// } else if (STYLE_VIDEO_FILL == value) { +//// mRenderer.enableVideoFit(false) +//// } +//// } +//// } +//// +//// override fun onVideoPropertiesChanged(videoEnabled: Boolean) { +//// mRenderer.disableVideo(!videoEnabled) +//// } +//// +//// override fun getView(): View { +//// return mView +//// } +//// +//// override fun onPause() { +//// mView.onPause() +//// } +//// +//// override fun onResume() { +//// mView.onResume() +//// } +//// +//// companion object { +//// private const val THUMBNAIL_SIZE = 90 //in dp +//// } +//// +//// init { +//// mView.setEGLContextClientVersion(2) +//// mView.setEGLConfigChooser(8, 8, 8, 8, 16, 0) +//// mView.holder.setFormat(PixelFormat.TRANSLUCENT) +//// mRenderer = MyRenderer() +//// mView.setRenderer(mRenderer) +//// mView.renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY +//// } +//} diff --git a/lib/config/config.dart b/lib/config/config.dart index 44da1d03..86737dca 100755 --- a/lib/config/config.dart +++ b/lib/config/config.dart @@ -16,11 +16,11 @@ const DOCTOR_ROTATION = 'https://doctorrota.hmg.com/'; // const BASE_URL = 'https://hmgwebservices.com/'; // const BASE_URL = 'http://10.20.200.111:1010/'; -// const BASE_URL = 'https://uat.hmgwebservices.com/'; +const BASE_URL = 'https://uat.hmgwebservices.com/'; // const BASE_URL = 'https://hmgwebservices.com/'; -const BASE_URL = 'https://webservices.hmg.com/'; +// const BASE_URL = 'https://webservices.hmg.com/'; // // const BASE_URL = 'https://vidauat.cloudsolutions.com.sa/'; //Vida Plus URL diff --git a/lib/core/viewModel/PatientSearchViewModel.dart b/lib/core/viewModel/PatientSearchViewModel.dart index 0656f73f..d91e34dc 100644 --- a/lib/core/viewModel/PatientSearchViewModel.dart +++ b/lib/core/viewModel/PatientSearchViewModel.dart @@ -104,7 +104,7 @@ class PatientSearchViewModel extends BaseViewModel { String dateTo; String dateFrom; if (OutPatientFilterType.Previous == outPatientFilterType) { - selectedFromDate = DateTime(DateTime.now().year, DateTime.now().month - 1, DateTime.now().day); + selectedFromDate = DateTime(DateTime.now().year, DateTime.now().month , DateTime.now().day-2); selectedToDate = DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day - 1); dateTo = AppDateUtils.convertDateToFormat(selectedToDate!, 'yyyy-MM-dd'); dateFrom = AppDateUtils.convertDateToFormat(selectedFromDate!, 'yyyy-MM-dd'); diff --git a/lib/screens/patients/In_patient/list_of_my_inpatient.dart b/lib/screens/patients/In_patient/list_of_my_inpatient.dart index fe861da4..85cef378 100644 --- a/lib/screens/patients/In_patient/list_of_my_inpatient.dart +++ b/lib/screens/patients/In_patient/list_of_my_inpatient.dart @@ -26,8 +26,10 @@ class ListOfMyInpatient extends StatelessWidget { margin: EdgeInsets.symmetric(horizontal: 16.0), child: patientSearchViewModel.filteredMyInPatientItems.length == 0 ? NoData() - : NotificationListener( - child: ListView.builder( + : + NotificationListener( + child: + ListView.builder( itemCount: patientSearchViewModel.filteredMyInPatientItems.length, scrollDirection: Axis.vertical, diff --git a/lib/widgets/auth/sms-popup.dart b/lib/widgets/auth/sms-popup.dart index 98668ae1..0c36dad7 100644 --- a/lib/widgets/auth/sms-popup.dart +++ b/lib/widgets/auth/sms-popup.dart @@ -48,6 +48,7 @@ class SMSOTP { late ProjectViewModel projectProvider; String displayTime = ''; bool isClosed = false; + // final TurnstileController _controller = TurnstileController(); // final TurnstileOptions _options = TurnstileOptions( // size: TurnstileSize.normal, @@ -58,6 +59,7 @@ class SMSOTP { // ); String? _token; + displayDialog(BuildContext context) async { double dialogWidth = MediaQuery.of(context).size.width * 0.90; double dialogInputWidth = (dialogWidth / 4) - (SizeConfig.isWidthLarge ? SizeConfig.getWidthMultiplier(width: dialogWidth) * 4.5 : 20); @@ -76,8 +78,8 @@ class SMSOTP { child: Container( color: Colors.white, child: StatefulBuilder(builder: (context, setState) { - if (displayTime == '') { - startTimer(setState); + if (displayTime == '' && context.mounted) { + startTimer(setState, context); } return Center( @@ -246,7 +248,6 @@ class SMSOTP { )), ), ), - Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ AppText( TranslationBase.of(context).validationMessage + ' ', @@ -264,34 +265,38 @@ class SMSOTP { fontSize: SizeConfig.getTextMultiplierBasedOnWidth(width: dialogWidth) * 3.5, ) ]), - SizedBox(height: 10,), - Column(children: [ - // CloudflareTurnstile( - // siteKey: '0x4AAAAAAAkmbvEy63pcxBBt', - // baseUrl: BASE_URL, - // options: _options, - // controller: _controller, - // onTokenReceived: (token) { - // setState(() { - // print("Cloudflare token: $token"); - // //todo pass this token to checkActivcationCode - // _token = token; - // checkValue(); - // }); - // }, - // // onTokenRecived: (token) { - // // setState(() { - // // print("Cloudflare token: $token"); - // // _token = token; - // // }); - // // }, - // onTokenExpired: () {}, - // // mode: TurnstileMode.managed, - // // errorBuilder: (context, error) { - // // return Text(error.message); - // // }, - // ), - ],), + SizedBox( + height: 10, + ), + Column( + children: [ + // CloudflareTurnstile( + // siteKey: '0x4AAAAAAAkmbvEy63pcxBBt', + // baseUrl: BASE_URL, + // options: _options, + // controller: _controller, + // onTokenReceived: (token) { + // setState(() { + // print("Cloudflare token: $token"); + // //todo pass this token to checkActivcationCode + // _token = token; + // checkValue(); + // }); + // }, + // // onTokenRecived: (token) { + // // setState(() { + // // print("Cloudflare token: $token"); + // // _token = token; + // // }); + // // }, + // onTokenExpired: () {}, + // // mode: TurnstileMode.managed, + // // errorBuilder: (context, error) { + // // return Text(error.message); + // // }, + // ), + ], + ), ], ), ), @@ -344,7 +349,8 @@ class SMSOTP { } checkValue() async { - if (verifyAccountForm.currentState!.validate() ) { //&& _token !=null removed cloud flare for vida plus + if (verifyAccountForm.currentState!.validate()) { + //&& _token !=null removed cloud flare for vida plus // if (digit1.text.isNotEmpty && digit2.text.isNotEmpty && digit3.text.isNotEmpty && digit4.text.isNotEmpty) { onSuccess(digit1.text.toString() + digit2.text.toString() + digit3.text.toString() + digit4.text.toString()); this.isClosed = true; @@ -363,8 +369,11 @@ class SMSOTP { return minutesString + ":" + secondsString; } - startTimer(setState) { + startTimer(setState, BuildContext context) { this.remainingTime--; + if (context.mounted == false) { + return; + } setState(() { displayTime = this.getSecondsAsDigitalClock(this.remainingTime); }); @@ -372,7 +381,7 @@ class SMSOTP { Future.delayed(Duration(seconds: 1), () { if (this.remainingTime > 0) { if (isClosed == false) { - startTimer(setState); + startTimer(setState,context); } } else { Navigator.pop(context);