Handle non-existant call support
This commit is contained in:
parent
3880628de4
commit
5d85b6cdb0
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue