Switch from audio only to active speaker using toggle video button (instead of disabling it)
This commit is contained in:
parent
cf3b68cc1b
commit
791e27f479
4 changed files with 54 additions and 23 deletions
|
@ -81,6 +81,15 @@ class ConferenceCallFragment : GenericFragment<VoipConferenceCallFragmentBinding
|
||||||
|
|
||||||
binding.statsViewModel = statsViewModel
|
binding.statsViewModel = statsViewModel
|
||||||
|
|
||||||
|
conferenceViewModel.reloadConferenceFragmentEvent.observe(
|
||||||
|
viewLifecycleOwner
|
||||||
|
) {
|
||||||
|
it.consume {
|
||||||
|
Log.i("[Conference Call] Reloading fragment after toggling video ON while in AUDIO_ONLY layout")
|
||||||
|
refreshConferenceFragment()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
conferenceViewModel.conferenceDisplayMode.observe(
|
conferenceViewModel.conferenceDisplayMode.observe(
|
||||||
viewLifecycleOwner
|
viewLifecycleOwner
|
||||||
) { displayMode ->
|
) { displayMode ->
|
||||||
|
@ -101,6 +110,16 @@ class ConferenceCallFragment : GenericFragment<VoipConferenceCallFragmentBinding
|
||||||
coreContext.core.nativeVideoWindowId = null
|
coreContext.core.nativeVideoWindowId = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
when (displayMode) {
|
||||||
|
ConferenceDisplayMode.AUDIO_ONLY -> {
|
||||||
|
controlsViewModel.fullScreenMode.value = false
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
val conference = conferenceViewModel.conference.value
|
||||||
|
if (conference != null) switchToFullScreenIfPossible(conference)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
conferenceViewModel.conferenceParticipantDevices.observe(
|
conferenceViewModel.conferenceParticipantDevices.observe(
|
||||||
|
@ -111,7 +130,7 @@ class ConferenceCallFragment : GenericFragment<VoipConferenceCallFragmentBinding
|
||||||
it.size > conferenceViewModel.maxParticipantsForMosaicLayout
|
it.size > conferenceViewModel.maxParticipantsForMosaicLayout
|
||||||
) {
|
) {
|
||||||
Log.w("[Conference Call] More than ${conferenceViewModel.maxParticipantsForMosaicLayout} participants (${it.size}), forcing active speaker layout")
|
Log.w("[Conference Call] More than ${conferenceViewModel.maxParticipantsForMosaicLayout} participants (${it.size}), forcing active speaker layout")
|
||||||
conferenceViewModel.changeLayout(ConferenceDisplayMode.ACTIVE_SPEAKER)
|
conferenceViewModel.changeLayout(ConferenceDisplayMode.ACTIVE_SPEAKER, false)
|
||||||
refreshConferenceFragment()
|
refreshConferenceFragment()
|
||||||
// Can't use SnackBar whilst changing fragment
|
// Can't use SnackBar whilst changing fragment
|
||||||
Toast.makeText(requireContext(), R.string.conference_too_many_participants_for_mosaic_layout, Toast.LENGTH_LONG).show()
|
Toast.makeText(requireContext(), R.string.conference_too_many_participants_for_mosaic_layout, Toast.LENGTH_LONG).show()
|
||||||
|
@ -149,20 +168,6 @@ class ConferenceCallFragment : GenericFragment<VoipConferenceCallFragmentBinding
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
conferenceViewModel.conferenceDisplayMode.observe(
|
|
||||||
viewLifecycleOwner
|
|
||||||
) { layout ->
|
|
||||||
when (layout) {
|
|
||||||
ConferenceDisplayMode.AUDIO_ONLY -> {
|
|
||||||
controlsViewModel.fullScreenMode.value = false
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
val conference = conferenceViewModel.conference.value
|
|
||||||
if (conference != null) switchToFullScreenIfPossible(conference)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
conferenceViewModel.firstToJoinEvent.observe(
|
conferenceViewModel.firstToJoinEvent.observe(
|
||||||
viewLifecycleOwner
|
viewLifecycleOwner
|
||||||
) {
|
) {
|
||||||
|
@ -272,14 +277,14 @@ class ConferenceCallFragment : GenericFragment<VoipConferenceCallFragmentBinding
|
||||||
if (conference.currentParams.isVideoEnabled) {
|
if (conference.currentParams.isVideoEnabled) {
|
||||||
when {
|
when {
|
||||||
conference.me.devices.isEmpty() -> {
|
conference.me.devices.isEmpty() -> {
|
||||||
Log.w("[Conference Call] Conference has video enabled but either our device hasn't joined yet")
|
Log.i("[Conference Call] Conference has video enabled but our device hasn't joined yet")
|
||||||
}
|
}
|
||||||
conference.me.devices.find { it.isInConference && it.getStreamAvailability(StreamType.Video) } != null -> {
|
conference.me.devices.find { it.isInConference && it.getStreamAvailability(StreamType.Video) } != null -> {
|
||||||
Log.i("[Conference Call] Conference has video enabled & our device has video enabled, enabling full screen mode")
|
Log.i("[Conference Call] Conference has video enabled & our device has video enabled, enabling full screen mode")
|
||||||
controlsViewModel.fullScreenMode.value = true
|
controlsViewModel.fullScreenMode.value = true
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
Log.w("[Conference Call] Conference has video enabled but our device video is disabled")
|
Log.i("[Conference Call] Conference has video enabled but our device video is disabled")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,12 @@ class ConferenceViewModel : ViewModel() {
|
||||||
MutableLiveData<Event<Boolean>>()
|
MutableLiveData<Event<Boolean>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var waitForNextStreamsRunningToUpdateLayout = false
|
||||||
|
|
||||||
|
val reloadConferenceFragmentEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||||
|
MutableLiveData<Event<Boolean>>()
|
||||||
|
}
|
||||||
|
|
||||||
private val conferenceListener = object : ConferenceListenerStub() {
|
private val conferenceListener = object : ConferenceListenerStub() {
|
||||||
override fun onParticipantAdded(conference: Conference, participant: Participant) {
|
override fun onParticipantAdded(conference: Conference, participant: Participant) {
|
||||||
Log.i("[Conference] Participant added: ${participant.address.asStringUriOnly()}")
|
Log.i("[Conference] Participant added: ${participant.address.asStringUriOnly()}")
|
||||||
|
@ -218,6 +224,18 @@ class ConferenceViewModel : ViewModel() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onCallStateChanged(
|
||||||
|
core: Core,
|
||||||
|
call: Call,
|
||||||
|
state: Call.State?,
|
||||||
|
message: String
|
||||||
|
) {
|
||||||
|
if (state == Call.State.StreamsRunning && waitForNextStreamsRunningToUpdateLayout) {
|
||||||
|
waitForNextStreamsRunningToUpdateLayout = false
|
||||||
|
reloadConferenceFragmentEvent.value = Event(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
@ -340,7 +358,14 @@ class ConferenceViewModel : ViewModel() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun changeLayout(layout: ConferenceDisplayMode) {
|
fun switchLayoutFromAudioOnlyToActiveSpeaker() {
|
||||||
|
if (conferenceDisplayMode.value == ConferenceDisplayMode.AUDIO_ONLY) {
|
||||||
|
changeLayout(ConferenceDisplayMode.ACTIVE_SPEAKER, true)
|
||||||
|
waitForNextStreamsRunningToUpdateLayout = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun changeLayout(layout: ConferenceDisplayMode, forceSendingVideo: Boolean) {
|
||||||
Log.i("[Conference] Trying to change conference layout to $layout")
|
Log.i("[Conference] Trying to change conference layout to $layout")
|
||||||
val conference = conference.value
|
val conference = conference.value
|
||||||
if (conference != null) {
|
if (conference != null) {
|
||||||
|
@ -353,6 +378,7 @@ class ConferenceViewModel : ViewModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
params.isVideoEnabled = layout != ConferenceDisplayMode.AUDIO_ONLY
|
params.isVideoEnabled = layout != ConferenceDisplayMode.AUDIO_ONLY
|
||||||
|
if (forceSendingVideo) params.videoDirection = MediaDirection.SendRecv
|
||||||
params.conferenceVideoLayout = when (layout) {
|
params.conferenceVideoLayout = when (layout) {
|
||||||
ConferenceDisplayMode.GRID -> ConferenceLayout.Grid
|
ConferenceDisplayMode.GRID -> ConferenceLayout.Grid
|
||||||
else -> ConferenceLayout.ActiveSpeaker
|
else -> ConferenceLayout.ActiveSpeaker
|
||||||
|
|
|
@ -96,8 +96,8 @@
|
||||||
android:layout_marginStart="5dp"
|
android:layout_marginStart="5dp"
|
||||||
android:background="@drawable/button_background_reverse"
|
android:background="@drawable/button_background_reverse"
|
||||||
android:contentDescription="@{controlsViewModel.isVideoEnabled && controlsViewModel.isSendingVideo ? @string/content_description_disable_video : @string/content_description_enable_video}"
|
android:contentDescription="@{controlsViewModel.isVideoEnabled && controlsViewModel.isSendingVideo ? @string/content_description_disable_video : @string/content_description_enable_video}"
|
||||||
android:enabled="@{controlsViewModel.isVideoAvailable && !controlsViewModel.isVideoUpdateInProgress && conferenceViewModel.conferenceDisplayMode != ConferenceDisplayMode.AUDIO_ONLY}"
|
android:enabled="@{controlsViewModel.isVideoAvailable && !controlsViewModel.isVideoUpdateInProgress}"
|
||||||
android:onClick="@{() -> controlsViewModel.toggleVideo()}"
|
android:onClick="@{() -> conferenceViewModel.conferenceDisplayMode != ConferenceDisplayMode.AUDIO_ONLY ? controlsViewModel.toggleVideo() : conferenceViewModel.switchLayoutFromAudioOnlyToActiveSpeaker()}"
|
||||||
android:padding="5dp"
|
android:padding="5dp"
|
||||||
android:selected="@{controlsViewModel.isVideoEnabled && controlsViewModel.isSendingVideo}"
|
android:selected="@{controlsViewModel.isVideoEnabled && controlsViewModel.isSendingVideo}"
|
||||||
android:src="@drawable/icon_toggle_camera"
|
android:src="@drawable/icon_toggle_camera"
|
||||||
|
|
|
@ -79,7 +79,7 @@
|
||||||
android:drawableEnd="@drawable/icon_conference_layout_grid"
|
android:drawableEnd="@drawable/icon_conference_layout_grid"
|
||||||
android:drawableTint="?attr/voipDrawableColor"
|
android:drawableTint="?attr/voipDrawableColor"
|
||||||
android:enabled="@{conferenceViewModel.conferenceParticipantDevices.size() > conferenceViewModel.maxParticipantsForMosaicLayout ? false : true}"
|
android:enabled="@{conferenceViewModel.conferenceParticipantDevices.size() > conferenceViewModel.maxParticipantsForMosaicLayout ? false : true}"
|
||||||
android:onClickListener="@{() -> conferenceViewModel.changeLayout(ConferenceDisplayMode.GRID)}"
|
android:onClickListener="@{() -> conferenceViewModel.changeLayout(ConferenceDisplayMode.GRID, false)}"
|
||||||
android:text="@string/conference_display_mode_mosaic" />
|
android:text="@string/conference_display_mode_mosaic" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
|
@ -97,7 +97,7 @@
|
||||||
android:checked="@{conferenceViewModel.conferenceDisplayMode == ConferenceDisplayMode.ACTIVE_SPEAKER}"
|
android:checked="@{conferenceViewModel.conferenceDisplayMode == ConferenceDisplayMode.ACTIVE_SPEAKER}"
|
||||||
android:drawableEnd="@drawable/icon_conference_layout_active_speaker"
|
android:drawableEnd="@drawable/icon_conference_layout_active_speaker"
|
||||||
android:drawableTint="?attr/voipDrawableColor"
|
android:drawableTint="?attr/voipDrawableColor"
|
||||||
android:onClickListener="@{() -> conferenceViewModel.changeLayout(ConferenceDisplayMode.ACTIVE_SPEAKER)}"
|
android:onClickListener="@{() -> conferenceViewModel.changeLayout(ConferenceDisplayMode.ACTIVE_SPEAKER, false)}"
|
||||||
android:text="@string/conference_display_mode_active_speaker" />
|
android:text="@string/conference_display_mode_active_speaker" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
|
@ -115,7 +115,7 @@
|
||||||
android:checked="@{conferenceViewModel.conferenceDisplayMode == ConferenceDisplayMode.AUDIO_ONLY}"
|
android:checked="@{conferenceViewModel.conferenceDisplayMode == ConferenceDisplayMode.AUDIO_ONLY}"
|
||||||
android:drawableEnd="@drawable/icon_conference_layout_audio_only"
|
android:drawableEnd="@drawable/icon_conference_layout_audio_only"
|
||||||
android:drawableTint="?attr/voipDrawableColor"
|
android:drawableTint="?attr/voipDrawableColor"
|
||||||
android:onClickListener="@{() -> conferenceViewModel.changeLayout(ConferenceDisplayMode.AUDIO_ONLY)}"
|
android:onClickListener="@{() -> conferenceViewModel.changeLayout(ConferenceDisplayMode.AUDIO_ONLY, false)}"
|
||||||
android:text="@string/conference_display_mode_audio_only" />
|
android:text="@string/conference_display_mode_audio_only" />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
|
|
Loading…
Reference in a new issue