Commit 0740271b authored by jehan's avatar jehan

add IOS section in doxygen

parent 74148020
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
/** /**
* @page liblinphone_license COPYING * @page liblinphone_license COPYING
* @verbinclude COPYING * @include COPYING
*/ */
/** /**
...@@ -196,5 +196,150 @@ void text_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddre ...@@ -196,5 +196,150 @@ void text_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddre
* *
**/ **/
/**
* @defgroup port Portability:
*
**/
/**
* @defgroup IOS IOS
* @ingroup port
*<br>
<b>Multitasking</b>
<br> liblinphone for IOS natively supports multitasking assuming application follows multitasking guides provided by Apple. First step is to declare application as multitasked. It means adding background mode for both audio and voip to Info.plist file.
<br>
\code
<key>UIBackgroundModes</key>
<array>
<string>voip</string>
<string>audio</string>
</array>
\endcode
<br>
<ul>
<li><b>SIP socket </b> Recommanded mode is TCP, because UDP requires keep alives for maintaining NAT association at the IP router level.
Unfortunnatly, UDP keep alives are not possible on IOS. For TCP, liblinphone automatically configures SIP socket for voip (I.E kCFStreamNetworkServiceType set to kCFStreamNetworkServiceTypeVoIP).
For UDP, it is the responsability of application to set this property of the UDP SIP socket before entering in background. For UDP, the application can access the SIP socket from method #linphone_core_get_sip_socket(). Note this property is only settable on a connected socket. As liblinphone UDP socket are not connected, application willing to enable UDP bacground mode must first connect the UDP sip socket before configuring the voip mode. Pseudo code belows show the different steps:
\code
//get sip socket
CFReadStreamRef mReadStream
int sipsock = linphone_core_get_sip_socket(theLinphoneCore);
//get address port of the sip proxy in order to connect the udp socket to this proxy
const char *port;
addr=linphone_address_new(linphone_proxy_config_get_addr(proxyCfg));
memset(&hints,0,sizeof(hints));
hints.ai_family=linphone_core_ipv6_enabled(theLinphoneCore) ? AF_INET6 : AF_INET;
port=linphone_address_get_port(addr);
if (port==NULL) port="5060";
err=getaddrinfo(linphone_address_get_domain(addr),port,&hints,&res);
if (err!=0){
ms_error("getaddrinfo() failed for %s: %s",linphone_address_get_domain(addr),gai_strerror(err));
linphone_address_destroy(addr);
return;
}
//connect the udp socket
err=connect(sipsock,res->ai_addr,res->ai_addrlen);
if (err==-1){
ms_error("Connect failed: %s",strerror(errno));
}
freeaddrinfo(res);
//create CFRead stream from the sip socket id
CFStreamCreatePairWithSocket(NULL, (CFSocketNativeHandle)sipsock, &mReadStream,nil);
//configure for persistante connection
if (!CFReadStreamSetProperty(mReadStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP)) {
ms_error("cannot set service type to voip for read stream");
}
if (!CFReadStreamOpen(mReadStream)) {
ms_error("cannot open read stream");
}
\endcode
<br> Note this operation has to be performed every time the application enters in background mode.
<br> Anyway, for battery saving, UDP background mode is not recomnmanded
<li><b>Entering bacground mode</b>
<br> Before entering in background mode \code - (void)applicationDidEnterBackground:(UIApplication *)application \endcode The application must first refresh sip registration using function #linphone_core_refresh_registers();
and register a Keep alive handler for periodically refreshing registration. The speudo code below show how to register a keep alive handler:
\code
//First refresh registration
linphone_core_refresh_registers(theLinphoneCore);
//wait for registration answer
int i=0;
while (!linphone_proxy_config_is_registered(proxyCfg) && i++<40 ) {
linphone_core_iterate(theLinphoneCore);
usleep(100000);
}
//register keepalive handler
[[UIApplication sharedApplication] setKeepAliveTimeout:600/*minimal interval is 600 s*/
handler:^{
//refresh sip registration
linphone_core_refresh_registers(theLinphoneCore);
//make sure sip REGISTER
linphone_core_iterate(theLinphoneCore);
}];
\endcode
<li><b>Incoming call notification while in background mode</b>
<br>Assuming application using liblinphone is well configured for multitasking, incoming calls arriving while liblinphone is in background mode will simply wakeup liblinphone thread but not resume GUI. To wakeup GUI, it is recommanded to send a Local Notification to the user from the #LinphoneCallStateCb. Here under a speudo code for this operation:
\code
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
// Create a new notification
UILocalNotification* notif = [[[UILocalNotification alloc] init] autorelease];
if (notif) {
notif.repeatInterval = 0;
notif.alertBody =@"New incoming call";
notif.alertAction = @"Answer";
notif.soundName = @"oldphone-mono-30s.caf";
[[UIApplication sharedApplication] presentLocalNotificationNow:notif];
}
\endcode
</ul>
<b>Networking</b>
<br>
<ul><li><b>WWAN connection</b>
<br>liblinphone relies on bsd socket for sip/rtp networking. On IOS, WWAN connection is supposed to automatically setup on any networking resquest issued by an application. At least on iPhone OS 3.x, BSD sockets do not automaticaly bring up the WWAN interface. So it is recommanded to add a special code to make sure the WWAN connection is properly setup. Speudo code belows describe a way to force WWAN connection.
\code
/*start a new thread to avoid blocking the main ui in case of peer host failure*/
[NSThread detachNewThreadSelector:@selector(runNetworkConnection) toTarget:self withObject:nil];
-(void) runNetworkConnection {
CFWriteStreamRef writeStream;
//create a dummy socket
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"192.168.0.200", 15000, nil, &writeStream);
CFWriteStreamOpen (writeStream);
const char* buff="hello";
//try to write on this socket
CFWriteStreamWrite (writeStream,(const UInt8*)buff,strlen(buff));
CFWriteStreamClose (writeStream);
}
\endcode
It is recommanded to perform this task each time the application is waked up, including keep alive handler.
<li><b>Managing IP connection state</b>
<br>liblinphone for IOS relies on the application to be informed of network changes. Network state change when the IP connection move from DOWN to UP, or from WIFI to WWAN. Applications using liblinphone must inform libliblinphone of this changes using function #linphone_core_set_network_reachable(). Usually this method is called from the IOS NetworkReachability callback. Here under a sample code:
\code
//typical reachability callback
void networkReachabilityCallBack(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void * info) {
if ((flags == 0) | (flags & (kSCNetworkReachabilityFlagsConnectionRequired |kSCNetworkReachabilityFlagsConnectionOnTraffic))) {
//network state is off
linphone_core_set_network_reachable(lc,false);
((LinphoneManager*)info).connectivity = none;
} else {
Connectivity newConnectivity = flags & kSCNetworkReachabilityFlagsIsWWAN ? wwan:wifi;
if (lLinphoneMgr.connectivity == none) {
//notify new network state
linphone_core_set_network_reachable(lc,true);
} else if (lLinphoneMgr.connectivity != newConnectivity) {
// connectivity has changed
linphone_core_set_network_reachable(lc,false);
linphone_core_set_network_reachable(lc,true);
}
//store new connectivity status
lLinphoneMgr.connectivity=newConnectivity;
}
}
}
\endcode
</ul>
<b>DTMF feebacks</b>
<br>liblinphone provides functions \link #linphone_core_play_dtmf() to play dtmf \endlink . Usually this is used to play a sound when the a user type a digit. On IOS, libLinphone relies on Audio unit for interfacing with the audio system. Audio unit initialization is a quit long operation that may trigger a bad user experience if performed each time a DTMF is played. On IOS, liblinphone introduce 2 functions for \link linphone_core_start_dtmf_stream() preloading \endlink \link #linphone_core_start_dtmf_stream() unloading \endlink underlying audio graph responsible of playing DTMFs.
<br> For application using function #linphone_core_play_dtmf() , it is recommanded to call #linphone_core_start_dtmf_stream() when entering in foreground and #linphone_core_stop_dtmf_stream() upon entering background mode.
*/
...@@ -3583,7 +3583,11 @@ static MSFilter *get_dtmf_gen(LinphoneCore *lc){ ...@@ -3583,7 +3583,11 @@ static MSFilter *get_dtmf_gen(LinphoneCore *lc){
} }
/** /**
* Plays a dtmf to the local user. * @ingroup media_parameters
* Plays a dtmf sound to the local user.
* @param lc #LinphoneCore
* @param dtmf DTMF to play ['0'..'16'] | '#' | '#'
* @param duration_ms duration in ms, -1 means play until next further call to #linphone_core_stop_dtmf()
**/ **/
void linphone_core_play_dtmf(LinphoneCore *lc, char dtmf, int duration_ms){ void linphone_core_play_dtmf(LinphoneCore *lc, char dtmf, int duration_ms){
MSFilter *f=get_dtmf_gen(lc); MSFilter *f=get_dtmf_gen(lc);
...@@ -3598,6 +3602,8 @@ void linphone_core_play_dtmf(LinphoneCore *lc, char dtmf, int duration_ms){ ...@@ -3598,6 +3602,8 @@ void linphone_core_play_dtmf(LinphoneCore *lc, char dtmf, int duration_ms){
} }
/** /**
* @ingroup media_parameters
*
* Stops playing a dtmf started by linphone_core_play_dtmf(). * Stops playing a dtmf started by linphone_core_play_dtmf().
**/ **/
void linphone_core_stop_dtmf(LinphoneCore *lc){ void linphone_core_stop_dtmf(LinphoneCore *lc){
......
...@@ -787,7 +787,12 @@ int linphone_core_get_sip_port(LinphoneCore *lc); ...@@ -787,7 +787,12 @@ int linphone_core_get_sip_port(LinphoneCore *lc);
int linphone_core_set_sip_transports(LinphoneCore *lc, const LCSipTransports *transports); int linphone_core_set_sip_transports(LinphoneCore *lc, const LCSipTransports *transports);
int linphone_core_get_sip_transports(LinphoneCore *lc, LCSipTransports *transports); int linphone_core_get_sip_transports(LinphoneCore *lc, LCSipTransports *transports);
/**
* @ingroup IOS
* Give access to the UDP sip socket. Can be useful to configure this socket as persistent I.E kCFStreamNetworkServiceType set to kCFStreamNetworkServiceTypeVoIP)
* @param lc #LinphoneCore
* @return socket file descriptor
*/
ortp_socket_t linphone_core_get_sip_socket(LinphoneCore *lc); ortp_socket_t linphone_core_get_sip_socket(LinphoneCore *lc);
void linphone_core_set_inc_timeout(LinphoneCore *lc, int seconds); void linphone_core_set_inc_timeout(LinphoneCore *lc, int seconds);
...@@ -927,6 +932,7 @@ int linphone_core_get_mtu(const LinphoneCore *lc); ...@@ -927,6 +932,7 @@ int linphone_core_get_mtu(const LinphoneCore *lc);
void linphone_core_set_mtu(LinphoneCore *lc, int mtu); void linphone_core_set_mtu(LinphoneCore *lc, int mtu);
/** /**
* @ingroup network_parameters
* This method is called by the application to notify the linphone core library when network is reachable. * This method is called by the application to notify the linphone core library when network is reachable.
* Calling this method with true trigger linphone to initiate a registration process for all proxy * Calling this method with true trigger linphone to initiate a registration process for all proxy
* configuration with parameter register set to enable. * configuration with parameter register set to enable.
...@@ -935,15 +941,18 @@ void linphone_core_set_mtu(LinphoneCore *lc, int mtu); ...@@ -935,15 +941,18 @@ void linphone_core_set_mtu(LinphoneCore *lc, int mtu);
*/ */
void linphone_core_set_network_reachable(LinphoneCore* lc,bool_t value); void linphone_core_set_network_reachable(LinphoneCore* lc,bool_t value);
/** /**
* @ingroup network_parameters
* return network state either as positioned by the application or by linphone * return network state either as positioned by the application or by linphone
*/ */
bool_t linphone_core_is_network_reachabled(LinphoneCore* lc); bool_t linphone_core_is_network_reachabled(LinphoneCore* lc);
/** /**
* @ingroup network_parameters
* enable signaling keep alive. small udp packet sent periodically to keep udp NAT association * enable signaling keep alive. small udp packet sent periodically to keep udp NAT association
*/ */
void linphone_core_enable_keep_alive(LinphoneCore* lc,bool_t enable); void linphone_core_enable_keep_alive(LinphoneCore* lc,bool_t enable);
/** /**
* @ingroup network_parameters
* Is signaling keep alive * Is signaling keep alive
*/ */
bool_t linphone_core_keep_alive_enabled(LinphoneCore* lc); bool_t linphone_core_keep_alive_enabled(LinphoneCore* lc);
......
...@@ -65,19 +65,20 @@ typedef enum { ...@@ -65,19 +65,20 @@ typedef enum {
typedef void (*LinphoneEcCalibrationCallback)(LinphoneCore *lc, LinphoneEcCalibratorStatus status, int delay_ms, void *data); typedef void (*LinphoneEcCalibrationCallback)(LinphoneCore *lc, LinphoneEcCalibratorStatus status, int delay_ms, void *data);
/** /**
*
* Start an echo calibration of the sound devices, in order to find adequate settings for the echo canceller automatically. * Start an echo calibration of the sound devices, in order to find adequate settings for the echo canceller automatically.
**/ **/
int linphone_core_start_echo_calibration(LinphoneCore *lc, LinphoneEcCalibrationCallback cb, void *cb_data); int linphone_core_start_echo_calibration(LinphoneCore *lc, LinphoneEcCalibrationCallback cb, void *cb_data);
#if TARGET_OS_IPHONE
/** /**
* IOS special function to warm up dtmf feeback stream. #linphone_core_stop_dtmf_stream must be called before entering BG mode * @ingroup IOS
* Special function to warm up dtmf feeback stream. #linphone_core_stop_dtmf_stream must() be called before entering FG mode
*/ */
void linphone_core_start_dtmf_stream(const LinphoneCore* lc); void linphone_core_start_dtmf_stream(LinphoneCore* lc);
/** /**
* IOS special function to stop dtmf feed back function. Must be called before entering BG mode * @ingroup IOS
* Special function to stop dtmf feed back function. Must be called before entering BG mode
*/ */
void linphone_core_stop_dtmf_stream(const LinphoneCore* lc); void linphone_core_stop_dtmf_stream(LinphoneCore* lc);
#endif
#ifdef __cplusplus #ifdef __cplusplus
......
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