Closed ticket #1107: iOS4 background feature
* pjlib: * add support for activesock TCP to work in background mode. * add feature in ioqueue to recreate closed UDP sockets. * pjsip-apps: * ipjsua: add support for iPhone OS 4 background mode * ipjsystest: add support for iPhone OS 4 background mode git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@3299 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
parent
f50194620e
commit
be3771a637
12058
aconfigure
12058
aconfigure
File diff suppressed because it is too large
Load Diff
|
@ -533,7 +533,7 @@ if test "$enable_sound" = "no"; then
|
|||
else
|
||||
case $target in
|
||||
arm-apple-darwin*)
|
||||
LIBS="$LIBS -framework CoreAudio -framework CoreFoundation -framework AudioToolbox"
|
||||
LIBS="$LIBS -framework CoreAudio -framework CoreFoundation -framework AudioToolbox -framework CFNetwork"
|
||||
AC_MSG_RESULT([Checking sound device backend... AudioUnit])
|
||||
;;
|
||||
*darwin*)
|
||||
|
|
|
@ -302,6 +302,21 @@ PJ_DECL(pj_status_t) pj_activesock_create_udp(pj_pool_t *pool,
|
|||
*/
|
||||
PJ_DECL(pj_status_t) pj_activesock_close(pj_activesock_t *asock);
|
||||
|
||||
#if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
|
||||
PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0
|
||||
/**
|
||||
* Set iPhone OS background mode setting. Setting to 1 will enable TCP
|
||||
* active socket to receive incoming data when application is in the
|
||||
* background. Setting to 0 will disable it. Default value of this
|
||||
* setting is PJ_ACTIVESOCK_TCP_IPHONE_OS_BG.
|
||||
*
|
||||
* @param asock The active socket.
|
||||
* @param val The value of background mode setting.
|
||||
*
|
||||
*/
|
||||
PJ_DECL(void) pj_activesock_set_iphone_os_bg(pj_activesock_t *asock,
|
||||
int val);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Associate arbitrary data with the active socket. Application may
|
||||
|
|
|
@ -169,13 +169,17 @@
|
|||
/* The type of atomic variable value: */
|
||||
#undef PJ_ATOMIC_VALUE_TYPE
|
||||
|
||||
/* Append ".local" suffix to the system's hostname? */
|
||||
#if defined(PJ_DARWINOS) && PJ_DARWINOS!=0
|
||||
# include "TargetConditionals.h"
|
||||
# if TARGET_OS_IPHONE
|
||||
# include "Availability.h"
|
||||
# ifdef __IPHONE_4_0
|
||||
# define PJ_GETHOSTNAME_APPEND_LOCAL_SUFFIX 1
|
||||
/* Append ".local" suffix to the system's hostname? (see ticket #1104) */
|
||||
# define PJ_GETHOSTNAME_APPEND_LOCAL_SUFFIX 1
|
||||
/* Is multitasking support available? (see ticket #1107) */
|
||||
# define PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT 1
|
||||
/* Enable activesock TCP background mode support */
|
||||
# define PJ_ACTIVESOCK_TCP_IPHONE_OS_BG 1
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
|
|
@ -21,10 +21,16 @@
|
|||
#include <pj/compat/socket.h>
|
||||
#include <pj/assert.h>
|
||||
#include <pj/errno.h>
|
||||
#include <pj/log.h>
|
||||
#include <pj/pool.h>
|
||||
#include <pj/sock.h>
|
||||
#include <pj/string.h>
|
||||
|
||||
#if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
|
||||
PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0
|
||||
# include <CFNetwork/CFNetwork.h>
|
||||
#endif
|
||||
|
||||
#define PJ_ACTIVESOCK_MAX_LOOP 50
|
||||
|
||||
|
||||
|
@ -71,7 +77,13 @@ struct pj_activesock_t
|
|||
unsigned async_count;
|
||||
unsigned max_loop;
|
||||
pj_activesock_cb cb;
|
||||
|
||||
#if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
|
||||
PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0
|
||||
int bg_setting;
|
||||
pj_sock_t sock;
|
||||
CFReadStreamRef readStream;
|
||||
#endif
|
||||
|
||||
struct send_data send_data;
|
||||
|
||||
struct read_op *read_op;
|
||||
|
@ -105,6 +117,51 @@ PJ_DEF(void) pj_activesock_cfg_default(pj_activesock_cfg *cfg)
|
|||
cfg->whole_data = PJ_TRUE;
|
||||
}
|
||||
|
||||
#if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
|
||||
PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0
|
||||
static void activesock_destroy_iphone_os_stream(pj_activesock_t *asock)
|
||||
{
|
||||
if (asock->readStream) {
|
||||
CFReadStreamClose(asock->readStream);
|
||||
CFRelease(asock->readStream);
|
||||
asock->readStream = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void activesock_create_iphone_os_stream(pj_activesock_t *asock)
|
||||
{
|
||||
if (asock->bg_setting && asock->stream_oriented) {
|
||||
activesock_destroy_iphone_os_stream(asock);
|
||||
|
||||
CFStreamCreatePairWithSocket(kCFAllocatorDefault, asock->sock,
|
||||
&asock->readStream, NULL);
|
||||
|
||||
if (!asock->readStream ||
|
||||
CFReadStreamSetProperty(asock->readStream,
|
||||
kCFStreamNetworkServiceType,
|
||||
kCFStreamNetworkServiceTypeVoIP)
|
||||
!= TRUE ||
|
||||
CFReadStreamOpen(asock->readStream) != TRUE)
|
||||
{
|
||||
PJ_LOG(2,("", "Failed to configure TCP transport for VoIP "
|
||||
"usage. Background mode will not be supported."));
|
||||
|
||||
activesock_destroy_iphone_os_stream(asock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PJ_DEF(void) pj_activesock_set_iphone_os_bg(pj_activesock_t *asock,
|
||||
int val)
|
||||
{
|
||||
asock->bg_setting = val;
|
||||
if (asock->bg_setting)
|
||||
activesock_create_iphone_os_stream(asock);
|
||||
else
|
||||
activesock_destroy_iphone_os_stream(asock);
|
||||
}
|
||||
#endif
|
||||
|
||||
PJ_DEF(pj_status_t) pj_activesock_create( pj_pool_t *pool,
|
||||
pj_sock_t sock,
|
||||
|
@ -156,6 +213,13 @@ PJ_DEF(pj_status_t) pj_activesock_create( pj_pool_t *pool,
|
|||
pj_ioqueue_set_concurrency(asock->key, opt->concurrency);
|
||||
}
|
||||
|
||||
#if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
|
||||
PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0
|
||||
asock->sock = sock;
|
||||
pj_activesock_set_iphone_os_bg(asock,
|
||||
PJ_ACTIVESOCK_TCP_IPHONE_OS_BG);
|
||||
#endif
|
||||
|
||||
*p_asock = asock;
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
@ -215,6 +279,11 @@ PJ_DEF(pj_status_t) pj_activesock_close(pj_activesock_t *asock)
|
|||
{
|
||||
PJ_ASSERT_RETURN(asock, PJ_EINVAL);
|
||||
if (asock->key) {
|
||||
#if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
|
||||
PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0
|
||||
activesock_destroy_iphone_os_stream(asock);
|
||||
#endif
|
||||
|
||||
pj_ioqueue_unregister(asock->key);
|
||||
asock->key = NULL;
|
||||
}
|
||||
|
@ -733,6 +802,10 @@ static void ioqueue_on_accept_complete(pj_ioqueue_key_t *key,
|
|||
if (!ret)
|
||||
return;
|
||||
|
||||
#if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
|
||||
PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0
|
||||
activesock_create_iphone_os_stream(asock);
|
||||
#endif
|
||||
} else if (status==PJ_SUCCESS) {
|
||||
/* Application doesn't handle the new socket, we need to
|
||||
* close it to avoid resource leak.
|
||||
|
@ -775,6 +848,12 @@ static void ioqueue_on_connect_complete(pj_ioqueue_key_t *key,
|
|||
/* We've been destroyed */
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
|
||||
PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0
|
||||
activesock_create_iphone_os_stream(asock);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
#endif /* PJ_HAS_TCP */
|
||||
|
|
|
@ -529,6 +529,16 @@ void ioqueue_dispatch_read_event( pj_ioqueue_t *ioqueue, pj_ioqueue_key_t *h )
|
|||
|
||||
/* In any case we would report this to caller. */
|
||||
bytes_read = -rc;
|
||||
|
||||
#if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
|
||||
PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0
|
||||
/* Special treatment for dead UDP sockets here, see ticket #1107 */
|
||||
if (rc == PJ_STATUS_FROM_OS(ENOTCONN) && !IS_CLOSING(h) &&
|
||||
h->fd_type==pj_SOCK_DGRAM())
|
||||
{
|
||||
replace_udp_sock(h);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Unlock; from this point we don't need to hold key's mutex
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <pj/sock.h>
|
||||
#include <pj/compat/socket.h>
|
||||
#include <pj/sock_select.h>
|
||||
#include <pj/sock_qos.h>
|
||||
#include <pj/errno.h>
|
||||
|
||||
/* Now that we have access to OS'es <sys/select>, lets check again that
|
||||
|
@ -123,6 +124,9 @@ struct pj_ioqueue_t
|
|||
#endif
|
||||
};
|
||||
|
||||
/* Proto */
|
||||
static pj_status_t replace_udp_sock(pj_ioqueue_key_t *h);
|
||||
|
||||
/* Include implementation for common abstraction after we declare
|
||||
* pj_ioqueue_key_t and pj_ioqueue_t.
|
||||
*/
|
||||
|
@ -620,6 +624,139 @@ static void scan_closing_keys(pj_ioqueue_t *ioqueue)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
|
||||
PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0
|
||||
static pj_status_t replace_udp_sock(pj_ioqueue_key_t *h)
|
||||
{
|
||||
enum flags {
|
||||
HAS_PEER_ADDR = 1,
|
||||
HAS_QOS = 2
|
||||
};
|
||||
pj_sock_t old_sock, new_sock = PJ_INVALID_SOCKET;
|
||||
pj_sockaddr local_addr, rem_addr;
|
||||
int val, addr_len;
|
||||
pj_fd_set_t *fds[3];
|
||||
unsigned i, fds_cnt, flags=0;
|
||||
pj_qos_params qos_params;
|
||||
unsigned msec;
|
||||
pj_status_t status;
|
||||
|
||||
pj_lock_acquire(h->ioqueue->lock);
|
||||
|
||||
old_sock = h->fd;
|
||||
|
||||
/* Can only replace UDP socket */
|
||||
pj_assert(h->fd_type == pj_SOCK_DGRAM());
|
||||
|
||||
PJ_LOG(4,(THIS_FILE, "Attempting to replace UDP socket %d", old_sock));
|
||||
|
||||
/* Investigate the old socket */
|
||||
addr_len = sizeof(local_addr);
|
||||
status = pj_sock_getsockname(old_sock, &local_addr, &addr_len);
|
||||
if (status != PJ_SUCCESS)
|
||||
goto on_error;
|
||||
|
||||
addr_len = sizeof(rem_addr);
|
||||
status = pj_sock_getpeername(old_sock, &rem_addr, &addr_len);
|
||||
if (status == PJ_SUCCESS)
|
||||
flags |= HAS_PEER_ADDR;
|
||||
|
||||
status = pj_sock_get_qos_params(old_sock, &qos_params);
|
||||
if (status == PJ_SUCCESS)
|
||||
flags |= HAS_QOS;
|
||||
|
||||
/* We're done with the old socket, close it otherwise we'll get
|
||||
* error in bind()
|
||||
*/
|
||||
pj_sock_close(old_sock);
|
||||
|
||||
/* Prepare the new socket */
|
||||
status = pj_sock_socket(local_addr.addr.sa_family, PJ_SOCK_DGRAM, 0,
|
||||
&new_sock);
|
||||
if (status != PJ_SUCCESS)
|
||||
goto on_error;
|
||||
|
||||
/* Even after the socket is closed, we'll still get "Address in use"
|
||||
* errors, so force it with SO_REUSEADDR
|
||||
*/
|
||||
val = 1;
|
||||
status = pj_sock_setsockopt(new_sock, SOL_SOCKET, SO_REUSEADDR,
|
||||
&val, sizeof(val));
|
||||
if (status != PJ_SUCCESS)
|
||||
goto on_error;
|
||||
|
||||
/* The loop is silly, but what else can we do? */
|
||||
addr_len = pj_sockaddr_get_len(&local_addr);
|
||||
for (msec=20; ; msec<1000? msec=msec*2 : 1000) {
|
||||
status = pj_sock_bind(new_sock, &local_addr, addr_len);
|
||||
if (status != PJ_STATUS_FROM_OS(EADDRINUSE))
|
||||
break;
|
||||
PJ_LOG(4,(THIS_FILE, "Address is still in use, retrying.."));
|
||||
pj_thread_sleep(msec);
|
||||
}
|
||||
|
||||
if (status != PJ_SUCCESS)
|
||||
goto on_error;
|
||||
|
||||
if (flags & HAS_QOS) {
|
||||
status = pj_sock_set_qos_params(new_sock, &qos_params);
|
||||
if (status != PJ_SUCCESS)
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
if (flags & HAS_PEER_ADDR) {
|
||||
status = pj_sock_connect(new_sock, &rem_addr, addr_len);
|
||||
if (status != PJ_SUCCESS)
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
/* Set socket to nonblocking. */
|
||||
val = 1;
|
||||
#if defined(PJ_WIN32) && PJ_WIN32!=0 || \
|
||||
defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE!=0
|
||||
if (ioctlsocket(new_sock, FIONBIO, &val)) {
|
||||
#else
|
||||
if (ioctl(new_sock, FIONBIO, &val)) {
|
||||
#endif
|
||||
status = pj_get_netos_error();
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
/* Replace the occurrence of old socket with new socket in the
|
||||
* fd sets.
|
||||
*/
|
||||
fds_cnt = 0;
|
||||
fds[fds_cnt++] = &h->ioqueue->rfdset;
|
||||
fds[fds_cnt++] = &h->ioqueue->wfdset;
|
||||
#if PJ_HAS_TCP
|
||||
fds[fds_cnt++] = &h->ioqueue->xfdset;
|
||||
#endif
|
||||
|
||||
for (i=0; i<fds_cnt; ++i) {
|
||||
if (PJ_FD_ISSET(old_sock, fds[i])) {
|
||||
PJ_FD_CLR(old_sock, fds[i]);
|
||||
PJ_FD_SET(new_sock, fds[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* And finally replace the fd in the key */
|
||||
h->fd = new_sock;
|
||||
|
||||
PJ_LOG(4,(THIS_FILE, "UDP has been replaced successfully!"));
|
||||
|
||||
pj_lock_release(h->ioqueue->lock);
|
||||
|
||||
return PJ_SUCCESS;
|
||||
|
||||
on_error:
|
||||
if (new_sock != PJ_INVALID_SOCKET)
|
||||
pj_sock_close(new_sock);
|
||||
PJ_PERROR(1,(THIS_FILE, status, "Error replacing socket"));
|
||||
pj_lock_release(h->ioqueue->lock);
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* pj_ioqueue_poll()
|
||||
|
|
|
@ -513,12 +513,21 @@ PJ_DEF(pj_status_t) pj_sock_socket(int af,
|
|||
PJ_ASSERT_RETURN(sock!=NULL, PJ_EINVAL);
|
||||
PJ_ASSERT_RETURN(PJ_INVALID_SOCKET==-1,
|
||||
(*sock=PJ_INVALID_SOCKET, PJ_EINVAL));
|
||||
|
||||
|
||||
*sock = socket(af, type, proto);
|
||||
if (*sock == PJ_INVALID_SOCKET)
|
||||
return PJ_RETURN_OS_ERROR(pj_get_native_netos_error());
|
||||
else
|
||||
else {
|
||||
#if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
|
||||
PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0
|
||||
pj_int32_t val = 1;
|
||||
if (type == pj_SOCK_DGRAM()) {
|
||||
pj_sock_setsockopt(*sock, pj_SOL_SOCKET(), SO_NOSIGPIPE,
|
||||
&val, sizeof(val));
|
||||
}
|
||||
#endif
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
//
|
||||
|
||||
#import <pjlib.h>
|
||||
#import <pjsua.h>
|
||||
#import "ipjsuaAppDelegate.h"
|
||||
|
||||
extern pj_log_func *log_cb;
|
||||
|
@ -18,14 +19,15 @@ extern pj_log_func *log_cb;
|
|||
@synthesize cfgView;
|
||||
|
||||
/* Sleep interval duration */
|
||||
#define SLEEP_INTERVAL 0.5
|
||||
#define SLEEP_INTERVAL 0.5
|
||||
/* Determine whether we should print the messages in the debugger
|
||||
* console as well
|
||||
*/
|
||||
#define DEBUGGER_PRINT 1
|
||||
#define DEBUGGER_PRINT 1
|
||||
/* Whether we should show pj log messages in the text area */
|
||||
#define SHOW_LOG 1
|
||||
#define PATH_LENGTH PJ_MAXPATH
|
||||
#define SHOW_LOG 1
|
||||
#define PATH_LENGTH PJ_MAXPATH
|
||||
#define KEEP_ALIVE_INTERVAL 600
|
||||
|
||||
extern pj_bool_t app_restart;
|
||||
|
||||
|
@ -34,13 +36,17 @@ char *argv[] = {"", "--config-file", argv_buf};
|
|||
|
||||
ipjsuaAppDelegate *app;
|
||||
|
||||
bool app_running;
|
||||
bool thread_quit;
|
||||
bool app_running;
|
||||
bool thread_quit;
|
||||
NSMutableString *mstr;
|
||||
pj_thread_desc a_thread_desc;
|
||||
pj_thread_t *a_thread;
|
||||
pjsua_call_id ccall_id;
|
||||
|
||||
pj_status_t app_init(int argc, char *argv[]);
|
||||
pj_status_t app_main(void);
|
||||
pj_status_t app_destroy(void);
|
||||
void keepAliveFunction(int timeout);
|
||||
|
||||
void showMsg(const char *format, ...)
|
||||
{
|
||||
|
@ -50,7 +56,7 @@ void showMsg(const char *format, ...)
|
|||
va_start(arg, format);
|
||||
NSString *str = [[NSString alloc] initWithFormat:[NSString stringWithFormat:@"%s", format] arguments: arg];
|
||||
#if DEBUGGER_PRINT
|
||||
NSLog(str);
|
||||
NSLog(@"%@", str);
|
||||
#endif
|
||||
va_end(arg);
|
||||
|
||||
|
@ -92,6 +98,62 @@ void showLog(int level, const char *data, int len)
|
|||
showMsg("%s", data);
|
||||
}
|
||||
|
||||
pj_bool_t showNotification(pjsua_call_id call_id)
|
||||
{
|
||||
#ifdef __IPHONE_4_0
|
||||
ccall_id = call_id;
|
||||
|
||||
// Create a new notification
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
UILocalNotification* alert = [[[UILocalNotification alloc] init] autorelease];
|
||||
if (alert)
|
||||
{
|
||||
alert.repeatInterval = 0;
|
||||
alert.alertBody = @"Incoming call received...";
|
||||
alert.alertAction = @"Answer";
|
||||
|
||||
[[UIApplication sharedApplication] presentLocalNotificationNow:alert];
|
||||
}
|
||||
|
||||
[pool release];
|
||||
|
||||
return PJ_FALSE;
|
||||
#else
|
||||
return PJ_TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)answer_call {
|
||||
if (!pj_thread_is_registered())
|
||||
{
|
||||
pj_thread_register("ipjsua", a_thread_desc, &a_thread);
|
||||
}
|
||||
pjsua_call_answer(ccall_id, 200, NULL, NULL);
|
||||
}
|
||||
|
||||
#ifdef __IPHONE_4_0
|
||||
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
|
||||
[app performSelectorOnMainThread:@selector(answer_call) withObject:nil waitUntilDone:YES];
|
||||
}
|
||||
|
||||
- (void)keepAlive {
|
||||
if (!pj_thread_is_registered())
|
||||
{
|
||||
pj_thread_register("ipjsua", a_thread_desc, &a_thread);
|
||||
}
|
||||
keepAliveFunction(KEEP_ALIVE_INTERVAL);
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackground:(UIApplication *)application
|
||||
{
|
||||
[app performSelectorOnMainThread:@selector(keepAlive) withObject:nil waitUntilDone:YES];
|
||||
[application setKeepAliveTimeout:KEEP_ALIVE_INTERVAL handler: ^{
|
||||
[app performSelectorOnMainThread:@selector(keepAlive) withObject:nil waitUntilDone:YES];
|
||||
}];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
- (void)start_app {
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
/* Wait until the view is ready */
|
||||
|
|
|
@ -28,5 +28,10 @@
|
|||
<string>MainWindow</string>
|
||||
<key>UIInterfaceOrientation</key>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>audio</string>
|
||||
<string>voip</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
282CCBFE0DB6C98000C4EA27 /* SecondView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 282CCBFD0DB6C98000C4EA27 /* SecondView.xib */; };
|
||||
288765080DF74369002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765070DF74369002DB57D /* CoreGraphics.framework */; };
|
||||
28AD73880D9D96C1002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD73870D9D96C1002E5188 /* MainWindow.xib */; };
|
||||
3A0D789F121E324E009D5030 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3A0D789E121E324E009D5030 /* CFNetwork.framework */; };
|
||||
3AE9099D11587BB900FAEAA5 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE9099C11587BB900FAEAA5 /* AudioToolbox.framework */; };
|
||||
3AE90A2D1158B52500FAEAA5 /* pjsua_app.c in Sources */ = {isa = PBXBuildFile; fileRef = 3AE90A2C1158B52500FAEAA5 /* pjsua_app.c */; };
|
||||
3AE90A6A1158C6B400FAEAA5 /* libgsmcodec-arm-apple-darwin9.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AE90A691158C6B400FAEAA5 /* libgsmcodec-arm-apple-darwin9.a */; };
|
||||
|
@ -53,6 +54,7 @@
|
|||
28A0AB4B0D9B1048005BE974 /* ipjsua_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ipjsua_Prefix.pch; sourceTree = "<group>"; };
|
||||
28AD73870D9D96C1002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = "<group>"; };
|
||||
29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
3A0D789E121E324E009D5030 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };
|
||||
3AE9099C11587BB900FAEAA5 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
|
||||
3AE90A2C1158B52500FAEAA5 /* pjsua_app.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pjsua_app.c; path = ../pjsua/pjsua_app.c; sourceTree = SOURCE_ROOT; };
|
||||
3AE90A691158C6B400FAEAA5 /* libgsmcodec-arm-apple-darwin9.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libgsmcodec-arm-apple-darwin9.a"; path = "../../../third_party/lib/libgsmcodec-arm-apple-darwin9.a"; sourceTree = SOURCE_ROOT; };
|
||||
|
@ -109,6 +111,7 @@
|
|||
3AE90EBA115F7BCE00FAEAA5 /* libpjsdp-arm-apple-darwin9.a in Frameworks */,
|
||||
3AE90EBB115F7BCE00FAEAA5 /* libspeex-arm-apple-darwin9.a in Frameworks */,
|
||||
3AE90EBC115F7BCE00FAEAA5 /* libsrtp-arm-apple-darwin9.a in Frameworks */,
|
||||
3A0D789F121E324E009D5030 /* CFNetwork.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -180,6 +183,7 @@
|
|||
1D30AB110D05D00D00671497 /* Foundation.framework */,
|
||||
288765070DF74369002DB57D /* CoreGraphics.framework */,
|
||||
3AE9099C11587BB900FAEAA5 /* AudioToolbox.framework */,
|
||||
3A0D789E121E324E009D5030 /* CFNetwork.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
|
@ -347,8 +351,9 @@
|
|||
../../../pjsip/lib,
|
||||
../../../third_party/lib,
|
||||
);
|
||||
OTHER_CFLAGS = "";
|
||||
PREBINDING = NO;
|
||||
SDKROOT = iphoneos3.1.2;
|
||||
SDKROOT = iphoneos4.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
|
@ -376,8 +381,9 @@
|
|||
../../../pjsip/lib,
|
||||
../../../third_party/lib,
|
||||
);
|
||||
OTHER_CFLAGS = "";
|
||||
PREBINDING = NO;
|
||||
SDKROOT = iphoneos3.1.2;
|
||||
SDKROOT = iphoneos4.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
|
|
@ -26,5 +26,9 @@
|
|||
<true/>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainWindow</string>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>audio</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -366,7 +366,7 @@
|
|||
../../../third_party/lib,
|
||||
);
|
||||
PREBINDING = NO;
|
||||
SDKROOT = iphoneos3.1.2;
|
||||
SDKROOT = iphoneos4.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
|
@ -394,7 +394,7 @@
|
|||
../../../third_party/lib,
|
||||
);
|
||||
PREBINDING = NO;
|
||||
SDKROOT = iphoneos3.1.2;
|
||||
SDKROOT = iphoneos4.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
|
|
@ -29,6 +29,7 @@ PJ_BEGIN_DECL
|
|||
|
||||
void showMsg(const char *format, ...);
|
||||
char * getInput(char *s, int n, FILE *stream);
|
||||
pj_bool_t showNotification(pjsua_call_id call_id);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -158,6 +158,23 @@ pj_log_func *log_cb = NULL;
|
|||
* Configuration manipulation
|
||||
*/
|
||||
|
||||
#if (defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
|
||||
PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0) || \
|
||||
defined(__IPHONE_4_0)
|
||||
void keepAliveFunction(int timeout)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<(int)pjsua_acc_get_count(); ++i) {
|
||||
if (!pjsua_acc_is_valid(i))
|
||||
continue;
|
||||
|
||||
if (app_config.acc_cfg[i].reg_timeout < timeout)
|
||||
app_config.acc_cfg[i].reg_timeout = timeout;
|
||||
pjsua_acc_set_registration(i, PJ_TRUE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Show usage */
|
||||
static void usage(void)
|
||||
{
|
||||
|
@ -2456,12 +2473,17 @@ static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
|
|||
|
||||
pjsua_call_get_info(call_id, &call_info);
|
||||
|
||||
/* Start ringback */
|
||||
ring_start(call_id);
|
||||
|
||||
if (current_call==PJSUA_INVALID_ID)
|
||||
current_call = call_id;
|
||||
|
||||
#ifdef USE_GUI
|
||||
if (!showNotification(call_id))
|
||||
return;
|
||||
#endif
|
||||
|
||||
/* Start ringback */
|
||||
ring_start(call_id);
|
||||
|
||||
if (app_config.auto_answer > 0) {
|
||||
pjsua_call_answer(call_id, app_config.auto_answer, NULL, NULL);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue