VoiceMac/Classes/VoiceBase/SIP/MGMSIPCall.m

577 lines
18 KiB
Mathematica
Raw Permalink Normal View History

2010-09-20 19:44:17 -05:00
//
// MGMSIPCall.m
// VoiceBase
//
// Created by Mr. Gecko on 9/10/10.
// Copyright (c) 2011 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/
//
// Permission to use, copy, modify, and/or distribute this software for any purpose
// with or without fee is hereby granted, provided that the above copyright notice
// and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
// OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
// DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
// ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2010-09-20 19:44:17 -05:00
//
#if MGMSIPENABLED
#import "MGMSIPCall.h"
#import "MGMSIPAccount.h"
#import "MGMSIPURL.h"
#import "MGMSIP.h"
#import "MGMAddons.h"
#import <AudioToolbox/AudioToolbox.h>
2010-09-20 19:44:17 -05:00
@implementation MGMSIPCall
- (id)initWithIdentifier:(pjsua_call_id)theIdentifier account:(MGMSIPAccount *)theAccount {
if ((self = [super init])) {
2010-09-20 19:44:17 -05:00
account = theAccount;
identifier = theIdentifier;
2010-09-21 20:47:54 -05:00
pj_thread_desc PJThreadDesc;
[[MGMSIP sharedSIP] registerThread:&PJThreadDesc];
2010-09-20 19:44:17 -05:00
pjsua_call_info callInfo;
pj_status_t status = pjsua_call_get_info(identifier, &callInfo);
if (status!=PJ_SUCCESS) {
[self release];
self = nil;
} else {
remoteURL = [[MGMSIPURL URLWithSIPID:[NSString stringWithPJString:callInfo.remote_info]] retain];
localURL = [[MGMSIPURL URLWithSIPID:[NSString stringWithPJString:callInfo.local_info]] retain];
state = callInfo.state;
stateText = [[NSString stringWithPJString:callInfo.state_text] copy];
lastStatus = callInfo.last_status;
lastStatusText = [[NSString stringWithPJString:callInfo.last_status_text] copy];
onHold = NO;
holdMusicPlayer = PJSUA_INVALID_ID;
recorderID = PJSUA_INVALID_ID;
incoming = (state==MGMSIPCallIncomingState);
muted = NO;
speaker = NO;
toneGenSlot = PJSUA_INVALID_ID;
2010-09-20 19:44:17 -05:00
}
2010-09-21 20:47:54 -05:00
bzero(&PJThreadDesc, sizeof(pj_thread_desc));
2010-09-20 19:44:17 -05:00
}
return self;
}
- (void)dealloc {
if (isRingbackOn)
[self stopRingback];
[self hangUp];
[remoteURL release];
[localURL release];
[stateText release];
[lastStatusText release];
[transferStatusText release];
[holdMusicPath release];
if (toneGenSlot!=PJSUA_INVALID_ID) {
pjsua_conf_remove_port(toneGenSlot);
pjmedia_port_destroy(toneGenPort);
toneGenPort = NULL;
}
2010-09-20 19:44:17 -05:00
[super dealloc];
}
- (NSString *)description {
return [NSString stringWithFormat:@"Remote: %@ Local: %@", remoteURL, localURL];
}
- (id<MGMSIPCallDelegate>)delegate {
return delegate;
}
- (void)setDelegate:(id)theDelegate {
delegate = theDelegate;
}
- (MGMSIPAccount *)account {
return account;
}
- (pjsua_call_id)identifier {
2010-09-20 19:44:17 -05:00
return identifier;
}
- (void)setIdentifier:(pjsua_call_id)theIdentifier {
2010-09-20 19:44:17 -05:00
identifier = theIdentifier;
}
- (MGMSIPURL *)remoteURL {
return remoteURL;
}
- (MGMSIPURL *)localURL {
return localURL;
}
- (MGMSIPCallState)state {
return state;
}
- (void)setState:(MGMSIPCallState)theState {
if (theState==MGMSIPCallDisconnectedState) {
#if TARGET_OS_IPHONE
if (speaker) [self speaker];
#endif
if (recorderID!=PJSUA_INVALID_ID)
[self performSelectorOnMainThread:@selector(stopRecordingMain) withObject:nil waitUntilDone:YES];
if (isRingbackOn)
[self stopRingback];
2010-09-20 19:44:17 -05:00
if (holdMusicPlayer!=PJSUA_INVALID_ID)
[self performSelectorOnMainThread:@selector(stopHoldMusic) withObject:nil waitUntilDone:YES];
2010-09-20 19:44:17 -05:00
}
state = theState;
}
- (NSString *)stateText {
return stateText;
}
- (void)setStateText:(NSString *)theStateText {
[stateText release];
2010-09-20 19:44:17 -05:00
stateText = [theStateText copy];
}
- (int)lastStatus {
return lastStatus;
}
- (void)setLastStatus:(int)theLastStatus {
lastStatus = theLastStatus;
}
- (NSString *)lastStatusText {
return lastStatusText;
}
- (void)setLastStatusText:(NSString *)theLastStatusText {
[lastStatusText release];
2010-09-20 19:44:17 -05:00
lastStatusText = [theLastStatusText copy];
}
- (int)transferStatus {
return transferStatus;
}
- (void)setTransferStatus:(int)theTransferStatus {
transferStatus = theTransferStatus;
}
- (NSString *)transferStatusText {
return transferStatusText;
}
- (void)setTransferStatusText:(NSString *)theTransferStatusText {
[transferStatusText release];
2010-09-20 19:44:17 -05:00
transferStatusText = [theTransferStatusText copy];
}
- (BOOL)isIncoming {
return incoming;
}
- (BOOL)isActive {
if (identifier==PJSUA_INVALID_ID)
return NO;
2010-09-21 20:47:54 -05:00
pj_thread_desc PJThreadDesc;
[[MGMSIP sharedSIP] registerThread:&PJThreadDesc];
2010-09-20 19:44:17 -05:00
2010-09-21 20:47:54 -05:00
pj_bool_t active = pjsua_call_is_active(identifier);
bzero(&PJThreadDesc, sizeof(pj_thread_desc));
return (active==PJ_TRUE);
2010-09-20 19:44:17 -05:00
}
- (BOOL)hasMedia {
if (identifier==PJSUA_INVALID_ID)
return NO;
2010-09-21 20:47:54 -05:00
pj_thread_desc PJThreadDesc;
[[MGMSIP sharedSIP] registerThread:&PJThreadDesc];
2010-09-20 19:44:17 -05:00
2010-09-21 20:47:54 -05:00
pj_bool_t media = pjsua_call_has_media(identifier);
bzero(&PJThreadDesc, sizeof(pj_thread_desc));
return (media==PJ_TRUE);
2010-09-20 19:44:17 -05:00
}
- (BOOL)hasActiveMedia {
if (identifier==PJSUA_INVALID_ID)
return NO;
2010-09-21 20:47:54 -05:00
pj_thread_desc PJThreadDesc;
[[MGMSIP sharedSIP] registerThread:&PJThreadDesc];
2010-09-20 19:44:17 -05:00
pjsua_call_info callInfo;
pjsua_call_get_info(identifier, &callInfo);
2010-09-21 20:47:54 -05:00
bzero(&PJThreadDesc, sizeof(pj_thread_desc));
2010-09-20 19:44:17 -05:00
return (callInfo.media_status==PJSUA_CALL_MEDIA_ACTIVE);
}
- (BOOL)isLocalOnHold {
if (identifier==PJSUA_INVALID_ID)
return NO;
return onHold;
}
- (BOOL)isRemoteOnHold {
if (identifier==PJSUA_INVALID_ID)
return NO;
2010-09-21 20:47:54 -05:00
pj_thread_desc PJThreadDesc;
[[MGMSIP sharedSIP] registerThread:&PJThreadDesc];
2010-09-20 19:44:17 -05:00
pjsua_call_info callInfo;
pjsua_call_get_info(identifier, &callInfo);
2010-09-21 20:47:54 -05:00
bzero(&PJThreadDesc, sizeof(pj_thread_desc));
2010-09-20 19:44:17 -05:00
return (callInfo.media_status==PJSUA_CALL_MEDIA_REMOTE_HOLD);
}
- (void)setHoldMusicPath:(NSString *)thePath {
[holdMusicPath release];
2010-09-20 19:44:17 -05:00
holdMusicPath = [thePath copy];
}
- (void)hold {
2010-09-21 20:47:54 -05:00
pj_thread_desc PJThreadDesc;
[[MGMSIP sharedSIP] registerThread:&PJThreadDesc];
2010-09-20 19:44:17 -05:00
if (state==MGMSIPCallConfirmedState) {
pjsua_conf_port_id conf_port = pjsua_call_get_conf_port(identifier);
if (!onHold) {
onHold = YES;
pjsua_conf_disconnect(0, conf_port);
pjsua_conf_adjust_rx_level(conf_port, 0);
[self performSelectorOnMainThread:@selector(startHoldMusic) withObject:nil waitUntilDone:YES];
2010-09-20 19:44:17 -05:00
} else {
onHold = NO;
pjsua_conf_connect(0, conf_port);
pjsua_conf_adjust_rx_level(conf_port, [[MGMSIP sharedSIP] micVolume]);
[self performSelectorOnMainThread:@selector(stopHoldMusic) withObject:nil waitUntilDone:YES];
2010-09-20 19:44:17 -05:00
}
}
2010-09-21 20:47:54 -05:00
bzero(&PJThreadDesc, sizeof(pj_thread_desc));
2010-09-20 19:44:17 -05:00
}
- (void)startHoldMusic {
if (holdMusicPlayer!=PJSUA_INVALID_ID)
return;
holdMusicPlayer = [self playSoundMain:holdMusicPath loop:YES];
}
- (void)stopHoldMusic {
[self stopPlayingSound:&holdMusicPlayer];
}
- (void)answer {
if (identifier==PJSUA_INVALID_ID || state==MGMSIPCallDisconnectedState)
return;
2010-09-21 20:47:54 -05:00
pj_thread_desc PJThreadDesc;
[[MGMSIP sharedSIP] registerThread:&PJThreadDesc];
2010-09-20 19:44:17 -05:00
pj_status_t status = pjsua_call_answer(identifier, PJSIP_SC_OK, NULL, NULL);
if (status!=PJ_SUCCESS)
NSLog(@"Error answering call %@", self);
2010-09-21 20:47:54 -05:00
bzero(&PJThreadDesc, sizeof(pj_thread_desc));
2010-09-20 19:44:17 -05:00
}
- (void)hangUp {
if (identifier==PJSUA_INVALID_ID || state==MGMSIPCallDisconnectedState)
return;
Added support for iPhone to MGMFFmpeg. Updated settings in Theme Tester. Updated settings in VoiceMac for the Theme Manager. Added the ability to hide icons in themes. Added the ability to change the font in themes. Fixed issue in MGMAddressBook where getting group members is not accurate. Made it so SIP addresses and Email addresses would not be recognized as phone numbers. Added support for 2 step verification. Added the ability to reload the user phone numbers. Added the ability to place the next message at any point in the previous message. Added the ability to do css based on the class of the message view with %MESSAGECLASSES%. Added the ability to get the codecs available and change the top codec in MGMSIP. Made it stop ring back before hanging up. Added initWithRootElement: to MGMXMLDocument. Added initWithName: and initWithName:stringValue: to MGMXMLElement. Added initWithKind:, setStringValue:, and fixed issues with reading attributes value. Made MGMVoiceUser support 2 step verification API, reload the user phones when it becomes active, and display a message if there is no phone numbers in Google Voice. Fixed issue where Google Chat will not appear in the User Phones list. Added a 2 Step Verification Dialog. Added Codec selection in MGMSIPPane. Fixed issues with MGMMultiSMS where it wouldn't alert the user if the message was blank and it wouldn't make the text field non editable. Added support for new SMS protocol to MGMSMSMessageView. Added support in the FFmpeg install script to build for iOS. Added ability to compile for the Simulator only in the PJProject build script. Made iOS and Mac OS final path go to 2 different folders. Updated to Revision 3466 of PJProject.
2011-03-21 07:43:56 -05:00
if (isRingbackOn)
[self stopRingback];
2010-09-21 20:47:54 -05:00
pj_thread_desc PJThreadDesc;
[[MGMSIP sharedSIP] registerThread:&PJThreadDesc];
2010-09-20 19:44:17 -05:00
if (recorderID!=PJSUA_INVALID_ID)
[self performSelectorOnMainThread:@selector(stopRecordingMain) withObject:nil waitUntilDone:YES];
2010-09-20 19:44:17 -05:00
pj_status_t status = pjsua_call_hangup(identifier, 0, NULL, NULL);
if (status!=PJ_SUCCESS)
NSLog(@"Error hanging up call %@", self);
}
- (void)sendRingingNotification {
if (identifier==PJSUA_INVALID_ID || state==MGMSIPCallDisconnectedState)
return;
2010-09-21 20:47:54 -05:00
pj_thread_desc PJThreadDesc;
[[MGMSIP sharedSIP] registerThread:&PJThreadDesc];
2010-09-20 19:44:17 -05:00
pj_status_t status = pjsua_call_answer(identifier, PJSIP_SC_RINGING, NULL, NULL);
if (status!=PJ_SUCCESS)
NSLog(@"Error sending ringing notification to call %@", self);
2010-09-21 20:47:54 -05:00
bzero(&PJThreadDesc, sizeof(pj_thread_desc));
2010-09-20 19:44:17 -05:00
}
- (void)replyWithTemporarilyUnavailable {
if (identifier==PJSUA_INVALID_ID || state==MGMSIPCallDisconnectedState)
return;
2010-09-21 20:47:54 -05:00
pj_thread_desc PJThreadDesc;
[[MGMSIP sharedSIP] registerThread:&PJThreadDesc];
2010-09-20 19:44:17 -05:00
pj_status_t status = pjsua_call_answer(identifier, PJSIP_SC_TEMPORARILY_UNAVAILABLE, NULL, NULL);
if (status!=PJ_SUCCESS)
NSLog(@"Error replying 480 Temporarily Unavailable");
2010-09-21 20:47:54 -05:00
bzero(&PJThreadDesc, sizeof(pj_thread_desc));
2010-09-20 19:44:17 -05:00
}
- (void)startRingback {
if (identifier==PJSUA_INVALID_ID)
2010-09-20 19:44:17 -05:00
return;
if (isRingbackOn)
return;
isRingbackOn = YES;
2010-09-21 20:47:54 -05:00
pj_thread_desc PJThreadDesc;
[[MGMSIP sharedSIP] registerThread:&PJThreadDesc];
2010-09-20 19:44:17 -05:00
[[MGMSIP sharedSIP] setRingbackCount:[[MGMSIP sharedSIP] ringbackCount]+1];
if ([[MGMSIP sharedSIP] ringbackCount]==1 && [[MGMSIP sharedSIP] ringbackSlot]!=PJSUA_INVALID_ID)
pjsua_conf_connect([[MGMSIP sharedSIP] ringbackSlot], 0);
2010-09-21 20:47:54 -05:00
bzero(&PJThreadDesc, sizeof(pj_thread_desc));
2010-09-20 19:44:17 -05:00
}
- (void)stopRingback {
if (identifier==PJSUA_INVALID_ID)
2010-09-20 19:44:17 -05:00
return;
if (!isRingbackOn)
return;
isRingbackOn = NO;
2010-09-21 20:47:54 -05:00
pj_thread_desc PJThreadDesc;
[[MGMSIP sharedSIP] registerThread:&PJThreadDesc];
2010-09-20 19:44:17 -05:00
int ringbackCount = [[MGMSIP sharedSIP] ringbackCount];
if (ringbackCount<=0) return;
2010-09-20 19:44:17 -05:00
[[MGMSIP sharedSIP] setRingbackCount:ringbackCount-1];
if ([[MGMSIP sharedSIP] ringbackSlot]!=PJSUA_INVALID_ID) {
pjsua_conf_disconnect([[MGMSIP sharedSIP] ringbackSlot], 0);
pjmedia_tonegen_rewind([[MGMSIP sharedSIP] ringbackPort]);
}
2010-09-21 20:47:54 -05:00
bzero(&PJThreadDesc, sizeof(pj_thread_desc));
2010-09-20 19:44:17 -05:00
}
- (void)sendDTMFDigits:(NSString *)theDigits {
if (identifier==PJSUA_INVALID_ID || state!=MGMSIPCallConfirmedState)
return;
2010-09-21 20:47:54 -05:00
pj_thread_desc PJThreadDesc;
[[MGMSIP sharedSIP] registerThread:&PJThreadDesc];
2010-09-20 19:44:17 -05:00
NSLog(@"%@", theDigits);
if ([account dtmfToneType]==0) {
pj_str_t digits = [theDigits PJString];
pj_status_t status = pjsua_call_dial_dtmf(identifier, &digits);
if (status!=PJ_SUCCESS)
NSLog(@"Unable to send DTMF tone.");
} else if ([account dtmfToneType]==1) {
2010-09-20 19:44:17 -05:00
const pj_str_t INFO = pj_str("INFO");
for (unsigned int i=0; i<[theDigits length]; i++) {
pjsua_msg_data messageData;
pjsua_msg_data_init(&messageData);
messageData.content_type = pj_str("application/dtmf-relay");
messageData.msg_body = [[NSString stringWithFormat:@"Signal=%C\r\nDuration=300", [theDigits characterAtIndex:i]] PJString];
pj_status_t status = pjsua_call_send_request(identifier, &INFO, &messageData);
if (status!=PJ_SUCCESS)
NSLog(@"Unable to send DTMF tone.");
2010-09-20 19:44:17 -05:00
}
}
if (toneGenSlot==PJSUA_INVALID_ID) {
pjsua_media_config mediaConfig = [[MGMSIP sharedSIP] mediaConfig];
unsigned int samplesPerFrame = mediaConfig.audio_frame_ptime * mediaConfig.clock_rate * mediaConfig.channel_count / 1000;
pj_status_t status = pjmedia_tonegen_create([[MGMSIP sharedSIP] PJPool], mediaConfig.clock_rate, mediaConfig.channel_count, samplesPerFrame, 16, 0, &toneGenPort);
if (status!=PJ_SUCCESS) {
NSLog(@"Error creating tone generator");
} else {
status = pjsua_conf_add_port([[MGMSIP sharedSIP] PJPool], toneGenPort, &toneGenSlot);
if (status!=PJ_SUCCESS)
NSLog(@"Error adding tone generator");
else
pjsua_conf_connect(toneGenSlot, 0);
}
}
if ([account dtmfToneType]==2) {
NSLog(@"Using Tone Generator.");
pjsua_conf_connect(toneGenSlot, pjsua_call_get_conf_port(identifier));
}
for (unsigned int i=0; i<[theDigits length]; i++) {
pjmedia_tonegen_stop(toneGenPort);
pjmedia_tone_digit digit[1];
digit[0].digit = [theDigits characterAtIndex:i];
digit[0].on_msec = 300;
digit[0].off_msec = 300;
digit[0].volume = 16383;
pjmedia_tonegen_play_digits(toneGenPort, 1, digit, 0);
if ([theDigits length]!=1 && (i+1)<[theDigits length]) [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
}
bzero(&PJThreadDesc, sizeof(pj_thread_desc));
}
- (void)receivedDTMFDigit:(int)theDigit {
if (identifier==PJSUA_INVALID_ID || state!=MGMSIPCallConfirmedState)
return;
if (delegate!=nil && [delegate respondsToSelector:@selector(receivedDMTFDigit:)]) [delegate receivedDMTFDigit:theDigit];
pj_thread_desc PJThreadDesc;
[[MGMSIP sharedSIP] registerThread:&PJThreadDesc];
if (toneGenSlot==PJSUA_INVALID_ID) {
pjsua_media_config mediaConfig = [[MGMSIP sharedSIP] mediaConfig];
unsigned int samplesPerFrame = mediaConfig.audio_frame_ptime * mediaConfig.clock_rate * mediaConfig.channel_count / 1000;
pj_status_t status = pjmedia_tonegen_create([[MGMSIP sharedSIP] PJPool], mediaConfig.clock_rate, mediaConfig.channel_count, samplesPerFrame, 16, 0, &toneGenPort);
if (status!=PJ_SUCCESS) {
NSLog(@"Error creating tone generator");
} else {
status = pjsua_conf_add_port([[MGMSIP sharedSIP] PJPool], toneGenPort, &toneGenSlot);
if (status!=PJ_SUCCESS)
NSLog(@"Error adding tone generator");
else
pjsua_conf_connect(toneGenSlot, 0);
}
}
pjmedia_tonegen_stop(toneGenPort);
pjsua_conf_disconnect(toneGenSlot, pjsua_call_get_conf_port(identifier));
pjmedia_tone_digit digit[1];
digit[0].digit = theDigit;
digit[0].on_msec = 100;
digit[0].off_msec = 100;
digit[0].volume = 16383;
pjmedia_tonegen_play_digits(toneGenPort, 1, digit, 0);
2010-09-21 20:47:54 -05:00
bzero(&PJThreadDesc, sizeof(pj_thread_desc));
2010-09-20 19:44:17 -05:00
}
- (void)playSound:(NSString *)theFile {
NSMethodSignature *signature = [self methodSignatureForSelector:@selector(playSoundMain:loop:)];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setSelector:@selector(playSoundMain:loop:)];
[invocation setArgument:&theFile atIndex:2];
BOOL shouldLoop = NO;
[invocation setArgument:&shouldLoop atIndex:3];
[invocation performSelectorOnMainThread:@selector(invokeWithTarget:) withObject:self waitUntilDone:YES];
}
- (pjsua_player_id)playSoundMain:(NSString *)theFile loop:(BOOL)shouldLoop {
if (identifier==PJSUA_INVALID_ID || state!=MGMSIPCallConfirmedState)
return PJSUA_INVALID_ID;
2010-09-21 20:47:54 -05:00
pj_thread_desc PJThreadDesc;
[[MGMSIP sharedSIP] registerThread:&PJThreadDesc];
2010-09-20 19:44:17 -05:00
pjsua_player_id player_id = PJSUA_INVALID_ID;
if (theFile==nil || ![[NSFileManager defaultManager] fileExistsAtPath:theFile])
return player_id;
pj_str_t file = [theFile PJString];
pj_status_t status = pjsua_player_create(&file, (shouldLoop ? 0 : PJMEDIA_FILE_NO_LOOP), &player_id);
if (status!=PJ_SUCCESS) {
NSLog(@"Couldn't create player");
return PJSUA_INVALID_ID;
} else {
status = pjsua_conf_connect(pjsua_player_get_conf_port(player_id), pjsua_call_get_conf_port(identifier));
if (status!=PJ_SUCCESS)
NSLog(@"Unable to play sound");
}
2010-09-21 20:47:54 -05:00
bzero(&PJThreadDesc, sizeof(pj_thread_desc));
2010-09-20 19:44:17 -05:00
return player_id;
}
- (void)stopPlayingSound:(pjsua_player_id *)thePlayerID {
if (*thePlayerID==PJSUA_INVALID_ID)
return;
2010-09-21 20:47:54 -05:00
pj_thread_desc PJThreadDesc;
[[MGMSIP sharedSIP] registerThread:&PJThreadDesc];
2010-09-20 19:44:17 -05:00
pjsua_player_destroy(*thePlayerID);
*thePlayerID = PJSUA_INVALID_ID;
2010-09-21 20:47:54 -05:00
bzero(&PJThreadDesc, sizeof(pj_thread_desc));
2010-09-20 19:44:17 -05:00
}
- (BOOL)isRecording {
return (recorderID!=PJSUA_INVALID_ID);
}
- (void)startRecording:(NSString *)toFile {
[self performSelectorOnMainThread:@selector(startRecordingMain:) withObject:toFile waitUntilDone:YES];
}
- (void)startRecordingMain:(NSString *)toFile {
if (recorderID!=PJSUA_INVALID_ID || identifier==PJSUA_INVALID_ID || state!=MGMSIPCallConfirmedState)
return;
2010-09-21 20:47:54 -05:00
pj_thread_desc PJThreadDesc;
[[MGMSIP sharedSIP] registerThread:&PJThreadDesc];
2010-09-20 19:44:17 -05:00
pj_str_t file = [toFile PJString];
pj_status_t status = pjsua_recorder_create(&file, 0, NULL, 0, 0, &recorderID);
if (status!=PJ_SUCCESS) {
NSLog(@"Couldn't create recorder");
} else {
pjsua_conf_connect(pjsua_call_get_conf_port(identifier), pjsua_recorder_get_conf_port(recorderID));
pjsua_conf_connect(0, pjsua_recorder_get_conf_port(recorderID));
}
2010-09-21 20:47:54 -05:00
bzero(&PJThreadDesc, sizeof(pj_thread_desc));
2010-09-20 19:44:17 -05:00
}
- (void)stopRecording {
[self performSelectorOnMainThread:@selector(stopRecordingMain) withObject:nil waitUntilDone:YES];
}
- (void)stopRecordingMain {
if (recorderID==PJSUA_INVALID_ID)
return;
2010-09-21 20:47:54 -05:00
pj_thread_desc PJThreadDesc;
[[MGMSIP sharedSIP] registerThread:&PJThreadDesc];
2010-09-20 19:44:17 -05:00
pjsua_recorder_destroy(recorderID);
recorderID = PJSUA_INVALID_ID;
2010-09-21 20:47:54 -05:00
bzero(&PJThreadDesc, sizeof(pj_thread_desc));
2010-09-20 19:44:17 -05:00
}
- (BOOL)isMuted {
return muted;
}
- (void)mute {
if (identifier==PJSUA_INVALID_ID || holdMusicPlayer!=PJSUA_INVALID_ID || state!=MGMSIPCallConfirmedState)
return;
2010-09-21 20:47:54 -05:00
pj_thread_desc PJThreadDesc;
[[MGMSIP sharedSIP] registerThread:&PJThreadDesc];
2010-09-20 19:44:17 -05:00
pj_status_t status;
if (muted)
status = pjsua_conf_adjust_rx_level(pjsua_call_get_conf_port(identifier), [[MGMSIP sharedSIP] micVolume]);
else
status = pjsua_conf_adjust_rx_level(pjsua_call_get_conf_port(identifier), 0);
if (status!=PJ_SUCCESS)
NSLog(@"Error %@ speakers for call %@", (muted ? @"unmuting" : @"mutting"), self);
else
muted = !muted;
2010-09-21 20:47:54 -05:00
bzero(&PJThreadDesc, sizeof(pj_thread_desc));
2010-09-20 19:44:17 -05:00
}
- (BOOL)isMicMuted {
return micMuted;
}
- (void)muteMic {
if (identifier==PJSUA_INVALID_ID || holdMusicPlayer!=PJSUA_INVALID_ID || state!=MGMSIPCallConfirmedState)
return;
2010-09-21 20:47:54 -05:00
pj_thread_desc PJThreadDesc;
[[MGMSIP sharedSIP] registerThread:&PJThreadDesc];
2010-09-20 19:44:17 -05:00
pj_status_t status;
if (micMuted)
status = pjsua_conf_connect(0, pjsua_call_get_conf_port(identifier));
else
status = pjsua_conf_disconnect(0, pjsua_call_get_conf_port(identifier));
if (status!=PJ_SUCCESS)
NSLog(@"Error %@ microphone for call %@", (micMuted ? @"unmuting" : @"mutting"), self);
else
micMuted = !micMuted;
2010-09-21 20:47:54 -05:00
bzero(&PJThreadDesc, sizeof(pj_thread_desc));
2010-09-20 19:44:17 -05:00
}
#if TARGET_OS_IPHONE
- (BOOL)isOnSpeaker {
return speaker;
}
- (void)speaker {
speaker = !speaker;
UInt32 route = (speaker ? kAudioSessionOverrideAudioRoute_Speaker : kAudioSessionOverrideAudioRoute_None);
if (AudioSessionSetProperty(kAudioSessionProperty_OverrideAudioRoute, sizeof(route), &route)!=noErr)
speaker = !speaker;
}
#endif
2010-09-20 19:44:17 -05:00
@end
#endif