Skip to content

Commit 1deb830

Browse files
committed
add call API
1 parent 203e668 commit 1deb830

File tree

11 files changed

+684
-2
lines changed

11 files changed

+684
-2
lines changed

deltachat-ffi/deltachat.h

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,6 +1222,79 @@ void dc_set_webxdc_integration (dc_context_t* context, const char* f
12221222
uint32_t dc_init_webxdc_integration (dc_context_t* context, uint32_t chat_id);
12231223

12241224

1225+
/**
1226+
* Start an outgoing call.
1227+
* This sends a message with all relevant information to the callee,
1228+
* who will get informed by an #DC_EVENT_INCOMING_CALL event and rings.
1229+
*
1230+
* Possible actions during ringing:
1231+
* - callee accepts using dc_accept_incoming_call(), caller receives #DC_EVENT_OUTGOING_CALL_ACCEPTED,
1232+
* callee's devices receive #DC_EVENT_INCOMING_CALL_ACCEPTED, call starts
1233+
* - callee rejects using dc_end_call(), caller receives #DC_EVENT_CALL_ENDED,
1234+
* callee's other devices receive #DC_EVENT_CALL_ENDED, done.
1235+
* - caller cancels the call using dc_end_call(), callee receives #DC_EVENT_CALL_ENDED, done.
1236+
* - after 2 minutes, caller and callee both should end the call.
1237+
* this is to prevent endless ringing of callee
1238+
* in case caller got offline without being able to send cancellation message.
1239+
*
1240+
* Actions during the call:
1241+
* - callee ends the call using dc_end_call(), caller receives #DC_EVENT_CALL_ENDED
1242+
* - caller ends the call using dc_end_call(), callee receives #DC_EVENT_CALL_ENDED
1243+
*
1244+
* Note, that the events are for updating the call screen,
1245+
* possible status messages are added and updated as usual, including the known events.
1246+
* In the UI, the sorted chatlist is used as an overview about calls as well as messages.
1247+
* To place a call with a contact that has no chat yet, use dc_create_chat_by_contact_id() first.
1248+
*
1249+
* @memberof dc_context_t
1250+
* @param context The context object.
1251+
* @param chat_id The chat to place a call for.
1252+
* This needs to be a one-to-one chat.
1253+
* @return ID of the system message announcing the call.
1254+
*/
1255+
uint32_t dc_place_outgoing_call (dc_context_t* context, uint32_t chat_id);
1256+
1257+
1258+
/**
1259+
* Accept incoming call.
1260+
*
1261+
* This implicitly accepts the contact request, if not yet done.
1262+
* All affected devices will receive
1263+
* either #DC_EVENT_OUTGOING_CALL_ACCEPTED or #DC_EVENT_INCOMING_CALL_ACCEPTED.
1264+
*
1265+
* @memberof dc_context_t
1266+
* @param context The context object.
1267+
* @param msg_id The ID of the call to accept.
1268+
* This is the ID reported by #DC_EVENT_INCOMING_CALL
1269+
* and equal to the ID of the corresponding info message.
1270+
* @return 1=success, 0=error
1271+
*/
1272+
int dc_accept_incoming_call (dc_context_t* context, uint32_t msg_id);
1273+
1274+
1275+
/**
1276+
* End incoming or outgoing call.
1277+
*
1278+
* From the view of the caller, a "cancellation",
1279+
* from the view of callee, a "rejection".
1280+
* If the call was accepted, this is a "hangup".
1281+
*
1282+
* For accepted calls,
1283+
* all participant devices get informed about the ended call via #DC_EVENT_CALL_ENDED.
1284+
* For not accepted calls, only the caller will inform the callee.
1285+
*
1286+
* If the callee rejects, the caller will get an timeout or give up at some point -
1287+
* same as for all other reasons the call cannot be established: Device not in reach, device muted, connectivity etc.
1288+
* This is to protect privacy of the callee, avoiding to check if callee is online.
1289+
*
1290+
* @memberof dc_context_t
1291+
* @param context The context object.
1292+
* @param msg_id the ID of the call.
1293+
* @return 1=success, 0=error
1294+
*/
1295+
int dc_end_call (dc_context_t* context, uint32_t msg_id);
1296+
1297+
12251298
/**
12261299
* Save a draft for a chat in the database.
12271300
*
@@ -4517,6 +4590,8 @@ int dc_msg_is_info (const dc_msg_t* msg);
45174590
* the UI should change the corresponding string using #DC_STR_INVALID_UNENCRYPTED_MAIL
45184591
* and also offer a way to fix the encryption, eg. by a button offering a QR scan
45194592
* - DC_INFO_WEBXDC_INFO_MESSAGE (32) - Info-message created by webxdc app sending `update.info`
4593+
* - DC_INFO_OUTGOING_CALL (50) - Info-message refers to an outgoing call
4594+
* - DC_INFO_INCOMING_CALL (55) - Info-message refers to an incoming call
45204595
*
45214596
* For the messages that refer to a CONTACT,
45224597
* dc_msg_get_info_contact_id() returns the contact ID.
@@ -4572,6 +4647,8 @@ uint32_t dc_msg_get_info_contact_id (const dc_msg_t* msg);
45724647
#define DC_INFO_PROTECTION_DISABLED 12
45734648
#define DC_INFO_INVALID_UNENCRYPTED_MAIL 13
45744649
#define DC_INFO_WEBXDC_INFO_MESSAGE 32
4650+
#define DC_INFO_OUTGOING_CALL 50
4651+
#define DC_INFO_INCOMING_CALL 55
45754652

45764653

45774654
/**
@@ -6569,6 +6646,38 @@ void dc_event_unref(dc_event_t* event);
65696646
*/
65706647
#define DC_EVENT_CHANNEL_OVERFLOW 2400
65716648

6649+
6650+
6651+
/**
6652+
* Incoming call.
6653+
* UI will usually start ringing.
6654+
*
6655+
* If user takes action, dc_accept_incoming_call() or dc_end_call() should be called.
6656+
*
6657+
* Otherwise, ringing should end on #DC_EVENT_CALL_ENDED
6658+
* or #DC_EVENT_INCOMING_CALL_ACCEPTED
6659+
*
6660+
* @param data1 (int) msg_id
6661+
*/
6662+
#define DC_EVENT_INCOMING_CALL 2550
6663+
6664+
/**
6665+
* The callee accepted an incoming call on another another device using dc_accept_incoming_call().
6666+
* The caller gets the event #DC_EVENT_OUTGOING_CALL_ACCEPTED at the same time.
6667+
*/
6668+
#define DC_EVENT_INCOMING_CALL_ACCEPTED 2560
6669+
6670+
/**
6671+
* A call placed using dc_place_outgoing_call() was accepted by the callee using dc_accept_incoming_call().
6672+
*/
6673+
#define DC_EVENT_OUTGOING_CALL_ACCEPTED 2570
6674+
6675+
/**
6676+
* An incoming or outgoing call was ended using dc_end_call().
6677+
*/
6678+
#define DC_EVENT_CALL_ENDED 2580
6679+
6680+
65726681
/**
65736682
* @}
65746683
*/

deltachat-ffi/src/lib.rs

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,10 @@ pub unsafe extern "C" fn dc_event_get_id(event: *mut dc_event_t) -> libc::c_int
565565
EventType::AccountsChanged => 2302,
566566
EventType::AccountsItemChanged => 2303,
567567
EventType::EventChannelOverflow { .. } => 2400,
568+
EventType::IncomingCall { .. } => 2550,
569+
EventType::IncomingCallAccepted { .. } => 2560,
570+
EventType::OutgoingCallAccepted { .. } => 2570,
571+
EventType::CallEnded { .. } => 2580,
568572
#[allow(unreachable_patterns)]
569573
#[cfg(test)]
570574
_ => unreachable!("This is just to silence a rust_analyzer false-positive"),
@@ -628,7 +632,11 @@ pub unsafe extern "C" fn dc_event_get_data1_int(event: *mut dc_event_t) -> libc:
628632
EventType::WebxdcRealtimeData { msg_id, .. }
629633
| EventType::WebxdcStatusUpdate { msg_id, .. }
630634
| EventType::WebxdcRealtimeAdvertisementReceived { msg_id }
631-
| EventType::WebxdcInstanceDeleted { msg_id, .. } => msg_id.to_u32() as libc::c_int,
635+
| EventType::WebxdcInstanceDeleted { msg_id, .. }
636+
| EventType::IncomingCall { msg_id, .. }
637+
| EventType::IncomingCallAccepted { msg_id, .. }
638+
| EventType::OutgoingCallAccepted { msg_id, .. }
639+
| EventType::CallEnded { msg_id, .. } => msg_id.to_u32() as libc::c_int,
632640
EventType::ChatlistItemChanged { chat_id } => {
633641
chat_id.unwrap_or_default().to_u32() as libc::c_int
634642
}
@@ -680,6 +688,10 @@ pub unsafe extern "C" fn dc_event_get_data2_int(event: *mut dc_event_t) -> libc:
680688
| EventType::ChatModified(_)
681689
| EventType::ChatDeleted { .. }
682690
| EventType::WebxdcRealtimeAdvertisementReceived { .. }
691+
| EventType::IncomingCall { .. }
692+
| EventType::IncomingCallAccepted { .. }
693+
| EventType::OutgoingCallAccepted { .. }
694+
| EventType::CallEnded { .. }
683695
| EventType::EventChannelOverflow { .. } => 0,
684696
EventType::MsgsChanged { msg_id, .. }
685697
| EventType::ReactionsChanged { msg_id, .. }
@@ -777,6 +789,10 @@ pub unsafe extern "C" fn dc_event_get_data2_str(event: *mut dc_event_t) -> *mut
777789
| EventType::AccountsChanged
778790
| EventType::AccountsItemChanged
779791
| EventType::WebxdcRealtimeAdvertisementReceived { .. }
792+
| EventType::IncomingCall { .. }
793+
| EventType::IncomingCallAccepted { .. }
794+
| EventType::OutgoingCallAccepted { .. }
795+
| EventType::CallEnded { .. }
780796
| EventType::EventChannelOverflow { .. } => ptr::null_mut(),
781797
EventType::ConfigureProgress { comment, .. } => {
782798
if let Some(comment) = comment {
@@ -1176,6 +1192,47 @@ pub unsafe extern "C" fn dc_init_webxdc_integration(
11761192
.unwrap_or(0)
11771193
}
11781194

1195+
#[no_mangle]
1196+
pub unsafe extern "C" fn dc_place_outgoing_call(context: *mut dc_context_t, chat_id: u32) -> u32 {
1197+
if context.is_null() || chat_id == 0 {
1198+
eprintln!("ignoring careless call to dc_place_outgoing_call()");
1199+
return 0;
1200+
}
1201+
let ctx = &*context;
1202+
let chat_id = ChatId::new(chat_id);
1203+
1204+
block_on(ctx.place_outgoing_call(chat_id))
1205+
.map(|msg_id| msg_id.to_u32())
1206+
.unwrap_or_log_default(ctx, "Failed to place call")
1207+
}
1208+
1209+
#[no_mangle]
1210+
pub unsafe extern "C" fn dc_accept_incoming_call(
1211+
context: *mut dc_context_t,
1212+
msg_id: u32,
1213+
) -> libc::c_int {
1214+
if context.is_null() || msg_id == 0 {
1215+
eprintln!("ignoring careless call to dc_accept_incoming_call()");
1216+
return 0;
1217+
}
1218+
let ctx = &*context;
1219+
let msg_id = MsgId::new(msg_id);
1220+
1221+
block_on(ctx.accept_incoming_call(msg_id)).is_ok() as libc::c_int
1222+
}
1223+
1224+
#[no_mangle]
1225+
pub unsafe extern "C" fn dc_end_call(context: *mut dc_context_t, msg_id: u32) -> libc::c_int {
1226+
if context.is_null() || msg_id == 0 {
1227+
eprintln!("ignoring careless call to dc_end_call()");
1228+
return 0;
1229+
}
1230+
let ctx = &*context;
1231+
let msg_id = MsgId::new(msg_id);
1232+
1233+
block_on(ctx.end_call(msg_id)).is_ok() as libc::c_int
1234+
}
1235+
11791236
#[no_mangle]
11801237
pub unsafe extern "C" fn dc_set_draft(
11811238
context: *mut dc_context_t,

deltachat-jsonrpc/src/api/types/events.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,19 @@ pub enum EventType {
417417
/// Number of events skipped.
418418
n: u64,
419419
},
420+
421+
/// Incoming call.
422+
IncomingCall { msg_id: u32 },
423+
424+
/// Incoming call accepted.
425+
/// This is esp. interesting to stop ringing on other devices.
426+
IncomingCallAccepted { msg_id: u32 },
427+
428+
/// Outgoing call accepted.
429+
OutgoingCallAccepted { msg_id: u32 },
430+
431+
/// Call ended.
432+
CallEnded { msg_id: u32 },
420433
}
421434

422435
impl From<CoreEventType> for EventType {
@@ -567,6 +580,18 @@ impl From<CoreEventType> for EventType {
567580
CoreEventType::EventChannelOverflow { n } => EventChannelOverflow { n },
568581
CoreEventType::AccountsChanged => AccountsChanged,
569582
CoreEventType::AccountsItemChanged => AccountsItemChanged,
583+
CoreEventType::IncomingCall { msg_id } => IncomingCall {
584+
msg_id: msg_id.to_u32(),
585+
},
586+
CoreEventType::IncomingCallAccepted { msg_id } => IncomingCallAccepted {
587+
msg_id: msg_id.to_u32(),
588+
},
589+
CoreEventType::OutgoingCallAccepted { msg_id } => OutgoingCallAccepted {
590+
msg_id: msg_id.to_u32(),
591+
},
592+
CoreEventType::CallEnded { msg_id } => CallEnded {
593+
msg_id: msg_id.to_u32(),
594+
},
570595
#[allow(unreachable_patterns)]
571596
#[cfg(test)]
572597
_ => unreachable!("This is just to silence a rust_analyzer false-positive"),

deltachat-jsonrpc/src/api/types/message.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,11 @@ pub enum SystemMessageType {
436436

437437
/// This message contains a users iroh node address.
438438
IrohNodeAddr,
439+
440+
OutgoingCall,
441+
IncomingCall,
442+
CallAccepted,
443+
CallEnded,
439444
}
440445

441446
impl From<deltachat::mimeparser::SystemMessage> for SystemMessageType {
@@ -461,6 +466,10 @@ impl From<deltachat::mimeparser::SystemMessage> for SystemMessageType {
461466
SystemMessage::IrohNodeAddr => SystemMessageType::IrohNodeAddr,
462467
SystemMessage::SecurejoinWait => SystemMessageType::SecurejoinWait,
463468
SystemMessage::SecurejoinWaitTimeout => SystemMessageType::SecurejoinWaitTimeout,
469+
SystemMessage::OutgoingCall => SystemMessageType::OutgoingCall,
470+
SystemMessage::IncomingCall => SystemMessageType::IncomingCall,
471+
SystemMessage::CallAccepted => SystemMessageType::CallAccepted,
472+
SystemMessage::CallEnded => SystemMessageType::CallEnded,
464473
}
465474
}
466475
}

0 commit comments

Comments
 (0)