Merge branch 'client-enhance-add-call-methods' into 'master'
[Client] Add call methods See merge request famedly/famedlysdk!153
This commit is contained in:
commit
5430bad08a
|
@ -32,6 +32,7 @@ export 'package:famedlysdk/src/utils/mx_content.dart';
|
|||
export 'package:famedlysdk/src/utils/profile.dart';
|
||||
export 'package:famedlysdk/src/utils/push_rules.dart';
|
||||
export 'package:famedlysdk/src/utils/states_map.dart';
|
||||
export 'package:famedlysdk/src/utils/turn_server_credentials.dart';
|
||||
export 'package:famedlysdk/src/account_data.dart';
|
||||
export 'package:famedlysdk/src/client.dart';
|
||||
export 'package:famedlysdk/src/event.dart';
|
||||
|
|
|
@ -30,6 +30,7 @@ import 'package:famedlysdk/src/presence.dart';
|
|||
import 'package:famedlysdk/src/store_api.dart';
|
||||
import 'package:famedlysdk/src/sync/user_update.dart';
|
||||
import 'package:famedlysdk/src/utils/matrix_file.dart';
|
||||
import 'package:famedlysdk/src/utils/turn_server_credentials.dart';
|
||||
import 'package:pedantic/pedantic.dart';
|
||||
import 'room.dart';
|
||||
import 'event.dart';
|
||||
|
@ -400,6 +401,15 @@ class Client {
|
|||
return;
|
||||
}
|
||||
|
||||
/// Get credentials for the client to use when initiating calls.
|
||||
Future<TurnServerCredentials> getTurnServerCredentials() async {
|
||||
final Map<String, dynamic> response = await this.jsonRequest(
|
||||
type: HTTPType.GET,
|
||||
action: "/client/r0/voip/turnServer",
|
||||
);
|
||||
return TurnServerCredentials.fromJson(response);
|
||||
}
|
||||
|
||||
/// Fetches the pushrules for the logged in user.
|
||||
/// These are needed for notifications on Android
|
||||
Future<PushRules> getPushrules() async {
|
||||
|
@ -477,6 +487,18 @@ class Client {
|
|||
final StreamController<AccountData> onAccountData =
|
||||
StreamController.broadcast();
|
||||
|
||||
/// Will be called on call invites.
|
||||
final StreamController<Event> onCallInvite = StreamController.broadcast();
|
||||
|
||||
/// Will be called on call hangups.
|
||||
final StreamController<Event> onCallHangup = StreamController.broadcast();
|
||||
|
||||
/// Will be called on call candidates.
|
||||
final StreamController<Event> onCallCandidates = StreamController.broadcast();
|
||||
|
||||
/// Will be called on call answers.
|
||||
final StreamController<Event> onCallAnswer = StreamController.broadcast();
|
||||
|
||||
/// Matrix synchronisation is done with https long polling. This needs a
|
||||
/// timeout which is usually 30 seconds.
|
||||
int syncTimeoutSec = 30;
|
||||
|
@ -894,6 +916,16 @@ class Client {
|
|||
_updateRoomsByEventUpdate(update);
|
||||
this.store?.storeEventUpdate(update);
|
||||
onEvent.add(update);
|
||||
|
||||
if (event["type"] == "m.call.invite") {
|
||||
onCallInvite.add(Event.fromJson(event, getRoomById(roomID)));
|
||||
} else if (event["type"] == "m.call.hangup") {
|
||||
onCallHangup.add(Event.fromJson(event, getRoomById(roomID)));
|
||||
} else if (event["type"] == "m.call.answer") {
|
||||
onCallAnswer.add(Event.fromJson(event, getRoomById(roomID)));
|
||||
} else if (event["type"] == "m.call.candidates") {
|
||||
onCallCandidates.add(Event.fromJson(event, getRoomById(roomID)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -220,6 +220,18 @@ class Event {
|
|||
return EventTypes.Sticker;
|
||||
case "m.room.message":
|
||||
return EventTypes.Message;
|
||||
case "m.call.encrypted":
|
||||
return EventTypes.Encrypted;
|
||||
case "m.call.encryption":
|
||||
return EventTypes.Encryption;
|
||||
case "m.call.invite":
|
||||
return EventTypes.CallInvite;
|
||||
case "m.call.answer":
|
||||
return EventTypes.CallAnswer;
|
||||
case "m.call.candidates":
|
||||
return EventTypes.CallCandidates;
|
||||
case "m.call.hangup":
|
||||
return EventTypes.CallHangup;
|
||||
}
|
||||
return EventTypes.Unknown;
|
||||
}
|
||||
|
@ -394,5 +406,11 @@ enum EventTypes {
|
|||
RoomAvatar,
|
||||
GuestAccess,
|
||||
HistoryVisibility,
|
||||
Encryption,
|
||||
Encrypted,
|
||||
CallInvite,
|
||||
CallAnswer,
|
||||
CallCandidates,
|
||||
CallHangup,
|
||||
Unknown,
|
||||
}
|
||||
|
|
|
@ -1048,6 +1048,103 @@ class Room {
|
|||
data: data,
|
||||
);
|
||||
}
|
||||
|
||||
/// This is sent by the caller when they wish to establish a call.
|
||||
/// [callId] is a unique identifier for the call.
|
||||
/// [version] is the version of the VoIP specification this message adheres to. This specification is version 0.
|
||||
/// [lifetime] is the time in milliseconds that the invite is valid for. Once the invite age exceeds this value,
|
||||
/// clients should discard it. They should also no longer show the call as awaiting an answer in the UI.
|
||||
/// [type] The type of session description. Must be 'offer'.
|
||||
/// [sdp] The SDP text of the session description.
|
||||
Future<String> inviteToCall(String callId, int lifetime, String sdp,
|
||||
{String type = "offer", int version = 0, String txid}) async {
|
||||
if (txid == null) txid = "txid${DateTime.now().millisecondsSinceEpoch}";
|
||||
final Map<String, dynamic> response = await client.jsonRequest(
|
||||
type: HTTPType.PUT,
|
||||
action: "/client/r0/rooms/$id/send/m.call.invite/$txid",
|
||||
data: {
|
||||
"call_id": callId,
|
||||
"lifetime": lifetime,
|
||||
"offer": {"sdp": sdp, "type": type},
|
||||
"version": version,
|
||||
},
|
||||
);
|
||||
return response["event_id"];
|
||||
}
|
||||
|
||||
/// This is sent by callers after sending an invite and by the callee after answering.
|
||||
/// Its purpose is to give the other party additional ICE candidates to try using to communicate.
|
||||
///
|
||||
/// [callId] The ID of the call this event relates to.
|
||||
///
|
||||
/// [version] The version of the VoIP specification this messages adheres to. This specification is version 0.
|
||||
///
|
||||
/// [candidates] Array of objects describing the candidates. Example:
|
||||
///
|
||||
/// ```
|
||||
/// [
|
||||
/// {
|
||||
/// "candidate": "candidate:863018703 1 udp 2122260223 10.9.64.156 43670 typ host generation 0",
|
||||
/// "sdpMLineIndex": 0,
|
||||
/// "sdpMid": "audio"
|
||||
/// }
|
||||
/// ],
|
||||
/// ```
|
||||
Future<String> sendCallCandidates(
|
||||
String callId,
|
||||
List<Map<String, dynamic>> candidates, {
|
||||
int version = 0,
|
||||
String txid,
|
||||
}) async {
|
||||
if (txid == null) txid = "txid${DateTime.now().millisecondsSinceEpoch}";
|
||||
final Map<String, dynamic> response = await client.jsonRequest(
|
||||
type: HTTPType.PUT,
|
||||
action: "/client/r0/rooms/$id/send/m.call.candidates/$txid",
|
||||
data: {
|
||||
"call_id": callId,
|
||||
"candidates": candidates,
|
||||
"version": version,
|
||||
},
|
||||
);
|
||||
return response["event_id"];
|
||||
}
|
||||
|
||||
/// This event is sent by the callee when they wish to answer the call.
|
||||
/// [callId] is a unique identifier for the call.
|
||||
/// [version] is the version of the VoIP specification this message adheres to. This specification is version 0.
|
||||
/// [type] The type of session description. Must be 'answer'.
|
||||
/// [sdp] The SDP text of the session description.
|
||||
Future<String> answerCall(String callId, String sdp,
|
||||
{String type = "answer", int version = 0, String txid}) async {
|
||||
if (txid == null) txid = "txid${DateTime.now().millisecondsSinceEpoch}";
|
||||
final Map<String, dynamic> response = await client.jsonRequest(
|
||||
type: HTTPType.PUT,
|
||||
action: "/client/r0/rooms/$id/send/m.call.answer/$txid",
|
||||
data: {
|
||||
"call_id": callId,
|
||||
"answer": {"sdp": sdp, "type": type},
|
||||
"version": version,
|
||||
},
|
||||
);
|
||||
return response["event_id"];
|
||||
}
|
||||
|
||||
/// This event is sent by the callee when they wish to answer the call.
|
||||
/// [callId] The ID of the call this event relates to.
|
||||
/// [version] is the version of the VoIP specification this message adheres to. This specification is version 0.
|
||||
Future<String> hangupCall(String callId,
|
||||
{int version = 0, String txid}) async {
|
||||
if (txid == null) txid = "txid${DateTime.now().millisecondsSinceEpoch}";
|
||||
final Map<String, dynamic> response = await client.jsonRequest(
|
||||
type: HTTPType.PUT,
|
||||
action: "/client/r0/rooms/$id/send/m.call.hangup/$txid",
|
||||
data: {
|
||||
"call_id": callId,
|
||||
"version": version,
|
||||
},
|
||||
);
|
||||
return response["event_id"];
|
||||
}
|
||||
}
|
||||
|
||||
enum PushRuleState { notify, mentions_only, dont_notify }
|
||||
|
|
23
lib/src/utils/turn_server_credentials.dart
Normal file
23
lib/src/utils/turn_server_credentials.dart
Normal file
|
@ -0,0 +1,23 @@
|
|||
/// Credentials for the client to use when initiating calls.
|
||||
class TurnServerCredentials {
|
||||
/// The username to use.
|
||||
final String username;
|
||||
|
||||
/// The password to use.
|
||||
final String password;
|
||||
|
||||
/// A list of TURN URIs
|
||||
final List<String> uris;
|
||||
|
||||
/// The time-to-live in seconds
|
||||
final int ttl;
|
||||
|
||||
const TurnServerCredentials(
|
||||
this.username, this.password, this.uris, this.ttl);
|
||||
|
||||
TurnServerCredentials.fromJson(Map<String, dynamic> json)
|
||||
: username = json['username'],
|
||||
password = json['password'],
|
||||
uris = json['uris'].cast<String>(),
|
||||
ttl = json['ttl'];
|
||||
}
|
Loading…
Reference in a new issue