Skip to content
Snippets Groups Projects
Commit a92c185e authored by Kateryna Kostiuk's avatar Kateryna Kostiuk
Browse files

calls: adapt to new API

- adapt to new API for calls
- adapt to new ApI for video input

Change-Id: I850a6c25acb7c133355f617c3bd7047f93961f02
parent f598e55f
Branches
No related tags found
No related merge requests found
Showing
with 408 additions and 247 deletions
......@@ -247,6 +247,8 @@
263B7158246D9390007044C4 /* SmartListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 263B7157246D9390007044C4 /* SmartListCell.swift */; };
263B715A246D9556007044C4 /* IncognitoSmartListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 263B7159246D9556007044C4 /* IncognitoSmartListCell.swift */; };
263B715C246D96E5007044C4 /* IncognitoSmartListCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 263B715B246D96E5007044C4 /* IncognitoSmartListCell.xib */; };
2659F65827483656009107F1 /* VideoManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2659F65727483656009107F1 /* VideoManager.swift */; };
2659F65C27483A27009107F1 /* DecodingAdapterDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2659F65B27483A27009107F1 /* DecodingAdapterDelegate.swift */; };
2662FC79246B1E1700FA7782 /* JamiSearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2662FC78246B1E1700FA7782 /* JamiSearchView.swift */; };
2662FC7B246B216B00FA7782 /* JamiSearchViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2662FC7A246B216B00FA7782 /* JamiSearchViewModel.swift */; };
2662FC7D246B78E800FA7782 /* IncognitoSmartListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2662FC7C246B78E800FA7782 /* IncognitoSmartListViewController.swift */; };
......@@ -661,6 +663,8 @@
263B7157246D9390007044C4 /* SmartListCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmartListCell.swift; sourceTree = "<group>"; };
263B7159246D9556007044C4 /* IncognitoSmartListCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IncognitoSmartListCell.swift; sourceTree = "<group>"; };
263B715B246D96E5007044C4 /* IncognitoSmartListCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = IncognitoSmartListCell.xib; sourceTree = "<group>"; };
2659F65727483656009107F1 /* VideoManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoManager.swift; sourceTree = "<group>"; };
2659F65B27483A27009107F1 /* DecodingAdapterDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecodingAdapterDelegate.swift; sourceTree = "<group>"; };
2662FC78246B1E1700FA7782 /* JamiSearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JamiSearchView.swift; sourceTree = "<group>"; };
2662FC7A246B216B00FA7782 /* JamiSearchViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JamiSearchViewModel.swift; sourceTree = "<group>"; };
2662FC7C246B78E800FA7782 /* IncognitoSmartListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = IncognitoSmartListViewController.swift; path = Ring/Features/Conversations/SmartList/IncognitoSmartListViewController.swift; sourceTree = SOURCE_ROOT; };
......@@ -1015,6 +1019,8 @@
645BDD8024B74BCB009129B1 /* LocationSharingService.swift */,
26D08AB8269628F400E37574 /* RequestsService.swift */,
26D08ABA2696293100E37574 /* RequestsAdapterDelegate.swift */,
2659F65727483656009107F1 /* VideoManager.swift */,
2659F65B27483A27009107F1 /* DecodingAdapterDelegate.swift */,
);
path = Services;
sourceTree = "<group>";
......@@ -2217,6 +2223,7 @@
5CE66F761FBF769B00EE9291 /* InitialLoadingViewController.swift in Sources */,
66ACB430214AE28C00A94162 /* ScanViewController.swift in Sources */,
0E6D959A2407115800996A28 /* LinkToAccountManagerViewController.swift in Sources */,
2659F65C27483A27009107F1 /* DecodingAdapterDelegate.swift in Sources */,
56BBC99F1ED714CB00CDAF8B /* ConversationsAdapter.mm in Sources */,
0E438A9A204F47E700402900 /* SettingsTableView.swift in Sources */,
0E49096A1FEAB156005CAA50 /* CallsAdapter.mm in Sources */,
......@@ -2286,6 +2293,7 @@
1A20417C1F1E56FF00C08435 /* WelcomeViewModel.swift in Sources */,
1A5DC03D1F35678D0075E8EF /* RequestItem.swift in Sources */,
0E403F811F7D797300C80BC2 /* MessageCellGenerated.swift in Sources */,
2659F65827483656009107F1 /* VideoManager.swift in Sources */,
64F8127A24BBC19C00A7DE6A /* MessageCellLocationSharing.swift in Sources */,
0E6D959C2407116E00996A28 /* LinkToAccountManagerViewModel.swift in Sources */,
62AD584C2056DB2700AF0701 /* MessageCellDataTransferSent.swift in Sources */,
......
......@@ -102,7 +102,7 @@ class VCardUtils {
return name
}
class func sendVCard(card: CNContact, callID: String, accountID: String, sender: CallsService) {
class func sendVCard(card: CNContact, callID: String, accountID: String, sender: CallsService, from: String) {
do {
let vCard = card
guard let vCardData = try CNContactVCardSerialization.dataWithImageAndUUID(from: vCard, andImageCompression: 40000, encoding: .utf8),
......@@ -131,7 +131,7 @@ class VCardUtils {
chunk[key] = vCardString
}
i += 1
sender.sendChunk(callID: callID, message: chunk, accountId: accountID)
sender.sendChunk(callID: callID, message: chunk, accountId: accountID, from: from)
}
} catch {
print(error)
......
......@@ -45,6 +45,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
private let callsProvider: CallsProviderDelegate = CallsProviderDelegate()
private var conversationManager: ConversationsManager?
private var interactionsManager: GeneratedInteractionsManager?
private var videoManager: VideoManager?
private lazy var callService: CallsService = {
CallsService(withCallsAdapter: CallsAdapter(), dbManager: self.dBManager)
}()
......@@ -152,8 +153,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
dataTransferService: self.dataTransferService,
callService: self.callService,
locationSharingService: self.locationSharingService, contactsService: self.contactsService,
callsProvider: self.callsProvider,
videoService: self.videoService, requestsService: self.requestsService)
callsProvider: self.callsProvider, requestsService: self.requestsService)
self.videoManager = VideoManager(with: self.callService, callsProvider: self.callsProvider, videoService: self.videoService)
self.window?.rootViewController = self.appCoordinator.rootViewController
self.window?.makeKeyAndVisible()
......
......@@ -27,32 +27,32 @@
@property (class, nonatomic, weak) id <CallsAdapterDelegate> delegate;
- (BOOL)acceptCallWithId:(NSString*)callId withMedia:(NSArray*)mediaList;
- (BOOL)refuseCallWithId:(NSString*)callId;
- (BOOL)hangUpCallWithId:(NSString*)callId;
- (BOOL)holdCallWithId:(NSString*)callId;
- (BOOL)unholdCallWithId:(NSString*)callId;
- (BOOL)requestMediaChange:(NSString*)callId withMedia: (NSArray*)mediaList;
- (void)answerMediaChangeResquest:(NSString*)callId withMedia: (NSArray*)mediaList;
- (NSString*)placeCallWithAccountId:(NSString*)accountId toRingId:(NSString*)ringId withMedia: (NSArray*)mediaList;
- (NSDictionary<NSString*,NSString*>*)callDetailsWithCallId:(NSString*)callId;
- (NSArray<NSString*>*)calls;
- (void) sendTextMessageWithCallID:(NSString*)callId message:(NSDictionary*)message accountId:(NSString*)accountId sMixed:(bool)isMixed;
- (BOOL) muteMedia:(NSString*)callId mediaType:(NSString*)media muted:(bool)muted;
- (BOOL)acceptCallWithId:(NSString*)callId accountId:(NSString*)accountId withMedia:(NSArray*)mediaList;
- (BOOL)refuseCallWithId:(NSString*)callId accountId:(NSString*)accountId;
- (BOOL)hangUpCallWithId:(NSString*)callId accountId:(NSString*)accountId;
- (BOOL)holdCallWithId:(NSString*)callId accountId:(NSString*)accountId;
- (BOOL)unholdCallWithId:(NSString*)callId accountId:(NSString*)accountId;
- (void)playDTMF:(NSString*)code;
- (BOOL)joinConference:(NSString*)confID call:(NSString*)callID;
- (BOOL)joinConferences:(NSString*)firstConf secondConference:(NSString*)secondConf;
- (BOOL)joinCall:(NSString*)firstCall second:(NSString*)secondCall;
- (NSDictionary<NSString*,NSString*>*)getConferenceDetails:(NSString*)conferenceId;
- (NSArray<NSString*>*)getConferenceCalls:(NSString*)conferenceId;
- (BOOL)hangUpConference:(NSString*)conferenceId;
- (void)setActiveParticipant:(NSString*)callId forConference:(NSString*)conferenceId;
- (void)setConferenceLayout:(int)layout forConference:(NSString*)conferenceId;
- (NSArray*)getConferenceInfo:(NSString*)conferenceId;
- (void)setConferenceModerator:(NSString*)participantId forConference:(NSString*)conferenceId active:(BOOL)isActive;
- (void)muteConferenceParticipant:(NSString*)participantId forConference:(NSString*)conferenceId active:(BOOL)isActive;
- (void)hangupConferenceParticipant:(NSString*)participantId forConference:(NSString*)conferenceId;
- (BOOL)requestMediaChange:(NSString*)callId accountId:(NSString*)accountId withMedia:(NSArray*)mediaList;
- (void)answerMediaChangeResquest:(NSString*)callId accountId:(NSString*)accountId withMedia: (NSArray*)mediaList;
- (NSString*)placeCallWithAccountId:(NSString*)accountId toParticipantId:(NSString*)participantId withMedia: (NSArray*)mediaList;
- (NSDictionary<NSString*,NSString*>*)callDetailsWithCallId:(NSString*)callId accountId:(NSString*)accountId;
- (NSArray<NSString*>*)callsForAccountId:(NSString*)accountId;
- (void)sendTextMessageWithCallID:(NSString*)callId accountId:(NSString*)accountId message:(NSDictionary*)message from:(NSString*)jamiId isMixed:(bool)isMixed;
- (BOOL)muteMedia:(NSString*)callId accountId:(NSString*)accountId mediaType:(NSString*)media muted:(bool)muted;
- (BOOL)joinConference:(NSString*)confID call:(NSString*)callID accountId:(NSString*)accountId account2Id:(NSString*)account2Id;
- (BOOL)joinConferences:(NSString*)firstConf secondConference:(NSString*)secondConf accountId:(NSString*)accountId account2Id:(NSString*)account2Id;
- (BOOL)joinCall:(NSString*)firstCall second:(NSString*)secondCall accountId:(NSString*)accountId account2Id:(NSString*)account2Id;
- (NSArray*)getConferenceInfo:(NSString*)conferenceId accountId:(NSString*)accountId;
- (NSDictionary<NSString*,NSString*>*)getConferenceDetails:(NSString*)conferenceId accountId:(NSString*)accountId;
- (NSArray<NSString*>*)getConferenceCalls:(NSString*)conferenceId accountId:(NSString*)accountId;
- (BOOL)hangUpConference:(NSString*)conferenceId accountId:(NSString*)accountId;
- (void)setActiveParticipant:(NSString*)callId forConference:(NSString*)conferenceId accountId:(NSString*)accountId;
- (void)setConferenceLayout:(int)layout forConference:(NSString*)conferenceId accountId:(NSString*)accountId;
- (void)setConferenceModerator:(NSString*)participantId forConference:(NSString*)conferenceId accountId:(NSString*)accountId active:(BOOL)isActive;
- (void)muteConferenceParticipant:(NSString*)participantId forConference:(NSString*)conferenceId accountId:(NSString*)accountId active:(BOOL)isActive;
- (void)hangupConferenceParticipant:(NSString*)participantId forConference:(NSString*)conferenceId accountId:(NSString*)accountId;
@end
......@@ -48,7 +48,7 @@ static id <CallsAdapterDelegate> _delegate;
std::map<std::string, std::shared_ptr<CallbackWrapperBase>> callHandlers;
//State changed signal
callHandlers.insert(exportable_callback<CallSignal::StateChange>([&](const std::string& callId,
callHandlers.insert(exportable_callback<CallSignal::StateChange>([&](const std::string& accountId, const std::string& callId,
const std::string& state,
int errorCode) {
if (CallsAdapter.delegate) {
......@@ -56,12 +56,14 @@ static id <CallsAdapterDelegate> _delegate;
NSString* stateString = [NSString stringWithUTF8String:state.c_str()];
[CallsAdapter.delegate didChangeCallStateWithCallId:callIdString
state:stateString
accountId:[NSString stringWithUTF8String:accountId.c_str()]
stateCode:errorCode];
}
}));
//Incoming message signal
callHandlers.insert(exportable_callback<CallSignal::IncomingMessage>([&](const std::string& callId,
callHandlers.insert(exportable_callback<CallSignal::IncomingMessage>([&](const std::string& accountId,
const std::string& callId,
const std::string& fromURI,
const std::map<std::string,
std::string>& message) {
......@@ -141,22 +143,22 @@ static id <CallsAdapterDelegate> _delegate;
}
}));
callHandlers.insert(exportable_callback<CallSignal::ConferenceCreated>([&](const std::string& confId) {
callHandlers.insert(exportable_callback<CallSignal::ConferenceCreated>([&](const std::string& accountId, const std::string& confId) {
if (CallsAdapter.delegate) {
NSString* confIdString = [NSString stringWithUTF8String:confId.c_str()];
[CallsAdapter.delegate conferenceCreatedWithConference: confIdString];
[CallsAdapter.delegate conferenceCreatedWithConference: confIdString accountId:[NSString stringWithUTF8String:accountId.c_str()] ];
}
}));
callHandlers.insert(exportable_callback<CallSignal::ConferenceChanged>([&](const std::string& confId, const std::string& state) {
callHandlers.insert(exportable_callback<CallSignal::ConferenceChanged>([&](const std::string& accountId, const std::string& confId, const std::string& state) {
if (CallsAdapter.delegate) {
NSString* confIdString = [NSString stringWithUTF8String:confId.c_str()];
NSString* stateString = [NSString stringWithUTF8String:state.c_str()];
[CallsAdapter.delegate conferenceChangedWithConference: confIdString state: stateString];
[CallsAdapter.delegate conferenceChangedWithConference: confIdString accountId: [NSString stringWithUTF8String:accountId.c_str()] state: stateString];
}
}));
callHandlers.insert(exportable_callback<CallSignal::ConferenceRemoved>([&](const std::string& confId) {
callHandlers.insert(exportable_callback<CallSignal::ConferenceRemoved>([&](const std::string& accountId, const std::string& confId) {
if (CallsAdapter.delegate) {
NSString* confIdString = [NSString stringWithUTF8String:confId.c_str()];
[CallsAdapter.delegate conferenceRemovedWithConference: confIdString];
......@@ -175,115 +177,116 @@ static id <CallsAdapterDelegate> _delegate;
#pragma mark -
- (BOOL)acceptCallWithId:(NSString*)callId withMedia:(NSArray*)mediaList {
return acceptWithMedia(std::string([callId UTF8String]), [Utils arrayOfDictionnarisToVectorOfMap: mediaList]);
- (BOOL)acceptCallWithId:(NSString*)callId accountId:(NSString*)accountId withMedia:(NSArray*)mediaList {
return acceptWithMedia(std::string([accountId UTF8String]), std::string([callId UTF8String]), [Utils arrayOfDictionnarisToVectorOfMap: mediaList]);
}
- (BOOL)refuseCallWithId:(NSString*)callId {
return refuse(std::string([callId UTF8String]));
- (BOOL)refuseCallWithId:(NSString*)callId accountId:(NSString*)accountId {
return refuse(std::string([accountId UTF8String]), std::string([callId UTF8String]));
}
- (BOOL)hangUpCallWithId:(NSString*)callId {
return hangUp(std::string([callId UTF8String]));
- (BOOL)hangUpCallWithId:(NSString*)callId accountId:(NSString*)accountId {
return hangUp(std::string([accountId UTF8String]), std::string([callId UTF8String]));
}
- (BOOL)holdCallWithId:(NSString*)callId {
return hold(std::string([callId UTF8String]));
- (BOOL)holdCallWithId:(NSString*)callId accountId:(NSString*)accountId {
return hold(std::string([accountId UTF8String]), std::string([callId UTF8String]));
}
- (BOOL)unholdCallWithId:(NSString*)callId {
return unhold(std::string([callId UTF8String]));
- (BOOL)unholdCallWithId:(NSString*)callId accountId:(NSString*)accountId {
return unhold(std::string([accountId UTF8String]), std::string([callId UTF8String]));
}
- (void)playDTMF:(NSString*)code {
playDTMF(std::string([code UTF8String]));
}
- (BOOL)requestMediaChange:(NSString*)callId withMedia: (NSArray*)mediaList {
requestMediaChange(std::string([callId UTF8String]), [Utils arrayOfDictionnarisToVectorOfMap: mediaList]);
- (BOOL)requestMediaChange:(NSString*)callId accountId:(NSString*)accountId withMedia:(NSArray*)mediaList {
requestMediaChange(std::string([accountId UTF8String]), std::string([callId UTF8String]), [Utils arrayOfDictionnarisToVectorOfMap: mediaList]);
return false;
}
- (void)answerMediaChangeResquest:(NSString*)callId withMedia: (NSArray*)mediaList {
answerMediaChangeRequest(std::string([callId UTF8String]), [Utils arrayOfDictionnarisToVectorOfMap: mediaList]);
- (void)answerMediaChangeResquest:(NSString*)callId accountId:(NSString*)accountId withMedia: (NSArray*)mediaList {
answerMediaChangeRequest(std::string([accountId UTF8String]), std::string([callId UTF8String]), [Utils arrayOfDictionnarisToVectorOfMap: mediaList]);
}
- (NSString*)placeCallWithAccountId:(NSString*)accountId toRingId:(NSString*)ringId withMedia:(NSArray*)mediaList {
- (NSString*)placeCallWithAccountId:(NSString*)accountId toParticipantId:(NSString*)participantId withMedia:(NSArray*)mediaList {
std::string callId;
callId = placeCallWithMedia(std::string([accountId UTF8String]), std::string([ringId UTF8String]), [Utils arrayOfDictionnarisToVectorOfMap:mediaList]);
callId = placeCallWithMedia(std::string([accountId UTF8String]), std::string([participantId UTF8String]), [Utils arrayOfDictionnarisToVectorOfMap:mediaList]);
return [NSString stringWithUTF8String:callId.c_str()];
}
- (void)sendTextMessageWithCallID:(NSString*)callId message:(NSDictionary*)message accountId:(NSString*)accountId sMixed:(bool)isMixed {
sendTextMessage(std::string([callId UTF8String]), [Utils dictionnaryToMap:message], std::string([accountId UTF8String]), isMixed);
}
- (NSDictionary<NSString*,NSString*>*)callDetailsWithCallId:(NSString*)callId {
std::map<std::string, std::string> callDetails = getCallDetails(std::string([callId UTF8String]));
- (NSDictionary<NSString*,NSString*>*)callDetailsWithCallId:(NSString*)callId accountId:(NSString*)accountId {
std::map<std::string, std::string> callDetails = getCallDetails(std::string([accountId UTF8String]), std::string([callId UTF8String]));
return [Utils mapToDictionnary:callDetails];
}
- (NSArray<NSString*>*)calls {
std::vector<std::string> calls = getCallList();
- (NSArray<NSString*>*)callsForAccountId:(NSString*)accountId {
std::vector<std::string> calls = getCallList(std::string([accountId UTF8String]));
return [Utils vectorToArray:calls];
}
- (BOOL)muteMedia:(NSString*)callId mediaType:(NSString*)media muted:(bool)muted {
return muteLocalMedia(std::string([callId UTF8String]), std::string([media UTF8String]), muted);
- (void)sendTextMessageWithCallID:(NSString*)callId accountId:(NSString*)accountId message:(NSDictionary*)message from:(NSString*)jamiId isMixed:(bool)isMixed {
sendTextMessage(std::string([accountId UTF8String]), std::string([callId UTF8String]), [Utils dictionnaryToMap:message], std::string([jamiId UTF8String]), isMixed);
}
- (BOOL)joinConference:(NSString*)confID call:(NSString*)callID {
return addParticipant(std::string([callID UTF8String]), std::string([confID UTF8String]));
- (BOOL)muteMedia:(NSString*)callId accountId:(NSString*)accountId mediaType:(NSString*)media muted:(bool)muted {
return muteLocalMedia(std::string([accountId UTF8String]), std::string([callId UTF8String]), std::string([media UTF8String]), muted);
}
- (BOOL)joinCall:(NSString*)firstCall second:(NSString*)secondCall {
return joinParticipant(std::string([firstCall UTF8String]), std::string([secondCall UTF8String]));
- (BOOL)joinConference:(NSString*)confID call:(NSString*)callID accountId:(NSString*)accountId account2Id:(NSString*)account2Id {
return addParticipant(std::string([accountId UTF8String]), std::string([callID UTF8String]), std::string([account2Id UTF8String]), std::string([confID UTF8String]));
}
- (BOOL)joinConferences:(NSString*)firstConf secondConference:(NSString*)secondConf {
return joinConference(std::string([firstConf UTF8String]), std::string([secondConf UTF8String]));
- (BOOL)joinConferences:(NSString*)firstConf secondConference:(NSString*)secondConf accountId:(NSString*)accountId account2Id:(NSString*)account2Id {
return joinConference(std::string([accountId UTF8String]), std::string([firstConf UTF8String]), std::string([account2Id UTF8String]), std::string([secondConf UTF8String]));
}
- (BOOL)hangUpConference:(NSString*)conferenceId {
return hangUpConference(std::string([conferenceId UTF8String]));
- (BOOL)joinCall:(NSString*)firstCall second:(NSString*)secondCall accountId:(NSString*)accountId account2Id:(NSString*)account2Id {
return joinParticipant(std::string([accountId UTF8String]), std::string([firstCall UTF8String]), std::string([account2Id UTF8String]), std::string([secondCall UTF8String]));
}
- (NSArray*)getConferenceInfo:(NSString*)conferenceId accountId:(NSString*)accountId {
auto result = getConferenceInfos(std::string([accountId UTF8String]), std::string([conferenceId UTF8String]));
NSArray* arrayResult = [Utils vectorOfMapsToArray:result];
return arrayResult;
}
- (void)setActiveParticipant:(NSString*)callId forConference:(NSString*)conferenceId {
setActiveParticipant(std::string([conferenceId UTF8String]), std::string([callId UTF8String]));
- (NSDictionary<NSString*,NSString*>*)getConferenceDetails:(NSString*)conferenceId accountId:(NSString*)accountId {
std::map<std::string, std::string> confDetails = getConferenceDetails(std::string([accountId UTF8String]), std::string([conferenceId UTF8String]));
return [Utils mapToDictionnary:confDetails];
}
- (void)setConferenceLayout:(int)layout forConference:(NSString*)conferenceId {
setConferenceLayout(std::string([conferenceId UTF8String]), layout);
- (NSArray<NSString*>*)getConferenceCalls:(NSString*)conferenceId accountId:(NSString*)accountId {
std::vector<std::string> calls = getParticipantList(std::string([accountId UTF8String]), std::string([conferenceId UTF8String]));
return [Utils vectorToArray:calls];
}
- (void)setConferenceModerator:(NSString*)participantId forConference:(NSString*)conferenceId active:(BOOL)isActive {
setModerator(std::string([conferenceId UTF8String]), std::string([participantId UTF8String]), isActive);
- (BOOL)hangUpConference:(NSString*)conferenceId accountId:(NSString*)accountId {
return hangUpConference(std::string([accountId UTF8String]), std::string([conferenceId UTF8String]));
}
- (void)muteConferenceParticipant:(NSString*)participantId forConference:(NSString*)conferenceId active:(BOOL)isActive {
muteParticipant(std::string([conferenceId UTF8String]), std::string([participantId UTF8String]), isActive);
- (void)setActiveParticipant:(NSString*)callId forConference:(NSString*)conferenceId accountId:(NSString*)accountId {
setActiveParticipant(std::string([accountId UTF8String]), std::string([conferenceId UTF8String]), std::string([callId UTF8String]));
}
- (void)hangupConferenceParticipant:(NSString*)participantId forConference:(NSString*)conferenceId {
hangupParticipant(std::string([conferenceId UTF8String]), std::string([participantId UTF8String]));
- (void)setConferenceLayout:(int)layout forConference:(NSString*)conferenceId accountId:(NSString*)accountId {
setConferenceLayout(std::string([accountId UTF8String]), std::string([conferenceId UTF8String]), layout);
}
- (NSArray*)getConferenceInfo:(NSString*)conferenceId {
auto result = getConferenceInfos(std::string([conferenceId UTF8String]));
NSArray* arrayResult = [Utils vectorOfMapsToArray:result];
return arrayResult;
- (void)setConferenceModerator:(NSString*)participantId forConference:(NSString*)conferenceId accountId:(NSString*)accountId active:(BOOL)isActive {
setModerator(std::string([accountId UTF8String]), std::string([conferenceId UTF8String]), std::string([participantId UTF8String]), isActive);
}
- (NSDictionary<NSString*,NSString*>*)getConferenceDetails:(NSString*)conferenceId {
std::map<std::string, std::string> confDetails = getConferenceDetails(std::string([conferenceId UTF8String]));
return [Utils mapToDictionnary:confDetails];
- (void)muteConferenceParticipant:(NSString*)participantId forConference:(NSString*)conferenceId accountId:(NSString*)accountId active:(BOOL)isActive {
muteParticipant(std::string([accountId UTF8String]), std::string([conferenceId UTF8String]), std::string([participantId UTF8String]), isActive);
}
- (NSArray<NSString*>*)getConferenceCalls:(NSString*)conferenceId {
std::vector<std::string> calls = getParticipantList(std::string([conferenceId UTF8String]));
return [Utils vectorToArray:calls];
- (void)hangupConferenceParticipant:(NSString*)participantId forConference:(NSString*)conferenceId accountId:(NSString*)accountId {
hangupParticipant(std::string([accountId UTF8String]), std::string([conferenceId UTF8String]), std::string([participantId UTF8String]));
}
#pragma mark AccountAdapterDelegate
+ (id <CallsAdapterDelegate>)delegate {
......
......@@ -23,10 +23,12 @@
#import <AVFoundation/AVFoundation.h>
@protocol VideoAdapterDelegate;
@protocol DecodingAdapterDelegate;
@interface VideoAdapter : NSObject
@property (class, nonatomic, weak) id <VideoAdapterDelegate> delegate;
@property (class, nonatomic, weak) id <VideoAdapterDelegate> videoDelegate;
@property (class, nonatomic, weak) id <DecodingAdapterDelegate> decodingDelegate;
- (void)addVideoDeviceWithName:(NSString*)deviceName withDevInfo:(NSDictionary*)deviceInfoDict;
- (void)setDefaultDevice:(NSString*)deviceName;
......@@ -36,18 +38,18 @@
withHeight:(NSInteger)h;
- (void)removeSinkTargetWithSinkId:(NSString*)sinkId;
- (void)writeOutgoingFrameWithBuffer:(CVImageBufferRef)image
angle:(int)angle;
angle:(int)angle
videoInputId:(NSString*)videoInputId;
- (void)setDecodingAccelerated:(BOOL)state;
- (BOOL)getDecodingAccelerated;
- (void)switchInput:(NSString*)deviceName;
- (void)switchInput:(NSString*)deviceName forCall:(NSString*) callID;
- (void)switchInput:(NSString*)videoInputId accountId:(NSString*)accountId forCall:(NSString*)callID;
- (void)setEncodingAccelerated:(BOOL)state;
- (BOOL)getEncodingAccelerated;
- (void)stopAudioDevice;
- (NSString*)startLocalRecording:(NSString*) path audioOnly:(BOOL)audioOnly;
- (NSString*)startLocalRecording:(NSString*)videoInputId path:(NSString*)path;
- (void)stopLocalRecording:(NSString*) path;
- (void)startCamera;
- (void)stopCamera;
- (void)openVideoInput:(NSString*)path;
- (void)closeVideoInput:(NSString*)path;
- (NSString*)createMediaPlayer:(NSString*)path;
- (bool)pausePlayer:(NSString*)playerId pause:(BOOL)pause;
- (bool)closePlayer:(NSString*)playerId;
......
......@@ -46,14 +46,14 @@ struct Renderer
void bindAVSinkFunctions() {
avtarget.push = [this](std::unique_ptr<DRing::VideoFrame> frame) {
if(!VideoAdapter.delegate) {
if(!VideoAdapter.videoDelegate) {
return;
}
@autoreleasepool {
UIImage *image = [Utils
convertHardwareDecodedFrameToImage: std::move(frame->pointer())];
isRendering = true;
[VideoAdapter.delegate writeFrameWithImage: image forCallId: rendererId];
[VideoAdapter.videoDelegate writeFrameWithImage: image forCallId: rendererId];
isRendering = false;
}
};
......@@ -72,7 +72,7 @@ struct Renderer
target.push = [this](DRing::SinkTarget::FrameBufferPtr buf) {
std::lock_guard<std::mutex> lk(renderMutex);
daemonFramePtr_ = std::move(buf);
if(VideoAdapter.delegate) {
if(VideoAdapter.videoDelegate) {
@autoreleasepool {
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef bitmapContext = CGBitmapContextCreate((void *)daemonFramePtr_->ptr,
......@@ -88,7 +88,7 @@ struct Renderer
UIImage* image = [UIImage imageWithCGImage:cgImage];
CGImageRelease(cgImage);
isRendering = true;
[VideoAdapter.delegate writeFrameWithImage: image forCallId: rendererId];
[VideoAdapter.videoDelegate writeFrameWithImage: image forCallId: rendererId];
isRendering = false;
}
}
......@@ -101,8 +101,9 @@ struct Renderer
std::map<std::string, std::shared_ptr<Renderer>> renderers;
}
// Static delegate that will receive the propagated daemon events
static id <VideoAdapterDelegate> _delegate;
// Static delegates that will receive the propagated daemon events
static id <VideoAdapterDelegate> _videoDelegate;
static id <DecodingAdapterDelegate> _decodingDelegate;
#pragma mark Init
......@@ -125,44 +126,39 @@ static id <VideoAdapterDelegate> _delegate;
int w,
int h,
bool is_mixer) {
if(VideoAdapter.delegate) {
if(VideoAdapter.decodingDelegate) {
NSString* rendererId = [NSString stringWithUTF8String:renderer_id.c_str()];
NSString* codecName = @"";
std::map<std::string, std::string> callDetails = getCallDetails(renderer_id);
if (callDetails.find("VIDEO_CODEC") != callDetails.end()) {
codecName = [NSString stringWithUTF8String: callDetails["VIDEO_CODEC"].c_str()];
}
[VideoAdapter.delegate decodingStartedWithRendererId:rendererId withWidth:(NSInteger)w withHeight:(NSInteger)h withCodec: codecName];
[VideoAdapter.decodingDelegate decodingStartedWithRendererId:rendererId withWidth:(NSInteger)w withHeight:(NSInteger)h];
}
}));
videoHandlers.insert(exportable_callback<VideoSignal::DecodingStopped>([&](const std::string& renderer_id,
const std::string& shm_path,
bool is_mixer) {
if(VideoAdapter.delegate) {
if(VideoAdapter.decodingDelegate) {
NSString* rendererId = [NSString stringWithUTF8String:renderer_id.c_str()];
[VideoAdapter.delegate decodingStoppedWithRendererId:rendererId];
[VideoAdapter.decodingDelegate decodingStoppedWithRendererId:rendererId];
}
}));
videoHandlers.insert(exportable_callback<VideoSignal::StartCapture>([&](const std::string& device) {
if(VideoAdapter.delegate) {
if(VideoAdapter.videoDelegate) {
NSString* deviceString = [NSString stringWithUTF8String:device.c_str()];
[VideoAdapter.delegate startCaptureWithDevice:deviceString];
[VideoAdapter.videoDelegate startCaptureWithDevice:deviceString];
}
}));
videoHandlers.insert(exportable_callback<VideoSignal::StopCapture>([&]() {
if(VideoAdapter.delegate) {
[VideoAdapter.delegate stopCapture];
videoHandlers.insert(exportable_callback<VideoSignal::StopCapture>([&](const std::string& deviceId) {
if(VideoAdapter.videoDelegate) {
[VideoAdapter.videoDelegate stopCapture];
}
}));
videoHandlers.insert(exportable_callback<MediaPlayerSignal::FileOpened>([&](const std::string& playerId, std::map<std::string, std::string> playerInfo) {
if(VideoAdapter.delegate) {
if(VideoAdapter.videoDelegate) {
NSString* player = @(playerId.c_str());
NSMutableDictionary* info = [Utils mapToDictionnary:playerInfo];
[VideoAdapter.delegate fileOpenedFor:player fileInfo:info];
[VideoAdapter.videoDelegate fileOpenedFor:player fileInfo:info];
}
}));
......@@ -211,8 +207,10 @@ static id <VideoAdapterDelegate> _delegate;
}
- (void)writeOutgoingFrameWithBuffer:(CVImageBufferRef)image
angle:(int)angle{
auto frame = DRing::getNewFrame();
angle:(int)angle
videoInputId:(NSString*)videoInputId
{
auto frame = DRing::getNewFrame(std::string([videoInputId UTF8String]));
if(!frame) {
return;
}
......@@ -221,7 +219,7 @@ static id <VideoAdapterDelegate> _delegate;
fromImageBuffer:image
angle:(int) angle];
DRing::publishFrame();
DRing::publishFrame(std::string([videoInputId UTF8String]));
}
- (void)addVideoDeviceWithName:(NSString*)deviceName withDevInfo:(NSDictionary*)deviceInfoDict {
......@@ -254,20 +252,16 @@ static id <VideoAdapterDelegate> _delegate;
return DRing::getEncodingAccelerated();
}
- (void)switchInput:(NSString*)deviceName {
DRing::switchInput(std::string([deviceName UTF8String]));
}
- (void)switchInput:(NSString*)deviceName forCall:(NSString*) callID {
DRing::switchInput(std::string([callID UTF8String]), std::string([deviceName UTF8String]));
- (void)switchInput:(NSString*)videoInputId accountId:(NSString*)accountId forCall:(NSString*)callID {
DRing::switchInput(std::string([accountId UTF8String]), std::string([callID UTF8String]), std::string([videoInputId UTF8String]));
}
- (void)stopAudioDevice {
DRing::stopAudioDevice();
}
- (NSString* )startLocalRecording:(NSString*) path audioOnly:(BOOL)audioOnly {
return @(DRing::startLocalRecorder(audioOnly, std::string([path UTF8String])).c_str());
- (NSString*)startLocalRecording:(NSString*)videoInputId path:(NSString*)path {
return @(DRing::startLocalMediaRecorder(std::string([videoInputId UTF8String]), std::string([path UTF8String])).c_str());
}
- (void)stopLocalRecording:(NSString*) path {
......@@ -282,7 +276,7 @@ static id <VideoAdapterDelegate> _delegate;
}
-(bool)closePlayer:(NSString*)playerId {
return DRing::closePlayer(std::string([playerId UTF8String]));
return DRing::closeMediaPlayer(std::string([playerId UTF8String]));
}
- (bool)mutePlayerAudio:(NSString*)playerId mute:(BOOL)mute {
......@@ -297,22 +291,32 @@ static id <VideoAdapterDelegate> _delegate;
return DRing::getPlayerPosition(std::string([playerId UTF8String]));
}
- (void)startCamera {
DRing::startCamera();
- (void)openVideoInput:(NSString*)path {
DRing::openVideoInput(std::string([path UTF8String]));
}
- (void)closeVideoInput:(NSString*)path {
DRing::closeVideoInput(std::string([path UTF8String]));
}
#pragma mark VideoAdapterDelegate
+ (id <VideoAdapterDelegate>)videoDelegate {
return _videoDelegate;
}
- (void)stopCamera {
DRing::stopCamera();
+ (void) setVideoDelegate:(id<VideoAdapterDelegate>)videoDelegate {
_videoDelegate = videoDelegate;
}
#pragma mark PresenceAdapterDelegate
#pragma mark DecodingAdapterDelegate
+ (id <VideoAdapterDelegate>)delegate {
return _delegate;
+ (id <DecodingAdapterDelegate>)decodingDelegate {
return _decodingDelegate;
}
+ (void) setDelegate:(id<VideoAdapterDelegate>)delegate {
_delegate = delegate;
+ (void) setDecodingDelegate:(id<DecodingAdapterDelegate>)decodingDelegate {
_decodingDelegate = decodingDelegate;
}
#pragma mark -
......
......@@ -581,7 +581,7 @@ extension CallViewModel {
}
guard let secondCall = self.callService.call(callID: contact.conferenceID) else { return }
if call.participantsCallId.count == 1 {
self.callService.joinCall(firstCall: call.callId, secondCall: secondCall.callId)
self.callService.joinCall(firstCallId: call.callId, secondCallId: secondCall.callId)
} else {
self.callService.joinConference(confID: contact.conferenceID, callID: self.rendererId)
}
......@@ -752,10 +752,9 @@ extension CallViewModel {
guard let account = self.accountService.currentAccount else { return false }
return self.callService.isModerator(participantId: account.jamiId, inConference: self.rendererId)
}
func getItemsForConferenceMenu(participantId: String, callId: String) -> [MenuItem] {
let conference = self.callService.call(callID: self.rendererId)
let active = self.callService.isParticipant(participantURI: participantId, activeIn: self.rendererId)
let active = self.callService.isParticipant(participantURI: participantId, activeIn: self.rendererId, accountId: conference?.accountId ?? "")
// menu for local call
if self.isLocalCall(participantId: participantId) || participantId.isEmpty {
return menuItemsManager.getMenuItemsForLocalCall(conference: conference, active: active)
......
......@@ -131,7 +131,7 @@ class SendFileViewModel: Stateable, ViewModel {
self.injectionBag = injectionBag
if !audioOnly {
videoService.setCameraOrientation(orientation: UIDevice.current.orientation)
videoService.startCamera()
videoService.startMediumCamera()
}
videoService.capturedVideoFrame.asObservable()
.subscribe(onNext: { [weak self] frame in
......@@ -163,7 +163,10 @@ class SendFileViewModel: Stateable, ViewModel {
let dateString = dateFormatter.string(from: date)
let random = String(arc4random_uniform(9999))
let nameForRecordingFile = dateString + "_" + random
guard let url = self.fileTransferService.getFilePathForRecordings(forFile: nameForRecordingFile, accountID: conversation.accountId, conversationID: conversation.id, isSwarm: self.conversation.isSwarm()) else { return }
guard let url = self.fileTransferService.getFilePathForRecordings(forFile: nameForRecordingFile,
accountID: conversation.accountId,
conversationID: conversation.id,
isSwarm: self.conversation.isSwarm()) else { return }
guard let name = self.videoService
.startLocalRecorder(audioOnly: audioOnly, path: url.path) else {
return
......
......@@ -68,6 +68,7 @@ enum CallDetailKey: String {
case videoSourceKey = "VIDEO_SOURCE"
case audioOnlyKey = "AUDIO_ONLY"
case confID = "CONF_ID"
case videoCodec = "VIDEO_CODEC"
}
enum MediaAttributeKey: String {
......
......@@ -20,15 +20,15 @@
*/
@objc protocol CallsAdapterDelegate {
func didChangeCallState(withCallId callId: String, state: String, stateCode: NSInteger)
func didChangeCallState(withCallId callId: String, state: String, accountId: String, stateCode: NSInteger)
func didReceiveMediaChangeRequest(withAccountId accountId: String, callId: String, withMedia: [[String: String]])
func didReceiveMessage(withCallId callId: String, fromURI uri: String, message: [String: String])
func receivingCall(withAccountId accountId: String, callId: String, fromURI uri: String, withMedia: [[String: String]])
func callPlacedOnHold(withCallId callId: String, holding: Bool)
func audioMuted(call callId: String, mute: Bool)
func videoMuted(call callId: String, mute: Bool)
func conferenceCreated(conference conferenceID: String)
func conferenceChanged(conference conferenceID: String, state: String)
func conferenceCreated(conference conferenceID: String, accountId: String)
func conferenceChanged(conference conferenceID: String, accountId: String, state: String)
func conferenceRemoved(conference conferenceID: String)
func conferenceInfoUpdated(conference conferenceID: String, info: [[String: String]])
func didChangeMediaNegotiationStatus(withCallId callId: String, event: String, withMedia: [[String: String]])
......
......@@ -56,6 +56,7 @@ class CallsService: CallsAdapterDelegate {
var calls = BehaviorRelay<[String: CallModel]>(value: [String: CallModel]())
var pendingConferences = [String: Set<String>]()
var createdConferences = Set<String>() /// set of created conferences, waiting to calls to be attached
private let ringVCardMIMEType = "x-ring/ring.profile.vcard;"
......@@ -102,15 +103,15 @@ class CallsService: CallsAdapterDelegate {
@objc
func refuseUnansweredCall(_ notification: NSNotification) {
guard let callid = notification.userInfo?[NotificationUserInfoKeys.callID.rawValue] as? String else {
guard let callId = notification.userInfo?[NotificationUserInfoKeys.callID.rawValue] as? String else {
return
}
guard let call = self.call(callID: callid) else {
guard let call = self.call(callID: callId) else {
return
}
if call.state == .incoming {
self.refuse(callId: callid)
self.refuse(callId: callId)
.subscribe({_ in
print("Call ignored")
})
......@@ -122,6 +123,11 @@ class CallsService: CallsAdapterDelegate {
return self.calls.value[callID]
}
func getVideoCodec(call: CallModel) -> String? {
let callDetails = self.callsAdapter.callDetails(withCallId: call.callId, accountId: call.accountId)
return callDetails?[CallDetailKey.videoCodec.rawValue]
}
func call(participantHash: String, accountID: String) -> CallModel? {
return self.calls
.value.values
......@@ -137,7 +143,7 @@ class CallsService: CallsAdapterDelegate {
completable(.error(CallServiceError.acceptCallFailed))
return Disposables.create { }
}
let success = self.callsAdapter.acceptCall(withId: callId, withMedia: call?.mediaList)
let success = self.callsAdapter.acceptCall(withId: callId, accountId: call?.accountId, withMedia: call?.mediaList)
if success {
completable(.completed)
} else {
......@@ -149,30 +155,33 @@ class CallsService: CallsAdapterDelegate {
func joinConference(confID: String, callID: String) {
guard let secondConf = self.call(callID: callID) else { return }
guard let firstConf = self.call(callID: confID) else { return }
if let pending = self.pendingConferences[confID], !pending.isEmpty {
self.pendingConferences[confID]!.insert(callID)
} else {
self.pendingConferences[confID] = [callID]
}
if secondConf.participantsCallId.count == 1 {
self.callsAdapter.joinConference(confID, call: callID)
self.callsAdapter.joinConference(confID, call: callID, accountId: firstConf.accountId, account2Id: secondConf.accountId)
} else {
self.callsAdapter.joinConferences(confID, secondConference: callID)
self.callsAdapter.joinConferences(confID, secondConference: callID, accountId: firstConf.accountId, account2Id: secondConf.accountId)
}
}
func joinCall(firstCall: String, secondCall: String) {
if let pending = self.pendingConferences[firstCall], !pending.isEmpty {
self.pendingConferences[firstCall]!.insert(secondCall)
func joinCall(firstCallId: String, secondCallId: String) {
guard let firstCall = self.call(callID: firstCallId) else { return }
guard let secondCall = self.call(callID: secondCallId) else { return }
if let pending = self.pendingConferences[firstCallId], !pending.isEmpty {
self.pendingConferences[firstCallId]!.insert(secondCallId)
} else {
self.pendingConferences[firstCall] = [secondCall]
self.pendingConferences[firstCallId] = [secondCallId]
}
self.callsAdapter.joinCall(firstCall, second: secondCall)
self.callsAdapter.joinCall(firstCallId, second: secondCallId, accountId: firstCall.accountId, account2Id: secondCall.accountId)
}
func isParticipant(participantURI: String?, activeIn conferenceId: String) -> Bool? {
func isParticipant(participantURI: String?, activeIn conferenceId: String, accountId: String) -> Bool? {
guard let uri = participantURI,
let participantsArray = self.callsAdapter.getConferenceInfo(conferenceId) as? [[String: String]] else { return nil }
let participantsArray = self.callsAdapter.getConferenceInfo(conferenceId, accountId: accountId) as? [[String: String]] else { return nil }
let participants = self.arrayToConferenceParticipants(participants: participantsArray, onlyURIAndActive: true)
for participant in participants where participant.uri?.filterOutHost() == uri.filterOutHost() {
return participant.isActive
......@@ -210,11 +219,11 @@ class CallsService: CallsAdapterDelegate {
func setActiveParticipant(conferenceId: String, maximixe: Bool, jamiId: String) {
guard let conference = self.call(callID: conferenceId),
let isActive = self.isParticipant(participantURI: jamiId, activeIn: conferenceId) else { return }
let isActive = self.isParticipant(participantURI: jamiId, activeIn: conferenceId, accountId: conference.accountId) else { return }
let newLayout = isActive ? self.getNewLayoutForActiveParticipant(currentLayout: conference.layout, maximixe: maximixe) : .oneWithSmal
conference.layout = newLayout
self.callsAdapter.setActiveParticipant(jamiId, forConference: conferenceId)
self.callsAdapter.setConferenceLayout(newLayout.rawValue, forConference: conferenceId)
self.callsAdapter.setActiveParticipant(jamiId, forConference: conferenceId, accountId: conference.accountId)
self.callsAdapter.setConferenceLayout(newLayout.rawValue, forConference: conferenceId, accountId: conference.accountId)
}
private func getNewLayoutForActiveParticipant(currentLayout: CallLayout, maximixe: Bool) -> CallLayout {
......@@ -236,7 +245,13 @@ class CallsService: CallsAdapterDelegate {
userName: String,
isAudioOnly: Bool = false) -> Observable<CallModel> {
let call = self.calls.value[callId]
let placeCall = self.placeCall(withAccount: account, toRingId: contactId, userName: userName, isAudioOnly: isAudioOnly, withMedia: call?.mediaList ?? [[String: String]]()).asObservable().publish()
let placeCall = self.placeCall(withAccount: account,
toRingId: contactId,
userName: userName,
isAudioOnly: isAudioOnly,
withMedia: call?.mediaList ?? [[String: String]]())
.asObservable()
.publish()
placeCall
.subscribe(onNext: { (callModel) in
self.inConferenceCalls.onNext(callModel)
......@@ -253,7 +268,11 @@ class CallsService: CallsAdapterDelegate {
func refuse(callId: String) -> Completable {
return Completable.create(subscribe: { completable in
let success = self.callsAdapter.refuseCall(withId: callId)
guard let call = self.call(callID: callId) else {
completable(.error(CallServiceError.hangUpCallFailed))
return Disposables.create { }
}
let success = self.callsAdapter.refuseCall(withId: callId, accountId: call.accountId)
if success {
completable(.completed)
} else {
......@@ -266,7 +285,11 @@ class CallsService: CallsAdapterDelegate {
func hangUp(callId: String) -> Completable {
return Completable.create(subscribe: { completable in
var success: Bool
success = self.callsAdapter.hangUpCall(withId: callId)
guard let call = self.call(callID: callId) else {
completable(.error(CallServiceError.hangUpCallFailed))
return Disposables.create { }
}
success = self.callsAdapter.hangUpCall(withId: callId, accountId: call.accountId)
if success {
completable(.completed)
} else {
......@@ -284,9 +307,9 @@ class CallsService: CallsAdapterDelegate {
}
var success: Bool
if call.participantsCallId.count < 2 {
success = self.callsAdapter.hangUpCall(withId: callId)
success = self.callsAdapter.hangUpCall(withId: callId, accountId: call.accountId)
} else {
success = self.callsAdapter.hangUpConference(callId)
success = self.callsAdapter.hangUpConference(callId, accountId: call.accountId)
}
if success {
completable(.completed)
......@@ -299,7 +322,11 @@ class CallsService: CallsAdapterDelegate {
func hold(callId: String) -> Completable {
return Completable.create(subscribe: { completable in
let success = self.callsAdapter.holdCall(withId: callId)
guard let call = self.call(callID: callId) else {
completable(.error(CallServiceError.hangUpCallFailed))
return Disposables.create { }
}
let success = self.callsAdapter.holdCall(withId: callId, accountId: call.accountId)
if success {
completable(.completed)
} else {
......@@ -311,7 +338,11 @@ class CallsService: CallsAdapterDelegate {
func unhold(callId: String) -> Completable {
return Completable.create(subscribe: { completable in
let success = self.callsAdapter.unholdCall(withId: callId)
guard let call = self.call(callID: callId) else {
completable(.error(CallServiceError.hangUpCallFailed))
return Disposables.create { }
}
let success = self.callsAdapter.unholdCall(withId: callId, accountId: call.accountId)
if success {
completable(.completed)
} else {
......@@ -355,9 +386,9 @@ class CallsService: CallsAdapterDelegate {
call.callType = .outgoing
return Single<CallModel>.create(subscribe: { [weak self] single in
if let self = self, let callId = self.callsAdapter.placeCall(withAccountId: account.id,
toRingId: ringId,
toParticipantId: ringId,
withMedia: mediaList),
let callDictionary = self.callsAdapter.callDetails(withCallId: callId) {
let callDictionary = self.callsAdapter.callDetails(withCallId: callId, accountId: account.id) {
call.update(withDictionary: callDictionary, withMedia: mediaList)
call.callId = callId
call.participantsCallId.removeAll()
......@@ -375,8 +406,10 @@ class CallsService: CallsAdapterDelegate {
}
func hostMuteAudio(conferenceId: String, mute: Bool, localCallId: String) {
guard let conference = call(callID: conferenceId) else { return }
let success = self.callsAdapter
.muteMedia(conferenceId,
accountId: conference.accountId,
mediaType: String(describing: MediaType.audio),
muted: mute)
guard let call = self.calls.value[localCallId], success else {
......@@ -387,8 +420,11 @@ class CallsService: CallsAdapterDelegate {
}
func hostMuteVideo(conferenceId: String, mute: Bool, localCallId: String) {
guard let conference = self.calls.value[conferenceId] else {
return
}
let success = self.callsAdapter
.muteMedia(conferenceId,
.muteMedia(conferenceId, accountId: conference.accountId,
mediaType: String(describing: MediaType.video),
muted: mute)
guard let call = self.calls.value[localCallId], success else {
......@@ -421,8 +457,8 @@ class CallsService: CallsAdapterDelegate {
media[MediaAttributeKey.label.rawValue] = mediaLabel
mediaList.append(media)
}
self.callsAdapter.requestMediaChange(callId, withMedia: mediaList)
if let callDictionary = self.callsAdapter.callDetails(withCallId: callId) {
self.callsAdapter.requestMediaChange(callId, accountId: call.accountId, withMedia: mediaList)
if let callDictionary = self.callsAdapter.callDetails(withCallId: callId, accountId: call.accountId) {
call.update(withDictionary: callDictionary, withMedia: mediaList)
self.currentCallsEvents.onNext(call)
}
......@@ -431,7 +467,7 @@ class CallsService: CallsAdapterDelegate {
func muteCurrentCallVideoVideo(mute: Bool) {
for call in self.calls.value.values where call.state == .current {
self.callsAdapter
.muteMedia(call.callId,
.muteMedia(call.callId, accountId: call.accountId,
mediaType: String(describing: MediaType.video),
muted: mute)
return
......@@ -446,13 +482,14 @@ class CallsService: CallsAdapterDelegate {
if accountID.isEmpty || callID.isEmpty {
return
}
guard let vCard = self.dbManager.accountVCard(for: accountID) else { return }
guard let vCard = self.dbManager.accountVCard(for: accountID),
let phoneNumber = vCard.phoneNumbers.first?.value else { return }
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
VCardUtils.sendVCard(card: vCard,
callID: callID,
accountID: accountID,
sender: self)
sender: self, from: phoneNumber.stringValue)
}
}
......@@ -460,9 +497,10 @@ class CallsService: CallsAdapterDelegate {
guard let call = self.call(callID: callID) else { return }
let messageDictionary = ["text/plain": message]
self.callsAdapter.sendTextMessage(withCallID: callID,
message: messageDictionary,
accountId: accountId.id,
sMixed: true)
message: messageDictionary,
from: call.paricipantHash(),
isMixed: true)
let accountHelper = AccountModelHelper(withAccount: accountId)
let type = accountHelper.isAccountSip() ? URIType.sip : URIType.ring
let contactUri = JamiURI.init(schema: type, infoHach: call.participantUri, account: accountId)
......@@ -480,18 +518,19 @@ class CallsService: CallsAdapterDelegate {
}
}
func sendChunk(callID: String, message: [String: String], accountId: String) {
func sendChunk(callID: String, message: [String: String], accountId: String, from: String) {
self.callsAdapter.sendTextMessage(withCallID: callID,
message: message,
accountId: accountId,
sMixed: true)
message: message,
from: from,
isMixed: true)
}
// MARK: CallsAdapterDelegate
// swiftlint:disable cyclomatic_complexity
func didChangeCallState(withCallId callId: String, state: String, stateCode: NSInteger) {
func didChangeCallState(withCallId callId: String, state: String, accountId: String, stateCode: NSInteger) {
if let callDictionary = self.callsAdapter.callDetails(withCallId: callId) {
if let callDictionary = self.callsAdapter.callDetails(withCallId: callId, accountId: accountId) {
// Add or update new call
var call = self.calls.value[callId]
call?.state = CallState(rawValue: state) ?? CallState.unknown
......@@ -551,9 +590,9 @@ class CallsService: CallsAdapterDelegate {
if let pendingCall = self.call(callID: confId) {
DispatchQueue.main.asyncAfter(deadline: .now() + seconds) {
if pendingCall.participantsCallId.count == 1 {
self.callsAdapter.joinCall(confId, second: callId)
self.callsAdapter.joinCall(confId, second: callId, accountId: pendingCall.accountId, account2Id: accountId)
} else {
self.callsAdapter.joinConference(confId, call: callId)
self.callsAdapter.joinConference(confId, call: callId, accountId: pendingCall.accountId, account2Id: accountId)
}
}
}
......@@ -567,7 +606,7 @@ class CallsService: CallsAdapterDelegate {
func didChangeMediaNegotiationStatus(withCallId callId: String, event: String, withMedia: [[String: String]]) {
guard let call = self.calls.value[callId],
let callDictionary = self.callsAdapter.callDetails(withCallId: callId) else { return }
let callDictionary = self.callsAdapter.callDetails(withCallId: callId, accountId: call.accountId) else { return }
call.update(withDictionary: callDictionary, withMedia: withMedia)
self.currentCallsEvents.onNext(call)
}
......@@ -595,7 +634,7 @@ class CallsService: CallsAdapterDelegate {
answerMedias.append(answerMedia)
}
}
self.callsAdapter.answerMediaChangeResquest(callId, withMedia: answerMedias)
self.callsAdapter.answerMediaChangeResquest(callId, accountId: accountId, withMedia: answerMedias)
}
func shouldCallBeAddedToConference(callId: String) -> String? {
......@@ -634,7 +673,7 @@ class CallsService: CallsAdapterDelegate {
// swiftlint:enable cyclomatic_complexity
func receivingCall(withAccountId accountId: String, callId: String, fromURI uri: String, withMedia mediaList: [[String: String]]) {
if let callDictionary = self.callsAdapter.callDetails(withCallId: callId) {
if let callDictionary = self.callsAdapter.callDetails(withCallId: callId, accountId: accountId) {
if !isCurrentCall() {
var call = self.calls.value[callId]
......@@ -692,9 +731,15 @@ class CallsService: CallsAdapterDelegate {
self.currentCallsEvents.onNext(call)
}
func conferenceCreated(conference conferenceID: String) {
func conferenceCreated(conference conferenceID: String, accountId: String) {
let conferenceCalls = Set(self.callsAdapter
.getConferenceCalls(conferenceID))
.getConferenceCalls(conferenceID, accountId: accountId))
if conferenceCalls.isEmpty {
// no calls attached to a conference. Wait until conference changed to check the calls.
createdConferences.insert(conferenceID)
return
}
createdConferences.remove(conferenceID)
self.pendingConferences.forEach { pending in
if !conferenceCalls.contains(pending.key) ||
conferenceCalls.isDisjoint(with: pending.value) {
......@@ -714,7 +759,7 @@ class CallsService: CallsAdapterDelegate {
values.forEach { (call) in
self.call(callID: call)?.participantsCallId = conferenceCalls
}
guard var callDetails = self.callsAdapter.getConferenceDetails(conferenceID) else { return }
guard var callDetails = self.callsAdapter.getConferenceDetails(conferenceID, accountId: accountId) else { return }
callDetails[CallDetailKey.accountIdKey.rawValue] = self.call(callID: callId)?.accountId
callDetails[CallDetailKey.audioOnlyKey.rawValue] = self.call(callID: callId)?.isAudioOnly.toString()
let mediaList = [[String: String]]()
......@@ -727,10 +772,15 @@ class CallsService: CallsAdapterDelegate {
}
}
func conferenceChanged(conference conferenceID: String, state: String) {
func conferenceChanged(conference conferenceID: String, accountId: String, state: String) {
if createdConferences.contains(conferenceID) {
// a conference was created but calls was not attached to a conference. In this case a conference should be added first.
self.conferenceCreated(conference: conferenceID, accountId: accountId)
return
}
guard let conference = self.call(callID: conferenceID) else { return }
let conferenceCalls = Set(self.callsAdapter
.getConferenceCalls(conferenceID))
.getConferenceCalls(conferenceID, accountId: conference.accountId))
conference.participantsCallId = conferenceCalls
conferenceCalls.forEach { (callId) in
guard let call = self.call(callID: callId) else { return }
......@@ -759,7 +809,7 @@ class CallsService: CallsAdapterDelegate {
guard let conferenceID = conferences.first, let conference = call(callID: conferenceID) else { return }
let conferenceCalls = Set(self.callsAdapter
.getConferenceCalls(conferenceID))
.getConferenceCalls(conferenceID, accountId: conference.accountId))
conference.participantsCallId = conferenceCalls
conferenceCalls.forEach { (callID) in
self.call(callID: callID)?.participantsCallId = conferenceCalls
......@@ -767,14 +817,17 @@ class CallsService: CallsAdapterDelegate {
}
func muteParticipant(confId: String, participantId: String, active: Bool) {
self.callsAdapter.muteConferenceParticipant(participantId, forConference: confId, active: active)
guard let conference = call(callID: confId) else { return }
self.callsAdapter.muteConferenceParticipant(participantId, forConference: confId, accountId: conference.accountId, active: active)
}
func setModeratorParticipant(confId: String, participantId: String, active: Bool) {
self.callsAdapter.setConferenceModerator(participantId, forConference: confId, active: active)
guard let conference = call(callID: confId) else { return }
self.callsAdapter.setConferenceModerator(participantId, forConference: confId, accountId: conference.accountId, active: active)
}
func hangupParticipant(confId: String, participantId: String) {
self.callsAdapter.hangupConferenceParticipant(participantId, forConference: confId)
guard let conference = call(callID: confId) else { return }
self.callsAdapter.hangupConferenceParticipant(participantId, forConference: confId, accountId: conference.accountId)
}
}
......@@ -36,7 +36,6 @@ class ConversationsManager {
private let callService: CallsService
private let locationSharingService: LocationSharingService
private let callsProvider: CallsProviderDelegate
private let videoService: VideoService
private let requestService: RequestsService
private let disposeBag = DisposeBag()
......@@ -54,7 +53,6 @@ class ConversationsManager {
locationSharingService: LocationSharingService,
contactsService: ContactsService,
callsProvider: CallsProviderDelegate,
videoService: VideoService,
requestsService: RequestsService) {
self.conversationService = conversationService
self.accountsService = accountsService
......@@ -64,7 +62,6 @@ class ConversationsManager {
self.locationSharingService = locationSharingService
self.contactsService = contactsService
self.callsProvider = callsProvider
self.videoService = videoService
self.requestService = requestsService
ConversationsAdapter.messagesDelegate = self
......@@ -161,26 +158,6 @@ class ConversationsManager {
}
private func subscribeCallsEvents() {
self.callService.sharedResponseStream
.filter { event in
event.eventType == .callEnded
}
.subscribe { [weak self] event in
guard let self = self else { return }
guard let accountID: String = event.getEventInput(.accountId) else {
return
}
guard let jamiId: String = event.getEventInput(.uri) else {
return
}
guard let call = self.callService.call(participantHash: jamiId.filterOutHost(), accountID: accountID) else { return }
self.callsProvider.stopCall(callUUID: call.callUUID)
self.videoService.stopCapture()
self.videoService.setCameraOrientation(orientation: UIDevice.current.orientation)
} onError: { _ in
}
.disposed(by: disposeBag)
self.callService.newMessage
.filter({ (event) in
return event.eventType == ServiceEventType.newIncomingMessage
......
/*
* Copyright (C) 2021 Savoir-faire Linux Inc.
*
* Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
@objc protocol DecodingAdapterDelegate {
func decodingStarted(withRendererId rendererId: String,
withWidth width: Int,
withHeight height: Int)
func decodingStopped(withRendererId rendererId: String)
}
......@@ -19,15 +19,9 @@
*/
@objc protocol VideoAdapterDelegate {
func decodingStarted(withRendererId rendererId: String,
withWidth width: Int,
withHeight height: Int,
withCodec codecId: String)
func decodingStopped(withRendererId rendererId: String)
func startCapture(withDevice device: String)
func stopCapture()
func writeFrame(withImage image: UIImage?, forCallId: String)
func setDecodingAccelerated(withState state: Bool)
func switchInput(toDevice device: String, callID: String?)
func fileOpened(for playerId: String, fileInfo: [String: String])
}
/*
* Copyright (C) 2021 Savoir-faire Linux Inc.
*
* Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import RxSwift
import SwiftyBeaver
class VideoManager {
let log = SwiftyBeaver.self
private let callService: CallsService
private let callsProvider: CallsProviderDelegate
private let videoService: VideoService
private let disposeBag = DisposeBag()
init(with callService: CallsService,
callsProvider: CallsProviderDelegate,
videoService: VideoService) {
self.callService = callService
self.callsProvider = callsProvider
self.videoService = videoService
self.subscribeCallsEvents()
VideoAdapter.decodingDelegate = self
}
private func subscribeCallsEvents() {
self.callService.sharedResponseStream
.filter { event in
event.eventType == .callEnded
}
.subscribe { [weak self] event in
guard let self = self else { return }
guard let accountID: String = event.getEventInput(.accountId) else {
return
}
guard let jamiId: String = event.getEventInput(.uri) else {
return
}
guard let call = self.callService.call(participantHash: jamiId.filterOutHost(), accountID: accountID) else { return }
self.callsProvider.stopCall(callUUID: call.callUUID)
self.videoService.stopCapture()
self.videoService.setCameraOrientation(orientation: UIDevice.current.orientation)
} onError: {_ in
}
.disposed(by: disposeBag)
}
}
extension VideoManager: DecodingAdapterDelegate {
func decodingStarted(withRendererId rendererId: String,
withWidth width: Int,
withHeight height: Int) {
var accountId = ""
var codecId: String?
if let call = self.callService.call(callID: rendererId),
let codec = self.callService.getVideoCodec(call: call) {
codecId = codec
accountId = call.accountId
}
self.videoService.decodingStarted(withRendererId: rendererId, withWidth: width, withHeight: height, withCodec: codecId, withaAccountId: accountId)
}
func decodingStopped(withRendererId rendererId: String) {
self.videoService.decodingStopped(withRendererId: rendererId)
}
}
......@@ -286,18 +286,20 @@ class VideoService: FrameExtractorDelegate {
private var hardwareAccelerationEnabledByUser = true
var angle: Int = 0
var switchInputRequested: Bool = false
var currentDeviceId = ""
private let disposeBag = DisposeBag()
init(withVideoAdapter videoAdapter: VideoAdapter) {
self.videoAdapter = videoAdapter
currentOrientation = camera.getOrientation
VideoAdapter.delegate = self
VideoAdapter.videoDelegate = self
self.hardwareAccelerationEnabledByUser = videoAdapter.getEncodingAccelerated()
camera.delegate = self
NotificationCenter.default.addObserver(self, selector: #selector(self.restoreDefaultDevice),
name: NSNotification.Name(rawValue: NotificationName.restoreDefaultVideoDevice.rawValue),
object: nil)
self.currentDeviceId = self.videoAdapter.getDefaultDevice()
}
@objc
......@@ -388,12 +390,14 @@ class VideoService: FrameExtractorDelegate {
}
extension VideoService: VideoAdapterDelegate {
func switchInput(toDevice device: String, callID: String?) {
func switchInput(toDevice device: String, callID: String?, accountId: String) {
if let call = callID {
videoAdapter.switchInput(device, forCall: call)
videoAdapter.switchInput(device, accountId: accountId, forCall: call)
return
}
videoAdapter.switchInput(device)
let current = self.videoAdapter.getDefaultDevice()
self.videoAdapter.closeVideoInput(current)
self.videoAdapter.openVideoInput(device)
}
func setDecodingAccelerated(withState state: Bool) {
......@@ -423,19 +427,20 @@ extension VideoService: VideoAdapterDelegate {
}
}
func decodingStarted(withRendererId rendererId: String, withWidth width: Int, withHeight height: Int, withCodec codecId: String) {
if !codecId.isEmpty {
func decodingStarted(withRendererId rendererId: String, withWidth width: Int, withHeight height: Int, withCodec codec: String?, withaAccountId accountId: String) {
if let codecId = codec, !codecId.isEmpty {
// we do not support hardware acceleration with VP8 codec. In this case software
// encoding will be used. Downgrate resolution if needed. After call finished
// resolution will be restored in restoreDefaultDevice()
let codec = VideoCodecs(rawValue: codecId) ?? VideoCodecs.unknown
if !supportHardware(codec: codec) && self.camera.quality == AVCaptureSession.Preset.hd1280x720 {
self.videoAdapter.setDefaultDevice(camera.namePortrait)
self.videoAdapter.switchInput("camera://" + camera.namePortrait, forCall: rendererId)
self.videoAdapter.switchInput("camera://" + camera.namePortrait, accountId: accountId, forCall: rendererId)
}
}
self.log.debug("Decoding started...")
videoAdapter.registerSinkTarget(withSinkId: rendererId, withWidth: width, withHeight: height)
self.currentDeviceId = self.videoAdapter.getDefaultDevice()
}
func supportHardware(codec: VideoCodecs) -> Bool {
......@@ -464,15 +469,15 @@ extension VideoService: VideoAdapterDelegate {
self.camera.startCapturing()
}
func startCamera() {
self.videoAdapter.startCamera()
func startMediumCamera() {
self.videoAdapter.openVideoInput("camera://" + self.camera.namePortrait)
}
func videRecordingFinished() {
if self.cameraPosition == .back {
self.switchCamera()
}
self.videoAdapter.stopCamera()
self.videoAdapter.closeVideoInput("camera://" + self.camera.namePortrait)
self.stopAudioDevice()
}
......@@ -513,7 +518,7 @@ extension VideoService: VideoAdapterDelegate {
orientation: self.getImageOrienation()))
}
videoAdapter.writeOutgoingFrame(with: imageBuffer,
angle: Int32(self.angle))
angle: Int32(self.angle), videoInputId: "camera://" + self.currentDeviceId)
}
func updateDevicePosition(position: AVCaptureDevice.Position) {
......@@ -526,7 +531,9 @@ extension VideoService: VideoAdapterDelegate {
}
func startLocalRecorder(audioOnly: Bool, path: String) -> String? {
return self.videoAdapter.startLocalRecording(path, audioOnly: audioOnly)
let device = audioOnly ? "" : "camera://" + camera.namePortrait
self.currentDeviceId = camera.namePortrait
return self.videoAdapter.startLocalRecording(device, path: path)
}
func stopLocalRecorder(path: String) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment