Commit ddfe6e79 authored by Kateryna Kostiuk's avatar Kateryna Kostiuk Committed by Andreas Traczyk

call: add call service

This patch introduce call service and adapter to manage
call state.

Author: Silbino Gonçalves Matado <silbino.gmatado@savoirfairelinux.com>

Change-Id: I8f69aad4f9c91c2001ef27cb78df631fd31bf291
Reviewed-by: Andreas Traczyk's avatarAndreas Traczyk <andreas.traczyk@savoirfairelinux.com>
parent 5fbe35e0
......@@ -106,6 +106,10 @@
0E403F831F7D79B000C80BC2 /* MessageCellGenerated.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0E403F821F7D79B000C80BC2 /* MessageCellGenerated.xib */; };
0E48F9D31FDF150700D6CC08 /* ContactRequestManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E48F9D21FDF150700D6CC08 /* ContactRequestManager.swift */; };
0E4909611FE97A94005CAA50 /* ActiveLabel.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E4909601FE97A94005CAA50 /* ActiveLabel.framework */; };
0E49096A1FEAB156005CAA50 /* CallsAdapter.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0E4909691FEAB156005CAA50 /* CallsAdapter.mm */; };
0E49096C1FEAB225005CAA50 /* CallsAdapterDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E49096B1FEAB225005CAA50 /* CallsAdapterDelegate.swift */; };
0E49096E1FEAC0DE005CAA50 /* CallsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E49096D1FEAC0DE005CAA50 /* CallsService.swift */; };
0E4909701FEAC1C6005CAA50 /* CallModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E49096F1FEAC1C6005CAA50 /* CallModel.swift */; };
0E6949791FA7E71C0029B60A /* BaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E6949781FA7E71C0029B60A /* BaseViewController.swift */; };
0E983E6E1FC77C3E0082103E /* ConversationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E983E6D1FC77C3E0082103E /* ConversationModel.swift */; };
0E9D84491FA7DA6A00C561EB /* ChatTabBarItemViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E9D84481FA7DA6A00C561EB /* ChatTabBarItemViewModel.swift */; };
......@@ -356,6 +360,11 @@
0E403F821F7D79B000C80BC2 /* MessageCellGenerated.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MessageCellGenerated.xib; sourceTree = "<group>"; };
0E48F9D21FDF150700D6CC08 /* ContactRequestManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactRequestManager.swift; sourceTree = "<group>"; };
0E4909601FE97A94005CAA50 /* ActiveLabel.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ActiveLabel.framework; path = Carthage/Build/iOS/ActiveLabel.framework; sourceTree = "<group>"; };
0E4909681FEAB156005CAA50 /* CallsAdapter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CallsAdapter.h; sourceTree = "<group>"; };
0E4909691FEAB156005CAA50 /* CallsAdapter.mm */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; path = CallsAdapter.mm; sourceTree = "<group>"; };
0E49096B1FEAB225005CAA50 /* CallsAdapterDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallsAdapterDelegate.swift; sourceTree = "<group>"; };
0E49096D1FEAC0DE005CAA50 /* CallsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallsService.swift; sourceTree = "<group>"; };
0E49096F1FEAC1C6005CAA50 /* CallModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallModel.swift; sourceTree = "<group>"; };
0E6949781FA7E71C0029B60A /* BaseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseViewController.swift; sourceTree = "<group>"; };
0E983E6D1FC77C3E0082103E /* ConversationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationModel.swift; sourceTree = "<group>"; };
0E9D84481FA7DA6A00C561EB /* ChatTabBarItemViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatTabBarItemViewModel.swift; sourceTree = "<group>"; };
......@@ -704,6 +713,8 @@
62DFAB2D1F9FF0D0002D6F9C /* NetworkService.swift */,
0EF78DE21FD0AE3000FC6966 /* ConversationsManager.swift */,
0E48F9D21FDF150700D6CC08 /* ContactRequestManager.swift */,
0E49096B1FEAB225005CAA50 /* CallsAdapterDelegate.swift */,
0E49096D1FEAC0DE005CAA50 /* CallsService.swift */,
);
path = Services;
sourceTree = "<group>";
......@@ -737,6 +748,8 @@
563AEC731EA6627F003A5641 /* NameRegistration */,
62A88D351F6C2E5F00F8AB18 /* PresenceAdapter.h */,
62A88D381F6C323500F8AB18 /* PresenceAdapter.mm */,
0E4909681FEAB156005CAA50 /* CallsAdapter.h */,
0E4909691FEAB156005CAA50 /* CallsAdapter.mm */,
);
path = Bridging;
sourceTree = "<group>";
......@@ -1137,6 +1150,7 @@
1A2D18BD1F29180700B2C785 /* ContactModel.swift */,
1A2D18BF1F29180700B2C785 /* DeviceModel.swift */,
0E983E6D1FC77C3E0082103E /* ConversationModel.swift */,
0E49096F1FEAC1C6005CAA50 /* CallModel.swift */,
);
path = Models;
sourceTree = "<group>";
......@@ -1581,6 +1595,7 @@
1A2D18C51F29180700B2C785 /* ContactModel.swift in Sources */,
1A2D18F71F292D7200B2C785 /* MessageCellSent.swift in Sources */,
04399AAC1D1C304300E99CD9 /* AccountAdapter.mm in Sources */,
0E49096C1FEAB225005CAA50 /* CallsAdapterDelegate.swift in Sources */,
1AABA7461F0FE9C000739605 /* UIColor+Ring.swift in Sources */,
1A5DC0201F355DCF0075E8EF /* ContactsService.swift in Sources */,
1A2D18C71F29180700B2C785 /* DeviceModel.swift in Sources */,
......@@ -1591,8 +1606,10 @@
02B22E091DF7585F000358C9 /* DaemonService.swift in Sources */,
5CE66F761FBF769B00EE9291 /* InitialLoadingViewController.swift in Sources */,
56BBC99F1ED714CB00CDAF8B /* MessagesAdapter.mm in Sources */,
0E49096A1FEAB156005CAA50 /* CallsAdapter.mm in Sources */,
1A2D18A61F27F7A400B2C785 /* UIViewController+Rx.swift in Sources */,
1A5DC0241F3564360075E8EF /* ContactRequestModel.swift in Sources */,
0E4909701FEAC1C6005CAA50 /* CallModel.swift in Sources */,
1A5DC03F1F35678D0075E8EF /* ContactRequestsViewController.swift in Sources */,
1A20418B1F1EA58A00C08435 /* ViewModelBased.swift in Sources */,
1A5DC01E1F355DA70075E8EF /* ContactsAdapterDelegate.swift in Sources */,
......@@ -1673,6 +1690,7 @@
04399AAD1D1C304300E99CD9 /* DRingAdapter.mm in Sources */,
1A2D18D11F29182500B2C785 /* ConversationViewController.swift in Sources */,
0EE1B5501F75AD4700BA98EE /* VCardUtils.swift in Sources */,
0E49096E1FEAC0DE005CAA50 /* CallsService.swift in Sources */,
0273C2FF1E0C438F00CF00BA /* AccountAdapterDelegate.swift in Sources */,
1A2D19011F29353A00B2C785 /* MeDetailViewModel.swift in Sources */,
1A2D18A41F27EF5200B2C785 /* AppCoordinator.swift in Sources */,
......
/*
* Copyright (C) 2017 Savoir-faire Linux Inc.
*
* Author: Silbino Gonçalves Matado <silbino.gmatado@savoirfairelinux.com>
* 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 <Foundation/Foundation.h>
@protocol CallsAdapterDelegate;
@interface CallsAdapter : NSObject
@property (class, nonatomic, weak) id <CallsAdapterDelegate> delegate;
- (BOOL)acceptCallWithId:(NSString*)callId;
- (BOOL)refuseCallWithId:(NSString*)callId;
- (BOOL)hangUpCallWithId:(NSString*)callId;
- (BOOL)holdCallWithId:(NSString*)callId;
- (BOOL)unholdCallWithId:(NSString*)callId;
- (NSString*)placeCallWithAccountId:(NSString*)accountId toRingId:(NSString*)ringId;
- (NSDictionary<NSString*,NSString*>*)callDetailsWithCallId:(NSString*)callId;
- (NSArray<NSString*>*)calls;
@end
/*
* Copyright (C) 2017 Savoir-faire Linux Inc.
*
* Author: Silbino Gonçalves Matado <silbino.gmatado@savoirfairelinux.com>
* 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 "CallsAdapter.h"
#import "Utils.h"
#import "dring/callmanager_interface.h"
#import "Ring-Swift.h"
using namespace DRing;
@implementation CallsAdapter
/// Static delegate that will receive the propagated daemon events
static id <CallsAdapterDelegate> _delegate;
#pragma mark Init
- (id)init {
if (self = [super init]) {
[self registerCallHandler];
}
return self;
}
#pragma mark -
#pragma mark Callbacks registration
- (void)registerCallHandler {
std::map<std::string, std::shared_ptr<CallbackWrapperBase>> callHandlers;
//State changed signal
callHandlers.insert(exportable_callback<CallSignal::StateChange>([&](const std::string& callId,
const std::string& state,
int errorCode) {
if (CallsAdapter.delegate) {
NSString* callIdString = [NSString stringWithUTF8String:callId.c_str()];
NSString* stateString = [NSString stringWithUTF8String:state.c_str()];
[CallsAdapter.delegate didChangeCallStateWithCallId:callIdString
state:stateString
stateCode:errorCode];
}
}));
//Incoming message signal
callHandlers.insert(exportable_callback<CallSignal::IncomingMessage>([&](const std::string& callId,
const std::string& fromURI,
const std::map<std::string,
std::string>& message) {
if (CallsAdapter.delegate) {
NSString* callIdString = [NSString stringWithUTF8String:callId.c_str()];
NSString* fromURIString = [NSString stringWithUTF8String:fromURI.c_str()];
NSDictionary* messageDict = [Utils mapToDictionnary:message];
[CallsAdapter.delegate didReceiveMessageWithCallId:callIdString
fromURI:fromURIString
message:messageDict];
}
}));
//Incoming call signal
callHandlers.insert(exportable_callback<CallSignal::IncomingCall>([&](const std::string& accountId,
const std::string& callId,
const std::string& fromURI) {
if (CallsAdapter.delegate) {
NSString* accountIdString = [NSString stringWithUTF8String:accountId.c_str()];
NSString* callIdString = [NSString stringWithUTF8String:callId.c_str()];
NSString* fromURIString = [NSString stringWithUTF8String:fromURI.c_str()];
[CallsAdapter.delegate receivingCallWithAccountId:accountIdString
callId:callIdString
fromURI:fromURIString];
}
}));
//New outgoing call signal
callHandlers.insert(exportable_callback<CallSignal::NewCallCreated>([&](const std::string& accountId,
const std::string& callId,
const std::string& toURI) {
if (CallsAdapter.delegate) {
NSString* accountIdString = [NSString stringWithUTF8String:accountId.c_str()];
NSString* callIdString = [NSString stringWithUTF8String:callId.c_str()];
NSString* toURIString = [NSString stringWithUTF8String:toURI.c_str()];
[CallsAdapter.delegate newCallStartedWithAccountId: accountIdString
callId: callIdString
toURI: toURIString];
}
}));
//Peer place call on hold signal
callHandlers.insert(exportable_callback<CallSignal::PeerHold>([&](const std::string& callId,
bool holding) {
if (CallsAdapter.delegate) {
NSString* callIdString = [NSString stringWithUTF8String: callId.c_str()];
[CallsAdapter.delegate callPlacedOnHoldWithCallId:callIdString holding:holding];
}
}));
callHandlers.insert(exportable_callback<CallSignal::VideoMuted>([&](const std::string& callId,
bool muted) {
if (CallsAdapter.delegate) {
NSString* callIdString = [NSString stringWithUTF8String:callId.c_str()];
[CallsAdapter.delegate muteVideoWithCall: callIdString mute: muted];
}
}));
callHandlers.insert(exportable_callback<CallSignal::AudioMuted>([&](const std::string& callId,
bool muted) {
if (CallsAdapter.delegate) {
NSString* callIdString = [NSString stringWithUTF8String:callId.c_str()];
[CallsAdapter.delegate muteAudioWithCall: callIdString mute: muted];
}
}));
registerCallHandlers(callHandlers);
}
#pragma mark -
- (BOOL)acceptCallWithId:(NSString*)callId {
return accept(std::string([callId UTF8String]));
}
- (BOOL)refuseCallWithId:(NSString*)callId {
return refuse(std::string([callId UTF8String]));
}
- (BOOL)hangUpCallWithId:(NSString*)callId {
return hangUp(std::string([callId UTF8String]));
}
- (BOOL)holdCallWithId:(NSString*)callId {
return hold(std::string([callId UTF8String]));
}
- (BOOL)unholdCallWithId:(NSString*)callId {
return unhold(std::string([callId UTF8String]));
}
- (NSString*)placeCallWithAccountId:(NSString*)accountId toRingId:(NSString*)ringId {
std::string callId = placeCall(std::string([accountId UTF8String]), std::string([ringId UTF8String]));
return [NSString stringWithUTF8String:callId.c_str()];
}
- (NSDictionary<NSString*,NSString*>*)callDetailsWithCallId:(NSString*)callId {
std::map<std::string, std::string> callDetails = getCallDetails(std::string([callId UTF8String]));
return [Utils mapToDictionnary:callDetails];
}
- (NSArray<NSString*>*)calls {
std::vector<std::string> calls = getCallList();
return [Utils vectorToArray:calls];
}
#pragma mark AccountAdapterDelegate
+ (id <CallsAdapterDelegate>)delegate {
return _delegate;
}
+ (void) setDelegate:(id<CallsAdapterDelegate>)delegate {
_delegate = delegate;
}
#pragma mark -
@end
......@@ -35,3 +35,4 @@
#import "PresenceAdapter.h"
#import <CommonCrypto/CommonCrypto.h>
#import <Contacts/Contacts.h>
#import "CallsAdapter.h"
/*
* Copyright (C) 2017 Savoir-faire Linux Inc.
*
* Author: Silbino Gonçalves Matado <silbino.gmatado@savoirfairelinux.com>
* 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.
*/
enum CallState: String {
case incoming = "INCOMING"
case connecting = "CONNECTING"
case ringing = "RINGING"
case current = "CURRENT"
case hungup = "HUNGUP"
case busy = "BUSY"
case failure = "FAILURE"
case hold = "HOLD"
case unhold = "UNHOLD"
case inactive = "INACTIVE"
case over = "OVER"
case unknown = "UNKNOWN"
}
enum CallType: Int {
case incoming = 0
case outgoing
case missed
}
enum CallDetailKey: String {
case callTypeKey = "CALL_TYPE"
case peerNumberKey = "PEER_NUMBER"
case registeredNameKey = "REGISTERED_NAME"
case displayNameKey = "DISPLAY_NAME"
case timeStampStartKey = "TIMESTAMP_START"
case accountIdKey = "ACCOUNTID"
case peerHoldingKey = "PEER_HOLDING"
case audioMutedKey = "AUDIO_MUTED"
case videoMutedKey = "VIDEO_MUTED"
case videoSourceKey = "VIDEO_SOURCE"
}
class CallModel {
var callId: String = ""
var dateReceived: Date = Date()
var participantRingId: String = ""
var displayName: String = ""
var registeredName: String = ""
var accountId: String = ""
var audioMuted: Bool = false
var videoMuted: Bool = false
var stateValue = CallState.unknown.rawValue
var callTypeValue = CallType.missed.rawValue
var state: CallState {
get {
if let state = CallState(rawValue: stateValue) {
return state
}
return CallState.unknown
}
set {
stateValue = newValue.rawValue
}
}
var callType: CallType {
get {
if let type = CallType(rawValue: callTypeValue) {
return type
}
return CallType.missed
}
set {
callTypeValue = newValue.rawValue
}
}
init(withCallId callId: String, callDetails dictionary: [String: String]) {
self.callId = callId
if let fromRingId = dictionary[CallDetailKey.peerNumberKey.rawValue]?.components(separatedBy: "@").first {
self.participantRingId = fromRingId
}
if let accountId = dictionary[CallDetailKey.accountIdKey.rawValue] {
self.accountId = accountId
}
if let callType = dictionary[CallDetailKey.callTypeKey.rawValue] {
if let callTypeInt = Int(callType) {
self.callType = CallType(rawValue: callTypeInt)!
} else {
self.callType = .missed
}
}
self.update(withDictionary: dictionary)
}
func update(withDictionary dictionary: [String: String]) {
self.dateReceived = Date()
if let displayName = dictionary[CallDetailKey.displayNameKey.rawValue] {
self.displayName = displayName
}
if let registeredName = dictionary[CallDetailKey.registeredNameKey.rawValue] {
self.registeredName = registeredName
}
if let videoMuted = dictionary[CallDetailKey.videoMutedKey.rawValue]?.toBool() {
self.videoMuted = videoMuted
}
if let audioMuted = dictionary[CallDetailKey.audioMutedKey.rawValue]?.toBool() {
self.audioMuted = audioMuted
}
if let participantRingId = dictionary[CallDetailKey.peerNumberKey.rawValue]?.components(separatedBy: "@").first {
self.participantRingId = participantRingId
}
if let accountId = dictionary[CallDetailKey.accountIdKey.rawValue] {
self.accountId = accountId
}
}
}
/*
* Copyright (C) 2017 Savoir-faire Linux Inc.
*
* Author: Silbino Gonçalves Matado <silbino.gmatado@savoirfairelinux.com>
* 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 CallsAdapterDelegate {
func didChangeCallState(withCallId callId: String, state: String, stateCode: NSInteger)
func didReceiveMessage(withCallId callId: String, fromURI uri: String, message: [String: String])
func receivingCall(withAccountId accountId: String, callId: String, fromURI uri: String)
func newCallStarted(withAccountId accountId: String, callId: String, toURI uri: String)
func callPlacedOnHold(withCallId callId: String, holding: Bool)
func muteAudio(call callId: String, mute: Bool)
func muteVideo(call callId: String, mute: Bool)
}
/*
* Copyright (C) 2017 Savoir-faire Linux Inc.
*
* Author: Silbino Gonçalves Matado <silbino.gmatado@savoirfairelinux.com>
* 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
import Contacts
enum CallServiceError: Error {
case acceptCallFailed
case refuseCallFailed
case hangUpCallFailed
case holdCallFailed
case unholdCallFailed
case placeCallFailed
}
class CallsService: CallsAdapterDelegate {
fileprivate let disposeBag = DisposeBag()
fileprivate let callsAdapter: CallsAdapter
fileprivate let log = SwiftyBeaver.self
fileprivate var calls = [String: CallModel]()
fileprivate let ringVCardMIMEType = "x-ring/ring.profile.vcard"
let currentCall = ReplaySubject<CallModel>.create(bufferSize: 1)
let newcall = Variable<CallModel>(CallModel(withCallId: "", callDetails: [:]))
init(withCallsAdapter callsAdapter: CallsAdapter) {
self.callsAdapter = callsAdapter
CallsAdapter.delegate = self
}
func accept(callId: String) -> Completable {
return Completable.create(subscribe: { completable in
let success = self.callsAdapter.acceptCall(withId: callId)
if success {
completable(.completed)
} else {
completable(.error(CallServiceError.acceptCallFailed))
}
return Disposables.create { }
})
}
func refuse(callId: String) -> Completable {
return Completable.create(subscribe: { completable in
let success = self.callsAdapter.refuseCall(withId: callId)
if success {
completable(.completed)
} else {
completable(.error(CallServiceError.refuseCallFailed))
}
return Disposables.create { }
})
}
func hangUp(callId: String) -> Completable {
return Completable.create(subscribe: { completable in
let success = self.callsAdapter.hangUpCall(withId: callId)
if success {
completable(.completed)
} else {
completable(.error(CallServiceError.hangUpCallFailed))
}
return Disposables.create { }
})
}
func hold(callId: String) -> Completable {
return Completable.create(subscribe: { completable in
let success = self.callsAdapter.holdCall(withId: callId)
if success {
completable(.completed)
} else {
completable(.error(CallServiceError.holdCallFailed))
}
return Disposables.create { }
})
}
func unhold(callId: String) -> Completable {
return Completable.create(subscribe: { completable in
let success = self.callsAdapter.unholdCall(withId: callId)
if success {
completable(.completed)
} else {
completable(.error(CallServiceError.unholdCallFailed))
}
return Disposables.create { }
})
}
func placeCall(withAccount account: AccountModel, toRingId ringId: String) -> Single<CallModel> {
//Create and emit the call
let call = CallModel(withCallId: ringId, callDetails: [String: String]())
call.state = .connecting
return Single<CallModel>.create(subscribe: { single in
if let callId = self.callsAdapter.placeCall(withAccountId: account.id,
toRingId: "ring:\(ringId)"),
let callDictionary = self.callsAdapter.callDetails(withCallId: callId) {
call.update(withDictionary: callDictionary)
call.callId = callId
self.currentCall.onNext(call)
self.calls[callId] = call
single(.success(call))
} else {
single(.error(CallServiceError.placeCallFailed))
}
return Disposables.create { }
})
}
// MARK: CallsAdapterDelegate
func didChangeCallState(withCallId callId: String, state: String, stateCode: NSInteger) {
if let callDictionary = self.callsAdapter.callDetails(withCallId: callId) {
//Add or update new call
var call = self.calls[callId]
if call == nil {
call = CallModel(withCallId: callId, callDetails: callDictionary)
} else {
call?.update(withDictionary: callDictionary)
}
//Update the call
call?.state = CallState(rawValue: state)!
//Emit the call to the observers
self.currentCall.onNext(call!)
//Remove from the cache if the call is over
if call?.state == .over {
// TODO save history
self.calls[callId] = nil
}
}
}
func didReceiveMessage(withCallId callId: String, fromURI uri: String, message: [String: String]) {
}
func receivingCall(withAccountId accountId: String, callId: String, fromURI uri: String) {
if let callDictionary = self.callsAdapter.callDetails(withCallId: callId) {
//Add or update new call
var call = self.calls[callId]
if call == nil {
call = CallModel(withCallId: callId, callDetails: callDictionary)
} else {
call?.update(withDictionary: callDictionary)
}
//Emit the call to the observers
self.newcall.value = call!
}
}
func newCallStarted(withAccountId accountId: String, callId: String, toURI uri: String) {
}
func callPlacedOnHold(withCallId callId: String, holding: Bool) {
}
func muteAudio(call callId: String, mute: Bool) {
}
func muteVideo(call callId: String, mute: Bool) {
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment