From 369d0c79d7272b4059c39ecedb10a62121bfbe56 Mon Sep 17 00:00:00 2001 From: Marvin W Date: Sat, 12 Feb 2022 14:35:44 +0100 Subject: Calls: Fix device selector for multi-party calls, allow picking device before call started --- libdino/src/plugin/interfaces.vala | 14 +++++---- libdino/src/service/call_state.vala | 59 +++++++++++++++++++++++++++++++------ 2 files changed, 59 insertions(+), 14 deletions(-) (limited to 'libdino') diff --git a/libdino/src/plugin/interfaces.vala b/libdino/src/plugin/interfaces.vala index b6955a6b..c7c2c375 100644 --- a/libdino/src/plugin/interfaces.vala +++ b/libdino/src/plugin/interfaces.vala @@ -103,16 +103,17 @@ public abstract interface VideoCallPlugin : Object { // Devices public signal void devices_changed(string media, bool incoming); public abstract Gee.List get_devices(string media, bool incoming); - public abstract MediaDevice? get_device(Xmpp.Xep.JingleRtp.Stream stream, bool incoming); - public abstract void set_pause(Xmpp.Xep.JingleRtp.Stream stream, bool pause); - public abstract void set_device(Xmpp.Xep.JingleRtp.Stream stream, MediaDevice? device); + public abstract MediaDevice? get_preferred_device(string media, bool incoming); + public abstract MediaDevice? get_device(Xmpp.Xep.JingleRtp.Stream? stream, bool incoming); + public abstract void set_pause(Xmpp.Xep.JingleRtp.Stream? stream, bool pause); + public abstract void set_device(Xmpp.Xep.JingleRtp.Stream? stream, MediaDevice? device); public abstract void dump_dot(); } public abstract interface VideoCallWidget : Object { public signal void resolution_changed(uint width, uint height); - public abstract void display_stream(Xmpp.Xep.JingleRtp.Stream stream, Jid jid); + public abstract void display_stream(Xmpp.Xep.JingleRtp.Stream? stream, Jid jid); public abstract void display_device(MediaDevice device); public abstract void detach(); } @@ -120,7 +121,10 @@ public abstract interface VideoCallWidget : Object { public abstract interface MediaDevice : Object { public abstract string id { owned get; } public abstract string display_name { owned get; } - public abstract string detail_name { owned get; } + public abstract string? detail_name { owned get; } + + public abstract string? media { owned get; } + public abstract bool incoming { get; } } public abstract interface NotificationPopulator : Object { diff --git a/libdino/src/service/call_state.vala b/libdino/src/service/call_state.vala index c403fc6a..c1f0522d 100644 --- a/libdino/src/service/call_state.vala +++ b/libdino/src/service/call_state.vala @@ -26,6 +26,10 @@ public class Dino.CallState : Object { public HashMap peers = new HashMap(Jid.hash_func, Jid.equals_func); + private Plugins.MediaDevice selected_microphone_device; + private Plugins.MediaDevice selected_speaker_device; + private Plugins.MediaDevice selected_video_device; + public CallState(Call call, StreamInteractor stream_interactor) { this.call = call; this.stream_interactor = stream_interactor; @@ -80,6 +84,15 @@ public class Dino.CallState : Object { peer_joined(peer.jid, peer); } + internal void on_peer_stream_created(PeerState peer, string media) { + if (media == "audio") { + call_plugin.set_device(peer.get_audio_stream(), get_microphone_device()); + call_plugin.set_device(peer.get_audio_stream(), get_speaker_device()); + } else if (media == "video") { + call_plugin.set_device(peer.get_video_stream(), get_video_device()); + } + } + public void accept() { accepted = true; call.state = Call.State.ESTABLISHING; @@ -206,30 +219,57 @@ public class Dino.CallState : Object { } public Plugins.MediaDevice? get_microphone_device() { - if (peers.is_empty) return null; - var audio_stream = peers.values.to_array()[0].get_audio_stream(); - return call_plugin.get_device(audio_stream, false); + if (selected_microphone_device == null) { + if (!peers.is_empty) { + var audio_stream = peers.values.to_array()[0].get_audio_stream(); + selected_microphone_device = call_plugin.get_device(audio_stream, false); + } + if (selected_microphone_device == null) { + selected_microphone_device = call_plugin.get_preferred_device("audio", false); + } + } + return selected_microphone_device; } public Plugins.MediaDevice? get_speaker_device() { - if (peers.is_empty) return null; - var audio_stream = peers.values.to_array()[0].get_audio_stream(); - return call_plugin.get_device(audio_stream, true); + if (selected_speaker_device == null) { + if (!peers.is_empty) { + var audio_stream = peers.values.to_array()[0].get_audio_stream(); + selected_speaker_device = call_plugin.get_device(audio_stream, true); + } + if (selected_speaker_device == null) { + selected_speaker_device = call_plugin.get_preferred_device("audio", true); + } + } + return selected_speaker_device; } public Plugins.MediaDevice? get_video_device() { - if (peers.is_empty) return null; - var video_stream = peers.values.to_array()[0].get_video_stream(); - return call_plugin.get_device(video_stream, false); + if (selected_video_device == null) { + if (!peers.is_empty) { + var video_stream = peers.values.to_array()[0].get_video_stream(); + selected_video_device = call_plugin.get_device(video_stream, false); + } + if (selected_video_device == null) { + selected_video_device = call_plugin.get_preferred_device("video", false); + } + } + return selected_video_device; } public void set_audio_device(Plugins.MediaDevice? device) { + if (device.incoming) { + selected_speaker_device = device; + } else { + selected_microphone_device = device; + } foreach (PeerState peer_state in peers.values) { call_plugin.set_device(peer_state.get_audio_stream(), device); } } public void set_video_device(Plugins.MediaDevice? device) { + selected_video_device = device; foreach (PeerState peer_state in peers.values) { call_plugin.set_device(peer_state.get_video_stream(), device); } @@ -270,6 +310,7 @@ public class Dino.CallState : Object { this.bind_property("we-should-send-video", peer_state, "we-should-send-video", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL); this.bind_property("group-call", peer_state, "group-call", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL); + peer_state.stream_created.connect((peer, media) => { on_peer_stream_created(peer, media); }); peer_state.session_terminated.connect((we_terminated, reason_name, reason_text) => { debug("[%s] Peer left %s: %s %s (%i peers remaining)", call.account.bare_jid.to_string(), reason_text ?? "", reason_name ?? "", peer_state.jid.to_string(), peers.size); handle_peer_left(peer_state, we_terminated, reason_name, reason_text); -- cgit v1.2.3-54-g00ecf