aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libdino/src/plugin/interfaces.vala2
-rw-r--r--libdino/src/service/calls.vala38
-rw-r--r--main/src/ui/conversation_titlebar/call_entry.vala13
-rw-r--r--plugins/rtp/src/codec_util.vala1
-rw-r--r--plugins/rtp/src/module.vala6
-rw-r--r--plugins/rtp/src/plugin.vala16
6 files changed, 65 insertions, 11 deletions
diff --git a/libdino/src/plugin/interfaces.vala b/libdino/src/plugin/interfaces.vala
index 8be77895..97951850 100644
--- a/libdino/src/plugin/interfaces.vala
+++ b/libdino/src/plugin/interfaces.vala
@@ -85,6 +85,8 @@ public abstract interface ConversationAdditionPopulator : ConversationItemPopula
}
public abstract interface VideoCallPlugin : Object {
+
+ public abstract bool supports(string media);
// Video widget
public abstract VideoCallWidget? create_widget(WidgetType type);
diff --git a/libdino/src/service/calls.vala b/libdino/src/service/calls.vala
index b7374607..1d47823d 100644
--- a/libdino/src/service/calls.vala
+++ b/libdino/src/service/calls.vala
@@ -83,7 +83,7 @@ namespace Dino {
we_should_send_video[call] = video;
we_should_send_audio[call] = true;
- if (yield has_jmi_resources(conversation)) {
+ if (has_jmi_resources(conversation)) {
XmppStream? stream = stream_interactor.get_stream(conversation.account);
jmi_call[conversation.account] = call;
jmi_video[conversation.account] = video;
@@ -245,8 +245,28 @@ namespace Dino {
// If video_feed == null && !mute we're trying to mute a non-existant feed. It will be muted as soon as it is created.
}
- public async bool can_do_calls(Conversation conversation) {
- return (yield get_call_resources(conversation)).size > 0 || yield has_jmi_resources(conversation);
+ public async bool can_do_audio_calls_async(Conversation conversation) {
+ if (!can_do_audio_calls()) return false;
+ return (yield get_call_resources(conversation)).size > 0 || has_jmi_resources(conversation);
+ }
+
+ private bool can_do_audio_calls() {
+ Plugins.VideoCallPlugin? plugin = Application.get_default().plugin_registry.video_call_plugin;
+ if (plugin == null) return false;
+
+ return plugin.supports("audio");
+ }
+
+ public async bool can_do_video_calls_async(Conversation conversation) {
+ if (!can_do_video_calls()) return false;
+ return (yield get_call_resources(conversation)).size > 0 || has_jmi_resources(conversation);
+ }
+
+ private bool can_do_video_calls() {
+ Plugins.VideoCallPlugin? plugin = Application.get_default().plugin_registry.video_call_plugin;
+ if (plugin == null) return false;
+
+ return plugin.supports("video");
}
private async Gee.List<Jid> get_call_resources(Conversation conversation) {
@@ -266,7 +286,7 @@ namespace Dino {
return ret;
}
- private async bool has_jmi_resources(Conversation conversation) {
+ private bool has_jmi_resources(Conversation conversation) {
int64 jmi_resources = db.entity.select()
.with(db.entity.jid_id, "=", db.get_jid_id(conversation.counterpart))
.join_with(db.entity_feature, db.entity.caps_hash, db.entity_feature.entity)
@@ -289,6 +309,11 @@ namespace Dino {
}
private void on_incoming_call(Account account, Xep.Jingle.Session session) {
+ if (!can_do_audio_calls()) {
+ warning("Incoming call but no call support detected. Ignoring.");
+ return;
+ }
+
bool counterpart_wants_video = false;
foreach (Xep.Jingle.Content content in session.contents) {
Xep.JingleRtp.Parameters? rtp_content_parameter = content.content_params as Xep.JingleRtp.Parameters;
@@ -550,6 +575,11 @@ namespace Dino {
Xep.JingleMessageInitiation.Module mi_module = stream_interactor.module_manager.get_module(account, Xep.JingleMessageInitiation.Module.IDENTITY);
mi_module.session_proposed.connect((from, to, sid, descriptions) => {
+ if (!can_do_audio_calls()) {
+ warning("Incoming call but no call support detected. Ignoring.");
+ return;
+ }
+
bool audio_requested = descriptions.any_match((description) => description.ns_uri == Xep.JingleRtp.NS_URI && description.get_attribute("media") == "audio");
bool video_requested = descriptions.any_match((description) => description.ns_uri == Xep.JingleRtp.NS_URI && description.get_attribute("media") == "video");
if (!audio_requested && !video_requested) return;
diff --git a/main/src/ui/conversation_titlebar/call_entry.vala b/main/src/ui/conversation_titlebar/call_entry.vala
index 5e28ecbe..e1d10e5c 100644
--- a/main/src/ui/conversation_titlebar/call_entry.vala
+++ b/main/src/ui/conversation_titlebar/call_entry.vala
@@ -34,6 +34,9 @@ namespace Dino.Ui {
private StreamInteractor stream_interactor;
private Conversation conversation;
+ private ModelButton audio_button = new ModelButton() { text="Audio call", visible=true };
+ private ModelButton video_button = new ModelButton() { text="Video call", visible=true };
+
public CallButton(StreamInteractor stream_interactor) {
this.stream_interactor = stream_interactor;
@@ -42,7 +45,6 @@ namespace Dino.Ui {
Gtk.PopoverMenu popover_menu = new Gtk.PopoverMenu();
Box box = new Box(Orientation.VERTICAL, 0) { margin=10, visible=true };
- ModelButton audio_button = new ModelButton() { text="Audio call", visible=true };
audio_button.clicked.connect(() => {
stream_interactor.get_module(Calls.IDENTITY).initiate_call.begin(conversation, false, (_, res) => {
Call call = stream_interactor.get_module(Calls.IDENTITY).initiate_call.end(res);
@@ -50,7 +52,7 @@ namespace Dino.Ui {
});
});
box.add(audio_button);
- ModelButton video_button = new ModelButton() { text="Video call", visible=true };
+
video_button.clicked.connect(() => {
stream_interactor.get_module(Calls.IDENTITY).initiate_call.begin(conversation, true, (_, res) => {
Call call = stream_interactor.get_module(Calls.IDENTITY).initiate_call.end(res);
@@ -116,9 +118,12 @@ namespace Dino.Ui {
private async void update_visibility() {
if (conversation.type_ == Conversation.Type.CHAT) {
Conversation conv_bak = conversation;
- bool can_do_calls = yield stream_interactor.get_module(Calls.IDENTITY).can_do_calls(conversation);
+ bool audio_works = yield stream_interactor.get_module(Calls.IDENTITY).can_do_audio_calls_async(conversation);
+ bool video_works = yield stream_interactor.get_module(Calls.IDENTITY).can_do_audio_calls_async(conversation);
if (conv_bak != conversation) return;
- visible = can_do_calls;
+
+ visible = audio_works;
+ video_button.visible = video_works;
} else {
visible = false;
}
diff --git a/plugins/rtp/src/codec_util.vala b/plugins/rtp/src/codec_util.vala
index 7537c11d..6a2438f1 100644
--- a/plugins/rtp/src/codec_util.vala
+++ b/plugins/rtp/src/codec_util.vala
@@ -225,6 +225,7 @@ public class Dino.Plugins.Rtp.CodecUtil {
}
public string? get_encode_element_name(string media, string? codec) {
+ if (!is_element_supported(get_pay_element_name(media, codec))) return null;
foreach (string candidate in get_encode_candidates(media, codec)) {
if (is_element_supported(candidate)) return candidate;
}
diff --git a/plugins/rtp/src/module.vala b/plugins/rtp/src/module.vala
index 52cc1880..13a21cd8 100644
--- a/plugins/rtp/src/module.vala
+++ b/plugins/rtp/src/module.vala
@@ -64,13 +64,13 @@ public class Dino.Plugins.Rtp.Module : JingleRtp.Module {
}
private async bool is_payload_supported(string media, JingleRtp.PayloadType payload_type) {
- string codec = CodecUtil.get_codec_from_payload(media, payload_type);
+ string? codec = CodecUtil.get_codec_from_payload(media, payload_type);
if (codec == null) return false;
if (unsupported_codecs.contains(codec)) return false;
if (supported_codecs.contains(codec)) return true;
- string encode_element = codec_util.get_encode_element_name(media, codec);
- string decode_element = codec_util.get_decode_element_name(media, codec);
+ string? encode_element = codec_util.get_encode_element_name(media, codec);
+ string? decode_element = codec_util.get_decode_element_name(media, codec);
if (encode_element == null || decode_element == null) {
debug("No suitable encoder or decoder found for %s", codec);
unsupported_codecs.add(codec);
diff --git a/plugins/rtp/src/plugin.vala b/plugins/rtp/src/plugin.vala
index f0ad7db2..d43588b4 100644
--- a/plugins/rtp/src/plugin.vala
+++ b/plugins/rtp/src/plugin.vala
@@ -278,6 +278,22 @@ public class Dino.Plugins.Rtp.Plugin : RootInterface, VideoCallPlugin, Object {
Gst.deinit();
}
+ public bool supports(string media) {
+ if (rtpbin == null) return false;
+
+ if (media == "audio") {
+ if (get_devices("audio", false).is_empty) return false;
+ if (get_devices("audio", true).is_empty) return false;
+ }
+
+ if (media == "video") {
+ if (Gst.ElementFactory.make("gtksink", null) == null) return false;
+ if (get_devices("video", false).is_empty) return false;
+ }
+
+ return true;
+ }
+
public VideoCallWidget? create_widget(WidgetType type) {
if (type == WidgetType.GTK) {
return new VideoWidget(this);