aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfiaxh <git@lightrise.org>2021-12-20 00:15:05 +0100
committerfiaxh <git@lightrise.org>2021-12-23 00:19:26 +0100
commitf0c7dd0682fec8d72c644d8e54896de7bdc40ddb (patch)
tree0e275aa1fab7004cef7c92e16721d493b18bf8b6
parentff4e2540ae3bfab6873beb7e03ef5c6a5b9da1da (diff)
downloaddino-f0c7dd0682fec8d72c644d8e54896de7bdc40ddb.tar.gz
dino-f0c7dd0682fec8d72c644d8e54896de7bdc40ddb.zip
UI + libdino: Improve MUJI calls from MUC
- Move calls from ICE-thead onto main thread - Identify Call.ourpart as MUC nick if in MUC - Keep track of the initiator of a call
-rw-r--r--libdino/src/entity/call.vala9
-rw-r--r--libdino/src/service/call_peer_state.vala14
-rw-r--r--libdino/src/service/call_state.vala9
-rw-r--r--libdino/src/service/call_store.vala9
-rw-r--r--libdino/src/service/calls.vala24
-rw-r--r--libdino/src/service/content_item_store.vala4
-rw-r--r--libdino/src/service/muc_manager.vala2
-rw-r--r--main/data/call_widget.ui2
-rw-r--r--main/src/ui/application.vala18
-rw-r--r--main/src/ui/call_window/call_window.vala2
-rw-r--r--main/src/ui/conversation_content_view/call_widget.vala2
-rw-r--r--main/src/ui/conversation_titlebar/call_entry.vala18
-rw-r--r--main/src/ui/notifier_freedesktop.vala6
13 files changed, 75 insertions, 44 deletions
diff --git a/libdino/src/entity/call.vala b/libdino/src/entity/call.vala
index 3b48f664..8e5bc246 100644
--- a/libdino/src/entity/call.vala
+++ b/libdino/src/entity/call.vala
@@ -20,9 +20,12 @@ namespace Dino.Entities {
public int id { get; set; default=-1; }
public Account account { get; set; }
- public Jid counterpart { get; set; } // For backwards compatibility with db version 21. Not to be used anymore.
+ public Jid counterpart { get; set; }
public Gee.List<Jid> counterparts = new Gee.ArrayList<Jid>(Jid.equals_bare_func);
public Jid ourpart { get; set; }
+ public Jid proposer {
+ get { return direction == DIRECTION_OUTGOING ? ourpart : counterpart; }
+ }
public bool direction { get; set; }
public DateTime time { get; set; }
public DateTime local_time { get; set; }
@@ -58,7 +61,6 @@ namespace Dino.Entities {
if (!counterparts.contains(peer)) { // Legacy: The first peer is also in the `call` table. Don't add twice.
counterparts.add(peer);
}
- if (counterpart == null) counterpart = peer;
}
counterpart = db.get_jid_by_id(row[db.call.counterpart_id]);
@@ -66,7 +68,6 @@ namespace Dino.Entities {
if (counterpart_resource != null) counterpart = counterpart.with_resource(counterpart_resource);
if (counterparts.is_empty) {
counterparts.add(counterpart);
- counterpart = counterpart;
}
notify.connect(on_update);
@@ -107,8 +108,6 @@ namespace Dino.Entities {
}
public void add_peer(Jid peer) {
- if (counterpart == null) counterpart = peer;
-
if (counterparts.contains(peer)) return;
counterparts.add(peer);
diff --git a/libdino/src/service/call_peer_state.vala b/libdino/src/service/call_peer_state.vala
index 8c4b0930..09440371 100644
--- a/libdino/src/service/call_peer_state.vala
+++ b/libdino/src/service/call_peer_state.vala
@@ -127,8 +127,6 @@ public class Dino.PeerState : Object {
}
public void reject() {
- call.state = Call.State.DECLINED;
-
if (session != null) {
foreach (Xep.Jingle.Content content in session.contents) {
content.reject();
@@ -299,7 +297,12 @@ public class Dino.PeerState : Object {
debug(@"[%s] %s connecting content signals %s", call.account.bare_jid.to_string(), jid.to_string(), rtp_content_parameter.media);
rtp_content_parameter.stream_created.connect((stream) => on_stream_created(rtp_content_parameter.media, stream));
- rtp_content_parameter.connection_ready.connect((status) => on_connection_ready(content, rtp_content_parameter.media));
+ rtp_content_parameter.connection_ready.connect((status) => {
+ Idle.add(() => {
+ on_connection_ready(content, rtp_content_parameter.media);
+ return false;
+ });
+ });
content.senders_modify_incoming.connect((content, proposed_senders) => {
if (content.session.senders_include_us(content.senders) != content.session.senders_include_us(proposed_senders)) {
@@ -342,7 +345,10 @@ public class Dino.PeerState : Object {
if (media == "video" && stream.receiving) {
counterpart_sends_video = true;
video_content_parameter.connection_ready.connect((status) => {
- counterpart_sends_video_updated(false);
+ Idle.add(() => {
+ counterpart_sends_video_updated(false);
+ return false;
+ });
});
}
diff --git a/libdino/src/service/call_state.vala b/libdino/src/service/call_state.vala
index 51563552..188a8321 100644
--- a/libdino/src/service/call_state.vala
+++ b/libdino/src/service/call_state.vala
@@ -126,7 +126,7 @@ public class Dino.CallState : Object {
foreach (PeerState peer in peers_cpy) {
peer.end(Xep.Jingle.ReasonElement.CANCEL);
}
- if (parent_muc != null) {
+ if (parent_muc != null && group_call != null) {
XmppStream stream = stream_interactor.get_stream(call.account);
if (stream == null) return;
stream.get_module(Xep.MujiMeta.Module.IDENTITY).send_invite_retract_to_peer(stream, parent_muc, group_call.muc_jid, message_type);
@@ -242,7 +242,12 @@ public class Dino.CallState : Object {
XmppStream stream = stream_interactor.get_stream(call.account);
if (stream == null) return;
- Jid muc_jid = stream_interactor.get_module(MucManager.IDENTITY).default_muc_server[call.account] ?? new Jid("chat.jabberfr.org");
+ Jid? muc_jid = null;
+ if (muc_jid == null) {
+ warning("Failed to initiate group call: MUC server not known.");
+ return;
+ }
+
muc_jid = new Jid("%08x@".printf(Random.next_int()) + muc_jid.to_string()); // TODO longer?
debug("[%s] Converting call to groupcall %s", call.account.bare_jid.to_string(), muc_jid.to_string());
diff --git a/libdino/src/service/call_store.vala b/libdino/src/service/call_store.vala
index fa6e63ee..bfc8255f 100644
--- a/libdino/src/service/call_store.vala
+++ b/libdino/src/service/call_store.vala
@@ -30,7 +30,7 @@ namespace Dino {
cache_call(call);
}
- public Call? get_call_by_id(int id) {
+ public Call? get_call_by_id(int id, Conversation conversation) {
Call? call = calls_by_db_id[id];
if (call != null) {
return call;
@@ -38,14 +38,17 @@ namespace Dino {
RowOption row_option = db.call.select().with(db.call.id, "=", id).row();
- return create_call_from_row_opt(row_option);
+ return create_call_from_row_opt(row_option, conversation);
}
- private Call? create_call_from_row_opt(RowOption row_opt) {
+ private Call? create_call_from_row_opt(RowOption row_opt, Conversation conversation) {
if (!row_opt.is_present()) return null;
try {
Call call = new Call.from_row(db, row_opt.inner);
+ if (conversation.type_.is_muc_semantic()) {
+ call.ourpart = conversation.counterpart.with_resource(call.ourpart.resourcepart);
+ }
cache_call(call);
return call;
} catch (InvalidJidError e) {
diff --git a/libdino/src/service/calls.vala b/libdino/src/service/calls.vala
index 629d8074..3e2181a5 100644
--- a/libdino/src/service/calls.vala
+++ b/libdino/src/service/calls.vala
@@ -39,9 +39,8 @@ namespace Dino {
Call call = new Call();
call.direction = Call.DIRECTION_OUTGOING;
call.account = conversation.account;
- // TODO we should only do that for Conversation.Type.CHAT, but the database currently requires a counterpart from the start
call.counterpart = conversation.counterpart;
- call.ourpart = conversation.account.full_jid;
+ call.ourpart = stream_interactor.get_module(MucManager.IDENTITY).get_own_jid(conversation.counterpart, conversation.account) ?? conversation.account.full_jid;
call.time = call.local_time = call.end_time = new DateTime.now_utc();
call.state = Call.State.RINGING;
@@ -57,7 +56,7 @@ namespace Dino {
PeerState peer_state = call_state.set_first_peer(conversation.counterpart);
yield peer_state.initiate_call(conversation.counterpart);
} else {
- call_state.initiate_groupchat_call(conversation.counterpart);
+ call_state.initiate_groupchat_call.begin(conversation.counterpart);
}
conversation.last_active = call.time;
@@ -213,24 +212,23 @@ namespace Dino {
private PeerState create_received_call(Account account, Jid from, Jid to, bool video_requested) {
Call call = new Call();
- Jid counterpart = null;
if (from.equals_bare(account.bare_jid)) {
// Call requested by another of our devices
call.direction = Call.DIRECTION_OUTGOING;
call.ourpart = from;
call.state = Call.State.OTHER_DEVICE;
- counterpart = to;
+ call.counterpart = to;
} else {
call.direction = Call.DIRECTION_INCOMING;
call.ourpart = account.full_jid;
call.state = Call.State.RINGING;
- counterpart = from;
+ call.counterpart = from;
}
- call.add_peer(counterpart);
+ call.add_peer(call.counterpart);
call.account = account;
call.time = call.local_time = call.end_time = new DateTime.now_utc();
- Conversation conversation = stream_interactor.get_module(ConversationManager.IDENTITY).create_conversation(counterpart.bare_jid, account, Conversation.Type.CHAT);
+ Conversation conversation = stream_interactor.get_module(ConversationManager.IDENTITY).create_conversation(call.counterpart.bare_jid, account, Conversation.Type.CHAT);
stream_interactor.get_module(CallStore.IDENTITY).add_call(call, conversation);
@@ -238,7 +236,7 @@ namespace Dino {
var call_state = new CallState(call, stream_interactor);
connect_call_state_signals(call_state);
- PeerState peer_state = call_state.set_first_peer(counterpart);
+ PeerState peer_state = call_state.set_first_peer(call.counterpart);
call_state.we_should_send_video = video_requested;
call_state.we_should_send_audio = true;
@@ -283,7 +281,7 @@ namespace Dino {
Call call = new Call();
call.direction = Call.DIRECTION_INCOMING;
call.ourpart = account.full_jid;
- call.add_peer(inviter_jid); // not rly
+ call.counterpart = inviter_jid;
call.account = account;
call.time = call.local_time = call.end_time = new DateTime.now_utc();
call.state = Call.State.RINGING;
@@ -361,13 +359,14 @@ namespace Dino {
if (from.equals(account.full_jid)) return;
Call call = current_jmi_request_peer[account].call;
+ call.ourpart = from;
call.state = Call.State.OTHER_DEVICE;
remove_call_from_datastructures(call);
} else if (from.equals_bare(current_jmi_request_peer[account].jid) && to.equals(account.full_jid)) { // Message from our peer
// We proposed the call
// We know the full jid of our peer now
current_jmi_request_call[account].rename_peer(current_jmi_request_peer[account].jid, from);
- current_jmi_request_peer[account].call_resource(from);
+ current_jmi_request_peer[account].call_resource.begin(from);
}
});
mi_module.session_rejected.connect((from, to, sid) => {
@@ -378,6 +377,9 @@ namespace Dino {
bool incoming_reject = call.direction == Call.DIRECTION_INCOMING && from.equals_bare(account.bare_jid);
if (!outgoing_reject && !incoming_reject) return;
+ // We don't care if a single person in a group call rejected the call
+ if (incoming_reject && call_states[call].group_call != null) return;
+
call.state = Call.State.DECLINED;
call_states[call].terminated(from, Xep.Jingle.ReasonElement.DECLINE, "JMI reject");
remove_call_from_datastructures(call);
diff --git a/libdino/src/service/content_item_store.vala b/libdino/src/service/content_item_store.vala
index e0102d24..7a8e38b8 100644
--- a/libdino/src/service/content_item_store.vala
+++ b/libdino/src/service/content_item_store.vala
@@ -69,7 +69,7 @@ public class ContentItemStore : StreamInteractionModule, Object {
}
break;
case 3:
- Call? call = stream_interactor.get_module(CallStore.IDENTITY).get_call_by_id(foreign_id);
+ Call? call = stream_interactor.get_module(CallStore.IDENTITY).get_call_by_id(foreign_id, conversation);
if (call != null) {
var call_item = new CallItem(call, conversation, row[db.content_item.id]);
items.add(call_item);
@@ -321,7 +321,7 @@ public class CallItem : ContentItem {
public Conversation conversation;
public CallItem(Call call, Conversation conversation, int id) {
- base(id, TYPE, call.direction == Call.DIRECTION_OUTGOING ? conversation.account.bare_jid : conversation.counterpart, call.time, call.encryption, Message.Marked.NONE);
+ base(id, TYPE, call.proposer, call.time, call.encryption, Message.Marked.NONE);
this.call = call;
this.conversation = conversation;
diff --git a/libdino/src/service/muc_manager.vala b/libdino/src/service/muc_manager.vala
index 8a317a08..05473647 100644
--- a/libdino/src/service/muc_manager.vala
+++ b/libdino/src/service/muc_manager.vala
@@ -424,7 +424,7 @@ public class MucManager : StreamInteractionModule, Object {
foreach (Xep.ServiceDiscovery.Identity identity in identities) {
if (identity.category == Xep.ServiceDiscovery.Identity.CATEGORY_CONFERENCE) {
default_muc_server[account] = item.jid;
- print(@"$(account.bare_jid) Default MUC: $(item.jid)\n");
+ debug("[%s] Default MUC: %s", account.bare_jid.to_string(), item.jid.to_string());
return;
}
}
diff --git a/main/data/call_widget.ui b/main/data/call_widget.ui
index 8e2ee36c..0c5d8bfa 100644
--- a/main/data/call_widget.ui
+++ b/main/data/call_widget.ui
@@ -98,7 +98,7 @@
<child>
<object class="GtkBox" id="multiparty_peer_box">
<property name="margin">10</property>
- <property name="spacing">5</property>
+ <property name="spacing">7</property>
<property name="hexpand">True</property>
</object>
</child>
diff --git a/main/src/ui/application.vala b/main/src/ui/application.vala
index 9f48caec..ecbea85e 100644
--- a/main/src/ui/application.vala
+++ b/main/src/ui/application.vala
@@ -206,9 +206,14 @@ public class Dino.Ui.Application : Gtk.Application, Dino.Application {
});
add_action(open_shortcuts_action);
- SimpleAction accept_call_action = new SimpleAction("accept-call", VariantType.INT32);
+ SimpleAction accept_call_action = new SimpleAction("accept-call", new VariantType.tuple(new VariantType[]{VariantType.INT32, VariantType.INT32}));
accept_call_action.activate.connect((variant) => {
- Call? call = stream_interactor.get_module(CallStore.IDENTITY).get_call_by_id(variant.get_int32());
+ int conversation_id = variant.get_child_value(0).get_int32();
+ Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation_by_id(conversation_id);
+ if (conversation == null) return;
+
+ int call_id = variant.get_child_value(1).get_int32();
+ Call? call = stream_interactor.get_module(CallStore.IDENTITY).get_call_by_id(call_id, conversation);
CallState? call_state = stream_interactor.get_module(Calls.IDENTITY).call_states[call];
if (call_state == null) return;
@@ -220,9 +225,14 @@ public class Dino.Ui.Application : Gtk.Application, Dino.Application {
});
add_action(accept_call_action);
- SimpleAction deny_call_action = new SimpleAction("reject-call", VariantType.INT32);
+ SimpleAction deny_call_action = new SimpleAction("reject-call", new VariantType.tuple(new VariantType[]{VariantType.INT32, VariantType.INT32}));
deny_call_action.activate.connect((variant) => {
- Call? call = stream_interactor.get_module(CallStore.IDENTITY).get_call_by_id(variant.get_int32());
+ int conversation_id = variant.get_child_value(0).get_int32();
+ Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation_by_id(conversation_id);
+ if (conversation == null) return;
+
+ int call_id = variant.get_child_value(1).get_int32();
+ Call? call = stream_interactor.get_module(CallStore.IDENTITY).get_call_by_id(call_id, conversation);
CallState? call_state = stream_interactor.get_module(Calls.IDENTITY).call_states[call];
if (call_state == null) return;
diff --git a/main/src/ui/call_window/call_window.vala b/main/src/ui/call_window/call_window.vala
index fab424bf..c610444f 100644
--- a/main/src/ui/call_window/call_window.vala
+++ b/main/src/ui/call_window/call_window.vala
@@ -20,7 +20,7 @@ namespace Dino.Ui {
public Revealer header_bar_revealer = new Revealer() { halign=Align.END, valign=Align.START, transition_type=RevealerTransitionType.CROSSFADE, transition_duration=200, visible=true };
public Box own_video_box = new Box(Orientation.HORIZONTAL, 0) { halign=Align.END, valign=Align.END, visible=true };
public Revealer invite_button_revealer = new Revealer() { margin_top=50, margin_right=30, halign=Align.END, valign=Align.START, transition_type=RevealerTransitionType.CROSSFADE, transition_duration=200 };
- public Button invite_button = new Button.from_icon_name("dino-account-plus") { relief=ReliefStyle.NONE };
+ public Button invite_button = new Button.from_icon_name("dino-account-plus") { relief=ReliefStyle.NONE, visible=false };
private Widget? own_video = null;
private HashMap<string, ParticipantWidget> participant_widgets = new HashMap<string, ParticipantWidget>();
private ArrayList<string> participants = new ArrayList<string>();
diff --git a/main/src/ui/conversation_content_view/call_widget.vala b/main/src/ui/conversation_content_view/call_widget.vala
index a7d37afd..a2c8c0c2 100644
--- a/main/src/ui/conversation_content_view/call_widget.vala
+++ b/main/src/ui/conversation_content_view/call_widget.vala
@@ -86,7 +86,7 @@ namespace Dino.Ui {
private void update_counterparts() {
if (call.state != Call.State.IN_PROGRESS && call.state != Call.State.ENDED) return;
- if (call.counterparts.size <= 1) return;
+ if (call.counterparts.size <= 1 && conversation.type_ == Conversation.Type.CHAT) return;
multiparty_peer_box.foreach((widget) => { multiparty_peer_box.remove(widget); });
diff --git a/main/src/ui/conversation_titlebar/call_entry.vala b/main/src/ui/conversation_titlebar/call_entry.vala
index 3fa399a6..3b3a5b39 100644
--- a/main/src/ui/conversation_titlebar/call_entry.vala
+++ b/main/src/ui/conversation_titlebar/call_entry.vala
@@ -115,13 +115,17 @@ namespace Dino.Ui {
return;
}
- Conversation conv_bak = 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_video_calls_async(conversation);
- if (conv_bak != conversation) return;
-
- visible = audio_works;
- video_button.visible = video_works;
+ if (conversation.type_ == Conversation.Type.CHAT) {
+ Conversation conv_bak = 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_video_calls_async(conversation);
+ if (conv_bak != conversation) return;
+
+ visible = audio_works;
+ video_button.visible = video_works;
+ } else {
+ visible = false;
+ }
}
public new void unset_conversation() { }
diff --git a/main/src/ui/notifier_freedesktop.vala b/main/src/ui/notifier_freedesktop.vala
index 83e9bf57..e8e2ba1d 100644
--- a/main/src/ui/notifier_freedesktop.vala
+++ b/main/src/ui/notifier_freedesktop.vala
@@ -141,10 +141,12 @@ public class Dino.Ui.FreeDesktopNotifier : NotificationProvider, Object {
GLib.Application.get_default().activate_action("open-conversation", new Variant.int32(conversation.id));
});
add_action_listener(notification_id, "reject", () => {
- GLib.Application.get_default().activate_action("reject-call", new Variant.int32(call.id));
+ var variant = new Variant.tuple(new Variant[] {new Variant.int32(conversation.id), new Variant.int32(call.id)});
+ GLib.Application.get_default().activate_action("reject-call", variant);
});
add_action_listener(notification_id, "accept", () => {
- GLib.Application.get_default().activate_action("accept-call", new Variant.int32(call.id));
+ var variant = new Variant.tuple(new Variant[] {new Variant.int32(conversation.id), new Variant.int32(call.id)});
+ GLib.Application.get_default().activate_action("accept-call", variant);
});
} catch (Error e) {
warning("Failed showing subscription request notification: %s", e.message);