diff options
author | fiaxh <git@lightrise.org> | 2021-05-11 12:57:02 +0200 |
---|---|---|
committer | fiaxh <git@lightrise.org> | 2021-05-11 12:57:02 +0200 |
commit | d71604913dd5b3372a823320db83c37c845fac5c (patch) | |
tree | 2ffbff97a02c81d48d8aef4a4b7ee870507236e9 /main/src/ui/call_window/call_window_controller.vala | |
parent | e92ed27317ae398c867c946cf7206b1f0b32f3b4 (diff) | |
parent | 90f9ecf62b2ebfef14de2874e7942552409632bf (diff) | |
download | dino-d71604913dd5b3372a823320db83c37c845fac5c.tar.gz dino-d71604913dd5b3372a823320db83c37c845fac5c.zip |
Merge remote-tracking branch 'origin/feature/calls'
Diffstat (limited to 'main/src/ui/call_window/call_window_controller.vala')
-rw-r--r-- | main/src/ui/call_window/call_window_controller.vala | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/main/src/ui/call_window/call_window_controller.vala b/main/src/ui/call_window/call_window_controller.vala new file mode 100644 index 00000000..b07b41b1 --- /dev/null +++ b/main/src/ui/call_window/call_window_controller.vala @@ -0,0 +1,254 @@ +using Dino.Entities; +using Gtk; + +public class Dino.Ui.CallWindowController : Object { + + private CallWindow call_window; + private Call call; + private Conversation conversation; + private StreamInteractor stream_interactor; + private Calls calls; + private Plugins.VideoCallPlugin call_plugin = Dino.Application.get_default().plugin_registry.video_call_plugin; + + private Plugins.VideoCallWidget? own_video = null; + private Plugins.VideoCallWidget? counterpart_video = null; + private int window_height = -1; + private int window_width = -1; + private bool window_size_changed = false; + + public CallWindowController(CallWindow call_window, Call call, StreamInteractor stream_interactor) { + this.call_window = call_window; + this.call = call; + this.stream_interactor = stream_interactor; + + this.calls = stream_interactor.get_module(Calls.IDENTITY); + this.conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation(call.counterpart.bare_jid, call.account, Conversation.Type.CHAT); + this.own_video = call_plugin.create_widget(Plugins.WidgetType.GTK); + this.counterpart_video = call_plugin.create_widget(Plugins.WidgetType.GTK); + + call_window.counterpart_display_name = Util.get_conversation_display_name(stream_interactor, conversation); + call_window.set_default_size(704, 528); // 640x480 * 1.1 + call_window.set_video_fallback(stream_interactor, conversation); + + this.call_window.bottom_bar.video_enabled = calls.should_we_send_video(call); + + if (call.direction == Call.DIRECTION_INCOMING) { + call_window.set_status("establishing"); + } else { + call_window.set_status("requested"); + } + + call_window.bottom_bar.hang_up.connect(() => { + calls.end_call(conversation, call); + call_window.close(); + call_window.destroy(); + this.dispose(); + }); + call_window.destroy.connect(() => { + calls.end_call(conversation, call); + this.dispose(); + }); + + call_window.bottom_bar.notify["audio-enabled"].connect(() => { + calls.mute_own_audio(call, !call_window.bottom_bar.audio_enabled); + }); + call_window.bottom_bar.notify["video-enabled"].connect(() => { + calls.mute_own_video(call, !call_window.bottom_bar.video_enabled); + update_own_video(); + }); + + calls.counterpart_sends_video_updated.connect((call, mute) => { + if (!this.call.equals(call)) return; + + if (mute) { + call_window.set_video_fallback(stream_interactor, conversation); + counterpart_video.detach(); + } else { + if (!(counterpart_video is Widget)) return; + Widget widget = (Widget) counterpart_video; + call_window.set_video(widget); + counterpart_video.display_stream(calls.get_video_stream(call)); + } + }); + calls.info_received.connect((call, session_info) => { + if (!this.call.equals(call)) return; + if (session_info == Xmpp.Xep.JingleRtp.CallSessionInfo.RINGING) { + call_window.set_status("ringing"); + } + }); + calls.encryption_updated.connect((call, audio_encryption, video_encryption, same) => { + if (!this.call.equals(call)) return; + + string? title = null; + string? icon_name = null; + bool show_keys = true; + Plugins.Registry registry = Dino.Application.get_default().plugin_registry; + Plugins.CallEncryptionEntry? encryption_entry = audio_encryption != null ? registry.call_encryption_entries[audio_encryption.encryption_ns] : null; + if (encryption_entry != null) { + Plugins.CallEncryptionWidget? encryption_widgets = encryption_entry.get_widget(call.account, audio_encryption); + if (encryption_widgets != null) { + title = encryption_widgets.get_title(); + icon_name = encryption_widgets.get_icon_name(); + show_keys = encryption_widgets.show_keys(); + } + } + call_window.bottom_bar.encryption_button.set_info(title, show_keys, audio_encryption, same ? null :video_encryption); + call_window.bottom_bar.encryption_button.set_icon(audio_encryption != null, icon_name); + }); + + own_video.resolution_changed.connect((width, height) => { + if (width == 0 || height == 0) return; + call_window.set_own_video_ratio((int)width, (int)height); + }); + counterpart_video.resolution_changed.connect((width, height) => { + if (window_size_changed) return; + if (width == 0 || height == 0) return; + if (width > height) { + call_window.resize(704, (int) (height * 704 / width)); + } else { + call_window.resize((int) (width * 704 / height), 704); + } + capture_window_size(); + }); + call_window.configure_event.connect((event) => { + if (window_width == -1 || window_height == -1) return false; + int current_height = this.call_window.get_allocated_height(); + int current_width = this.call_window.get_allocated_width(); + if (window_width != current_width || window_height != current_height) { + debug("Call window size changed by user. Disabling auto window-to-video size adaptation. %i->%i x %i->%i", window_width, current_width, window_height, current_height); + window_size_changed = true; + } + return false; + }); + call_window.realize.connect(() => { + capture_window_size(); + }); + + call.notify["state"].connect(on_call_state_changed); + calls.call_terminated.connect(on_call_terminated); + + update_own_video(); + } + + private void capture_window_size() { + Allocation allocation; + this.call_window.get_allocation(out allocation); + this.window_height = this.call_window.get_allocated_height(); + this.window_width = this.call_window.get_allocated_width(); + } + + private void on_call_state_changed() { + if (call.state == Call.State.IN_PROGRESS) { + call_window.set_status(""); + call_plugin.devices_changed.connect((media, incoming) => { + if (media == "audio") update_audio_device_choices(); + if (media == "video") update_video_device_choices(); + }); + + update_audio_device_choices(); + update_video_device_choices(); + } + } + + private void on_call_terminated(Call call, string? reason_name, string? reason_text) { + call_window.show_counterpart_ended(reason_name, reason_text); + Timeout.add_seconds(3, () => { + call.notify["state"].disconnect(on_call_state_changed); + calls.call_terminated.disconnect(on_call_terminated); + + + call_window.close(); + call_window.destroy(); + + return false; + }); + } + + private void update_audio_device_choices() { + if (call_plugin.get_devices("audio", true).size == 0 || call_plugin.get_devices("audio", false).size == 0) { + call_window.bottom_bar.show_audio_device_error(); + } /*else if (call_plugin.get_devices("audio", true).size == 1 && call_plugin.get_devices("audio", false).size == 1) { + call_window.bottom_bar.show_audio_device_choices(false); + return; + } + + AudioSettingsPopover? audio_settings_popover = call_window.bottom_bar.show_audio_device_choices(true); + update_current_audio_device(audio_settings_popover); + + audio_settings_popover.microphone_selected.connect((device) => { + call_plugin.set_device(calls.get_audio_stream(call), device); + update_current_audio_device(audio_settings_popover); + }); + audio_settings_popover.speaker_selected.connect((device) => { + call_plugin.set_device(calls.get_audio_stream(call), device); + update_current_audio_device(audio_settings_popover); + }); + calls.stream_created.connect((call, media) => { + if (media == "audio") { + update_current_audio_device(audio_settings_popover); + } + });*/ + } + + private void update_current_audio_device(AudioSettingsPopover audio_settings_popover) { + Xmpp.Xep.JingleRtp.Stream stream = calls.get_audio_stream(call); + if (stream != null) { + audio_settings_popover.current_microphone_device = call_plugin.get_device(stream, false); + audio_settings_popover.current_speaker_device = call_plugin.get_device(stream, true); + } + } + + private void update_video_device_choices() { + int device_count = call_plugin.get_devices("video", false).size; + + if (device_count == 0) { + call_window.bottom_bar.show_video_device_error(); + } /*else if (device_count == 1 || calls.get_video_stream(call) == null) { + call_window.bottom_bar.show_video_device_choices(false); + return; + } + + VideoSettingsPopover? video_settings_popover = call_window.bottom_bar.show_video_device_choices(true); + update_current_video_device(video_settings_popover); + + video_settings_popover.camera_selected.connect((device) => { + call_plugin.set_device(calls.get_video_stream(call), device); + update_current_video_device(video_settings_popover); + own_video.display_device(device); + }); + calls.stream_created.connect((call, media) => { + if (media == "video") { + update_current_video_device(video_settings_popover); + } + });*/ + } + + private void update_current_video_device(VideoSettingsPopover video_settings_popover) { + Xmpp.Xep.JingleRtp.Stream stream = calls.get_video_stream(call); + if (stream != null) { + video_settings_popover.current_device = call_plugin.get_device(stream, false); + } + } + + private void update_own_video() { + if (this.call_window.bottom_bar.video_enabled) { + Gee.List<Plugins.MediaDevice> devices = call_plugin.get_devices("video", false); + if (!(own_video is Widget) || devices.is_empty) { + call_window.set_own_video(null); + } else { + Widget widget = (Widget) own_video; + call_window.set_own_video(widget); + own_video.display_device(devices.first()); + } + } else { + own_video.detach(); + call_window.unset_own_video(); + } + } + + public override void dispose() { + base.dispose(); + call.notify["state"].disconnect(on_call_state_changed); + calls.call_terminated.disconnect(on_call_terminated); + } +}
\ No newline at end of file |