Merge branch 'master' of git.linphone.org:linphone

This commit is contained in:
Ghislain MARY 2012-09-19 18:00:45 +02:00
commit 49b1b61b5a
25 changed files with 1980 additions and 1264 deletions

View file

@ -61,7 +61,7 @@ case $target in
CONSOLE_FLAGS="-mconsole"
mingw_found=yes
;;
armv6-apple-darwin|armv7-apple-darwin|i386-apple-darwin)
armv6-apple-darwin|armv7-apple-darwin|i386-apple-darwin|armv7s-apple-darwin)
CFLAGS="$CFLAGS -DTARGET_OS_IPHONE "
build_tests=no
ios_found=yes

View file

@ -212,7 +212,6 @@ TunnelManager::TunnelManager(LinphoneCore* lc) :TunnelClientController()
mExosipTransport.recvfrom=eXosipRecvfrom;
mExosipTransport.sendto=eXosipSendto;
mExosipTransport.select=eXosipSelect;
mStateChanged=false;
linphone_core_add_iterate_hook(mCore,(LinphoneCoreIterateHook)sOnIterate,this);
mTransportFactories.audio_rtcp_func=sCreateRtpTransport;
mTransportFactories.audio_rtcp_func_data=this;
@ -242,12 +241,13 @@ void TunnelManager::stopClient(){
}
}
void TunnelManager::processTunnelEvent(){
void TunnelManager::processTunnelEvent(const Event &ev){
LinphoneProxyConfig* lProxy;
linphone_core_get_default_proxy(mCore, &lProxy);
if (mEnabled && mTunnelClient->isReady()){
ms_message("Tunnel is up, registering now");
ms_message("Tunnel is up, registering now");
linphone_core_set_firewall_policy(mCore,LinphonePolicyNoFirewall);
linphone_core_set_rtp_transport_factories(mCore,&mTransportFactories);
eXosip_transport_hook_register(&mExosipTransport);
//force transport to udp
@ -296,8 +296,9 @@ void TunnelManager::enable(bool isEnable) {
ms_message("Turning tunnel [%s]",(isEnable?"on":"off"));
if (isEnable && !mEnabled){
mEnabled=true;
//1 save transport
//1 save transport and firewall policy
linphone_core_get_sip_transports(mCore, &mRegularTransport);
mPreviousFirewallPolicy=linphone_core_get_firewall_policy(mCore);
//2 unregister
waitUnRegistration();
//3 insert tunnel
@ -312,8 +313,9 @@ void TunnelManager::enable(bool isEnable) {
linphone_core_set_rtp_transport_factories(mCore,NULL);
eXosip_transport_hook_register(NULL);
//Restore transport
//Restore transport and firewall policy
linphone_core_set_sip_transports(mCore, &mRegularTransport);
linphone_core_set_firewall_policy(mCore, mPreviousFirewallPolicy);
//register
LinphoneProxyConfig* lProxy;
linphone_core_get_default_proxy(mCore, &lProxy);
@ -325,15 +327,31 @@ void TunnelManager::enable(bool isEnable) {
}
void TunnelManager::tunnelCallback(bool connected, TunnelManager *zis){
zis->mStateChanged=true;
Event ev;
ev.mType=TunnelEvent;
ev.mData.mConnected=connected;
zis->postEvent(ev);
}
void TunnelManager::onIterate(){
mMutex.lock();
while(!mEvq.empty()){
Event ev=mEvq.front();
mEvq.pop();
mMutex.unlock();
if (ev.mType==TunnelEvent)
processTunnelEvent(ev);
else if (ev.mType==UdpMirrorClientEvent){
processUdpMirrorEvent(ev);
}
mMutex.lock();
}
mMutex.unlock();
}
/*invoked from linphone_core_iterate() */
void TunnelManager::sOnIterate(TunnelManager *zis){
if (zis->mStateChanged){
zis->mStateChanged=false;
zis->processTunnelEvent();
}
zis->onIterate();
}
#ifdef ANDROID
@ -374,26 +392,39 @@ void TunnelManager::enableLogs(bool isEnabled,LogHandler logHandler) {
bool TunnelManager::isEnabled() {
return mEnabled;
}
void TunnelManager::UdpMirrorClientListener(bool isUdpAvailable, void* data) {
TunnelManager* thiz = (TunnelManager*)data;
if (isUdpAvailable) {
void TunnelManager::processUdpMirrorEvent(const Event &ev){
if (ev.mData.mHaveUdp) {
LOGI("Tunnel is not required, disabling");
thiz->enable(false);
thiz->mAutoDetectStarted = false;
enable(false);
mAutoDetectStarted = false;
} else {
if (++thiz->mCurrentUdpMirrorClient !=thiz->mUdpMirrorClients.end()) {
//1 enable tunnable but also try backup server
if (mCurrentUdpMirrorClient !=mUdpMirrorClients.end()) {
// enable tunnel but also try backup server
LOGI("Tunnel is required, enabling; Trying backup udp mirror");
UdpMirrorClient &lUdpMirrorClient=*thiz->mCurrentUdpMirrorClient;
lUdpMirrorClient.start(TunnelManager::UdpMirrorClientListener,(void*)thiz);
UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient;
lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this);
} else {
LOGI("Tunnel is required, enabling; no backup udp mirror available");
thiz->mAutoDetectStarted = false;
mAutoDetectStarted = false;
}
thiz->enable(true);
enable(true);
}
return;
}
void TunnelManager::postEvent(const Event &ev){
mMutex.lock();
mEvq.push(ev);
mMutex.unlock();
}
void TunnelManager::sUdpMirrorClientCallback(bool isUdpAvailable, void* data) {
TunnelManager* thiz = (TunnelManager*)data;
Event ev;
ev.mType=UdpMirrorClientEvent;
ev.mData.mHaveUdp=isUdpAvailable;
thiz->postEvent(ev);
}
void TunnelManager::autoDetect() {
@ -409,7 +440,7 @@ void TunnelManager::autoDetect() {
mAutoDetectStarted=true;
mCurrentUdpMirrorClient =mUdpMirrorClients.begin();
UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient;
lUdpMirrorClient.start(TunnelManager::UdpMirrorClientListener,(void*)this);
lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this);
}

View file

@ -130,9 +130,21 @@ class UdpMirrorClient;
LinphoneCore *getLinphoneCore();
virtual void setHttpProxy(const char *host,int port, const char *username, const char *passwd);
private:
enum EventType{
UdpMirrorClientEvent,
TunnelEvent,
};
struct Event{
EventType mType;
union EventData{
bool mConnected;
bool mHaveUdp;
}mData;
};
typedef std::list<UdpMirrorClient> UdpMirrorClientList;
virtual bool isStarted();
virtual bool isReady() const;
void onIterate();
static int customSendto(struct _RtpTransport *t, mblk_t *msg , int flags, const struct sockaddr *to, socklen_t tolen);
static int customRecvfrom(struct _RtpTransport *t, mblk_t *msg, int flags, struct sockaddr *from, socklen_t *fromlen);
static int eXosipSendto(int fd,const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen,void* userdata);
@ -140,9 +152,11 @@ class UdpMirrorClient;
static int eXosipSelect(int nfds, fd_set *s1, fd_set *s2, fd_set *s3, struct timeval *tv,void* userdata);
static void tunnelCallback(bool connected, TunnelManager *zis);
static void sOnIterate(TunnelManager *zis);
static void UdpMirrorClientListener(bool result, void* data);
static void sUdpMirrorClientCallback(bool result, void* data);
void waitUnRegistration();
void processTunnelEvent();
void processTunnelEvent(const Event &ev);
void processUdpMirrorEvent(const Event &ev);
void postEvent(const Event &ev);
LinphoneCore* mCore;
LCSipTransports mRegularTransport;
TunnelSocket *mSipSocket;
@ -150,19 +164,21 @@ class UdpMirrorClient;
StateCallback mCallback;
void * mCallbackData;
bool mEnabled;
bool mStateChanged;
std::queue<Event> mEvq;
std::list <ServerAddr> mServerAddrs;
UdpMirrorClientList mUdpMirrorClients;
UdpMirrorClientList::iterator mCurrentUdpMirrorClient;
TunnelClient* mTunnelClient;
void stopClient();
Mutex mMutex;
static Mutex sMutex;
bool mAutoDetectStarted;
LinphoneRtpTransportFactories mTransportFactories;
std::string mHttpUserName;
std::string mHttpPasswd;
std::string mHttpProxyHost;
int mHttpProxyPort;
int mHttpProxyPort;
LinphoneFirewallPolicy mPreviousFirewallPolicy;
};
/**

View file

@ -20,6 +20,7 @@ package org.linphone.core.tutorials;
import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneChatMessage;
import org.linphone.core.LinphoneChatRoom;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
@ -231,5 +232,11 @@ public class TutorialBuddyStatus implements LinphoneCoreListener {
TutorialNotifier.notify(s);
}
@Override
public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr, LinphoneChatMessage message) {
// TODO Auto-generated method stub
}
}

View file

@ -20,6 +20,7 @@ package org.linphone.core.tutorials;
import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneChatMessage;
import org.linphone.core.LinphoneChatRoom;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
@ -146,5 +147,12 @@ public class TutorialChatRoom implements LinphoneCoreListener {
TutorialNotifier.notify(s);
}
@Override
public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr,
LinphoneChatMessage message) {
// TODO Auto-generated method stub
}
}

View file

@ -20,6 +20,7 @@ package org.linphone.core.tutorials;
import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneChatMessage;
import org.linphone.core.LinphoneChatRoom;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
@ -156,5 +157,12 @@ public class TutorialHelloWorld implements LinphoneCoreListener {
TutorialNotifier.notify(s);
}
@Override
public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr,
LinphoneChatMessage message) {
// TODO Auto-generated method stub
}
}

View file

@ -20,6 +20,7 @@ package org.linphone.core.tutorials;
import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneChatMessage;
import org.linphone.core.LinphoneChatRoom;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
@ -187,6 +188,13 @@ public class TutorialRegistration implements LinphoneCoreListener {
TutorialNotifier.notify(s);
}
@Override
public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr,
LinphoneChatMessage message) {
// TODO Auto-generated method stub
}
}

View file

@ -173,17 +173,26 @@ void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel){
bcTunnel(tunnel)->autoDetect();
}
static void tunnel_add_servers_from_config(LinphoneTunnel *tunnel, char* confaddress){
char *str1;
for(str1=confaddress;;str1=NULL){
char *port;
char *address=strtok(str1," "); // Not thread safe
if (!address) break;
port=strchr(address, ':');
if (!port) ms_fatal("Bad tunnel address %s",confaddress);
*port++='\0';
linphone_tunnel_add_server(tunnel, address, atoi(port));
}
static void tunnel_add_servers_from_config(LinphoneTunnel *tunnel, const char* confaddress){
char *tmp=(char*)ms_malloc0(strlen(confaddress)+1);
const char *it=confaddress;
int adv;
do{
int ret=sscanf(it,"%s%n",tmp,&adv);
if (ret>=1){
it+=adv;
char *port=strchr(tmp,':');
if (!port){
ms_error("Tunnel server addresses incorrectly specified from config file: %s",it);
break;
}else{
*port='\0';
port++;
bcTunnel(tunnel)->addServer(tmp, atoi(port));
}
}else break;
}while(1);
ms_free(tmp);
}
static void my_ortp_logv(OrtpLogLevel level, const char *fmt, va_list args){
@ -197,13 +206,9 @@ static void my_ortp_logv(OrtpLogLevel level, const char *fmt, va_list args){
void linphone_tunnel_configure(LinphoneTunnel *tunnel){
bool_t enabled=(bool_t)lp_config_get_int(config(tunnel),"tunnel","enabled",FALSE);
const char* addresses=lp_config_get_string(config(tunnel),"tunnel","server_addresses", NULL);
char *copy=addresses ? ms_strdup(addresses) : NULL;
linphone_tunnel_enable_logs_with_handler(tunnel,TRUE,my_ortp_logv);
linphone_tunnel_clean_servers(tunnel);
if (copy){
tunnel_add_servers_from_config(tunnel,copy);
ms_free(copy);
}
if (addresses)
tunnel_add_servers_from_config(tunnel,addresses);
linphone_tunnel_enable(tunnel, enabled);
}

View file

@ -62,10 +62,10 @@ void linphone_tunnel_add_server(LinphoneTunnel *tunnel, const char *host, int po
* @param tunnel object
* @param host tunnel server ip address
* @param port tunnel server tls port, recommended value is 443
* @param remote_udp_mirror remote port on the tunnel server side used to test udp reachability
* @param remote_udp_mirror_port remote port on the tunnel server side used to test udp reachability
* @param delay udp packet round trip delay in ms considered as acceptable. recommended value is 1000 ms.
*/
void linphone_tunnel_add_server_and_mirror(LinphoneTunnel *tunnel, const char *host, int port, int remote_udp_mirror, int delay);
void linphone_tunnel_add_server_and_mirror(LinphoneTunnel *tunnel, const char *host, int port, int remote_udp_mirror_port, int delay);
/**
* @param tunnel object
* returns a string of space separated list of host:port of tunnel server addresses
@ -98,16 +98,37 @@ bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel);
**/
void linphone_tunnel_reconnect(LinphoneTunnel *tunnel);
/**
* Start tunnel need detection.
* @param tunnel object
* In auto detect mode, the tunnel manager try to establish a real time rtp cummunication with the tunnel server on specified port.
*<br>In case of success, the tunnel is automatically turned off. Otherwise, if no udp commmunication is feasible, tunnel mode is turned on.
*<br> Call this method each time to run the auto detection algorithm
*/
void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel);
/**
* Set an optional http proxy to go through when connecting to tunnel server.
* @param tunnel LinphoneTunnel object
* @param host Http proxy host.
* @param port http proxy port.
* @param username optional http proxy username if the proxy request authentication. Currently only basic authentication is supported. Use NULL if not needed.
* @param password optional http proxy password. Use NULL if not needed.
**/
void linphone_tunnel_set_http_proxy(LinphoneTunnel *tunnel, const char *host, int port, const char* username,const char* passwd);
void linphone_tunnel_set_http_proxy_auth_info(LinphoneTunnel*tunnel, const char* username,const char* passwd);
/**
* Retrieve optional http proxy configuration previously set with linphone_tunnel_set_http_proxy().
* @param tunnel LinphoneTunnel object
* @param host Http proxy host.
* @param port http proxy port.
* @param username optional http proxy username if the proxy request authentication. Currently only basic authentication is supported. Use NULL if not needed.
* @param password optional http proxy password. Use NULL if not needed.
**/
void linphone_tunnel_get_http_proxy(LinphoneTunnel*tunnel,const char **host, int *port, const char **username, const char **passwd);
void linphone_tunnel_set_http_proxy_auth_info(LinphoneTunnel*tunnel, const char* username,const char* passwd);
void linphone_tunnel_enable_logs(LinphoneTunnel *tunnel, bool_t enabled);
/**

View file

@ -1732,12 +1732,17 @@ const LinphoneCallStats *linphone_call_get_video_stats(const LinphoneCall *call)
* @}
**/
static void display_bandwidth(RtpSession *as, RtpSession *vs){
static void report_bandwidth(LinphoneCall *call, RtpSession *as, RtpSession *vs){
call->stats[LINPHONE_CALL_STATS_AUDIO].download_bandwidth=(as!=NULL) ? (rtp_session_compute_recv_bandwidth(as)*1e-3) : 0;
call->stats[LINPHONE_CALL_STATS_AUDIO].upload_bandwidth=(as!=NULL) ? (rtp_session_compute_send_bandwidth(as)*1e-3) : 0;
call->stats[LINPHONE_CALL_STATS_VIDEO].download_bandwidth=(vs!=NULL) ? (rtp_session_compute_recv_bandwidth(vs)*1e-3) : 0;
call->stats[LINPHONE_CALL_STATS_VIDEO].upload_bandwidth=(vs!=NULL) ? (rtp_session_compute_send_bandwidth(vs)*1e-3) : 0;
ms_message("bandwidth usage: audio=[d=%.1f,u=%.1f] video=[d=%.1f,u=%.1f] kbit/sec",
(as!=NULL) ? (rtp_session_compute_recv_bandwidth(as)*1e-3) : 0,
(as!=NULL) ? (rtp_session_compute_send_bandwidth(as)*1e-3) : 0,
(vs!=NULL) ? (rtp_session_compute_recv_bandwidth(vs)*1e-3) : 0,
(vs!=NULL) ? (rtp_session_compute_send_bandwidth(vs)*1e-3) : 0);
call->stats[LINPHONE_CALL_STATS_AUDIO].download_bandwidth,
call->stats[LINPHONE_CALL_STATS_AUDIO].upload_bandwidth ,
call->stats[LINPHONE_CALL_STATS_VIDEO].download_bandwidth,
call->stats[LINPHONE_CALL_STATS_VIDEO].upload_bandwidth
);
}
static void linphone_core_disconnected(LinphoneCore *lc, LinphoneCall *call){
@ -1769,7 +1774,6 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
if (ice_session_role(call->ice_session) == IR_Controlling) {
ice_session_select_candidates(call->ice_session);
linphone_core_update_call(call->core, call, &call->current_params);
linphone_core_update_ice_state_in_call_stats(call);
}
break;
case IS_Failed:
@ -1778,13 +1782,13 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
/* At least one ICE session has succeeded, so perform a call update. */
ice_session_select_candidates(call->ice_session);
linphone_core_update_call(call->core, call, &call->current_params);
linphone_core_update_ice_state_in_call_stats(call);
}
}
break;
default:
break;
}
linphone_core_update_ice_state_in_call_stats(call);
} else if (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) {
int ping_time = -1;
if (evd->info.ice_processing_successful==TRUE) {
@ -1848,7 +1852,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse
video_load=ms_ticker_get_average_load(call->videostream->ticker);
vs=call->videostream->session;
}
display_bandwidth(as,vs);
report_bandwidth(call,as,vs);
ms_message("Thread processing load: audio=%f\tvideo=%f",audio_load,video_load);
}
#ifdef VIDEO_ENABLED

View file

@ -844,6 +844,7 @@ static void video_config_read(LinphoneCore *lc){
ms_message("we are using a specific display:%s\n",lc->video_conf.displaytype);
linphone_core_enable_video(lc,capture,display);
linphone_core_enable_video_preview(lc,lp_config_get_int(lc->config,"video","show_local",0));
linphone_core_enable_self_view(lc,self_view);
linphone_core_set_video_policy(lc,&vpol);
#endif
@ -4095,6 +4096,8 @@ void linphone_core_set_native_preview_window_id(LinphoneCore *lc, unsigned long
LinphoneCall *call=linphone_core_get_current_call(lc);
if (call!=NULL && call->videostream){
video_stream_set_native_preview_window_id(call->videostream,id);
}else if (lc->previewstream){
video_preview_set_native_window_id(lc->previewstream,id);
}
#endif
}

View file

@ -267,6 +267,7 @@ typedef struct _LinphoneCall LinphoneCall;
**/
enum _LinphoneIceState{
LinphoneIceStateNotActivated, /**< ICE has not been activated for this call */
LinphoneIceStateFailed, /**< ICE processing has failed */
LinphoneIceStateInProgress, /**< ICE process is in progress */
LinphoneIceStateHostConnection, /**< ICE has established a direct connection to the remote host */
LinphoneIceStateReflexiveConnection, /**< ICE has established a connection to the remote host through one or several NATs */
@ -304,6 +305,8 @@ struct _LinphoneCallStats {
mblk_t* sent_rtcp;/**<Last RTCP packet sent, as a mblk_t structure. See oRTP documentation for details how to extract information from it*/
float round_trip_delay; /**<Round trip propagation time in seconds if known, -1 if unknown.*/
LinphoneIceState ice_state; /**< State of ICE processing. */
float download_bandwidth; /**<Download bandwidth measurement of received stream, expressed in kbit/s, including IP/UDP/RTP headers*/
float upload_bandwidth; /**<Download bandwidth measurement of sent stream, expressed in kbit/s, including IP/UDP/RTP headers*/
};
/**

View file

@ -152,7 +152,7 @@ public:
/*void textReceived(LinphoneCore lc, LinphoneChatRoom cr,LinphoneAddress from,String message);*/
textReceivedId = env->GetMethodID(listenerClass,"textReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatRoom;Lorg/linphone/core/LinphoneAddress;Ljava/lang/String;)V");
messageReceivedId = env->GetMethodID(listenerClass,"messageReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatRoom;Lorg/linphone/core/LinphoneAddress;Lorg/linphone/core/LinphoneChatMessage;)V");
messageReceivedId = env->GetMethodID(listenerClass,"messageReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatRoom;Lorg/linphone/core/LinphoneChatMessage;)V");
proxyClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneProxyConfigImpl"));
proxyCtrId = env->GetMethodID(proxyClass,"<init>", "(J)V");
@ -161,7 +161,7 @@ public:
callCtrId = env->GetMethodID(callClass,"<init>", "(J)V");
chatMessageClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneChatMessageImpl"));
chatMessageCtrId = env->GetMethodID(chatMessageClass,"<init>", "(J)V");
if (chatMessageClass) chatMessageCtrId = env->GetMethodID(chatMessageClass,"<init>", "(J)V");
chatRoomClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneChatRoomImpl"));
chatRoomCtrId = env->GetMethodID(chatRoomClass,"<init>", "(J)V");
@ -402,7 +402,6 @@ public:
,lcData->messageReceivedId
,lcData->core
,env->NewObject(lcData->chatRoomClass,lcData->chatRoomCtrId,(jlong)room)
,env->NewObject(lcData->addressClass,lcData->addressCtrId,(jlong)msg->from)
,env->NewObject(lcData->chatMessageClass,lcData->chatMessageCtrId,(jlong)msg));
}
static void ecCalibrationStatus(LinphoneCore *lc, LinphoneEcCalibratorStatus status, int delay_ms, void *data) {
@ -1426,10 +1425,15 @@ extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_setExternalBodyUr
linphone_chat_message_set_external_body_url((LinphoneChatMessage *)ptr, url);
env->ReleaseStringUTFChars(jurl, url);
}
extern "C" long Java_org_linphone_core_LinphoneChatMessageImpl_getPeerAddress(JNIEnv* env
extern "C" jlong Java_org_linphone_core_LinphoneChatMessageImpl_getFrom(JNIEnv* env
,jobject thiz
,jlong ptr) {
return (long) linphone_chat_message_get_peer_address((LinphoneChatMessage*)ptr);
return (jlong) linphone_chat_message_get_from((LinphoneChatMessage*)ptr);
}
extern "C" jlong Java_org_linphone_core_LinphoneChatMessageImpl_getPeerAddress(JNIEnv* env
,jobject thiz
,jlong ptr) {
return (jlong) linphone_chat_message_get_peer_address((LinphoneChatMessage*)ptr);
}
extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_sendMessage(JNIEnv* env
,jobject thiz

View file

@ -641,37 +641,46 @@ void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call)
{
IceCheckList *audio_check_list;
IceCheckList *video_check_list;
IceSessionState session_state;
if (call->ice_session == NULL) return;
audio_check_list = ice_session_check_list(call->ice_session, 0);
video_check_list = ice_session_check_list(call->ice_session, 1);
if (audio_check_list == NULL) return;
switch (ice_check_list_selected_valid_candidate_type(audio_check_list)) {
case ICT_HostCandidate:
call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateHostConnection;
break;
case ICT_ServerReflexiveCandidate:
case ICT_PeerReflexiveCandidate:
call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateReflexiveConnection;
break;
case ICT_RelayedCandidate:
call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateRelayConnection;
break;
}
if (call->params.has_video && (video_check_list != NULL)) {
switch (ice_check_list_selected_valid_candidate_type(video_check_list)) {
session_state = ice_session_state(call->ice_session);
if ((session_state == IS_Completed) || ((session_state == IS_Failed) && (ice_session_has_completed_check_list(call->ice_session) == TRUE))) {
switch (ice_check_list_selected_valid_candidate_type(audio_check_list)) {
case ICT_HostCandidate:
call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateHostConnection;
call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateHostConnection;
break;
case ICT_ServerReflexiveCandidate:
case ICT_PeerReflexiveCandidate:
call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateReflexiveConnection;
call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateReflexiveConnection;
break;
case ICT_RelayedCandidate:
call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateRelayConnection;
call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateRelayConnection;
break;
}
if (call->params.has_video && (video_check_list != NULL)) {
switch (ice_check_list_selected_valid_candidate_type(video_check_list)) {
case ICT_HostCandidate:
call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateHostConnection;
break;
case ICT_ServerReflexiveCandidate:
case ICT_PeerReflexiveCandidate:
call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateReflexiveConnection;
break;
case ICT_RelayedCandidate:
call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateRelayConnection;
break;
}
}
} else {
call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateFailed;
if (call->params.has_video && (video_check_list != NULL)) {
call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateFailed;
}
}
}
@ -685,8 +694,12 @@ void linphone_core_update_local_media_description_from_ice(SalMediaDescription *
if (session_state == IS_Completed) {
desc->ice_completed = TRUE;
ice_check_list_selected_valid_local_candidate(ice_session_check_list(session, 0), &rtp_addr, NULL, NULL, NULL);
strncpy(desc->addr, rtp_addr, sizeof(desc->addr));
result = ice_check_list_selected_valid_local_candidate(ice_session_check_list(session, 0), &rtp_addr, NULL, NULL, NULL);
if (result == TRUE) {
strncpy(desc->addr, rtp_addr, sizeof(desc->addr));
} else {
ms_warning("If ICE has completed successfully, rtp_addr should be set!");
}
}
else {
desc->ice_completed = FALSE;
@ -879,6 +892,10 @@ void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call,
ice_session_remove_check_list(call->ice_session, ice_session_check_list(call->ice_session, i - 1));
}
ice_session_check_mismatch(call->ice_session);
} else {
/* Response from remote does not contain mandatory ICE attributes, delete the session. */
linphone_call_delete_ice_session(call);
return;
}
if (ice_session_nb_check_lists(call->ice_session) == 0) {
linphone_call_delete_ice_session(call);

View file

@ -10,7 +10,8 @@ UI_FILES= about.ui \
buddylookup.ui \
tunnel_config.ui \
waiting.ui \
dscp_settings.ui
dscp_settings.ui \
call_statistics.ui
PIXMAPS= \
stock_people.png

212
gtk/call_statistics.ui Normal file
View file

@ -0,0 +1,212 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.24"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkDialog" id="call_statistics">
<property name="can_focus">False</property>
<property name="border_width">5</property>
<property name="title" translatable="yes">Call statistics</property>
<property name="type_hint">dialog</property>
<signal name="response" handler="linphone_gtk_call_statistics_closed" swapped="no"/>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkHButtonBox" id="dialog-action_area1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<placeholder/>
</child>
<child>
<object class="GtkButton" id="button1">
<property name="label">gtk-close</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="frame1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="left_padding">12</property>
<child>
<object class="GtkTable" id="table1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="n_rows">6</property>
<property name="n_columns">2</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkLabel" id="audio_codec_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Audio codec</property>
</object>
<packing>
<property name="x_options"></property>
</packing>
</child>
<child>
<object class="GtkLabel" id="video_codec_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Video codec</property>
</object>
<packing>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
<property name="x_options"></property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Audio IP bandwidth usage</property>
</object>
<packing>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
<property name="x_options"></property>
</packing>
</child>
<child>
<object class="GtkLabel" id="audio_codec">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="video_codec">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">1</property>
<property name="bottom_attach">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="audio_bandwidth_usage">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">2</property>
<property name="bottom_attach">3</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Media connectivity</property>
</object>
<packing>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
<property name="x_options"></property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<object class="GtkLabel" id="media_connectivity">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">4</property>
<property name="bottom_attach">5</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Video IP bandwidth usage</property>
</object>
<packing>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
<property name="x_options"></property>
</packing>
</child>
<child>
<object class="GtkLabel" id="video_bandwidth_usage">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">3</property>
<property name="bottom_attach">4</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="call_statistics_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;b&gt;Call statistics and information&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="0">button1</action-widget>
</action-widgets>
</object>
</interface>

View file

@ -193,6 +193,100 @@ void linphone_gtk_enable_conference_button(LinphoneCore *lc, gboolean value){
}
}
static void show_used_codecs(GtkWidget *callstats, LinphoneCall *call){
const LinphoneCallParams *params=linphone_call_get_current_params(call);
if (params){
const PayloadType *acodec=linphone_call_params_get_used_audio_codec(params);
const PayloadType *vcodec=linphone_call_params_get_used_video_codec(params);
GtkWidget *acodec_ui=linphone_gtk_get_widget(callstats,"audio_codec");
GtkWidget *vcodec_ui=linphone_gtk_get_widget(callstats,"video_codec");
if (acodec){
char tmp[64]={0};
snprintf(tmp,sizeof(tmp)-1,"%s/%i/%i",acodec->mime_type,acodec->clock_rate,acodec->channels);
gtk_label_set_label(GTK_LABEL(acodec_ui),tmp);
}else gtk_label_set_label(GTK_LABEL(acodec_ui),_("Not used"));
if (vcodec){
gtk_label_set_label(GTK_LABEL(vcodec_ui),vcodec->mime_type);
}else gtk_label_set_label(GTK_LABEL(vcodec_ui),_("Not used"));
}
}
static const char *ice_state_to_string(LinphoneIceState ice_state){
switch(ice_state){
case LinphoneIceStateNotActivated:
return _("Ice not activated");
case LinphoneIceStateInProgress:
return _("ICE in progress");
case LinphoneIceStateReflexiveConnection:
return _("Going through one or more NATs");
case LinphoneIceStateHostConnection:
return _("Direct");
case LinphoneIceStateRelayConnection:
return _("Through a relay server");
}
return "invalid";
}
static void _refresh_call_stats(GtkWidget *callstats, LinphoneCall *call){
const LinphoneCallStats *as=linphone_call_get_audio_stats(call);
const LinphoneCallStats *vs=linphone_call_get_video_stats(call);
LinphoneIceState ice_state=as->ice_state;
gchar *tmp=g_strdup_printf(_("download: %f\nupload: %f (kbit/s)"),
as->download_bandwidth,as->upload_bandwidth);
gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"audio_bandwidth_usage")),tmp);
g_free(tmp);
tmp=g_strdup_printf(_("download: %f\nupload: %f (kbit/s)"),
vs->download_bandwidth,vs->upload_bandwidth);
gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"video_bandwidth_usage")),tmp);
g_free(tmp);
gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"media_connectivity")),ice_state_to_string(ice_state));
}
static gboolean refresh_call_stats(GtkWidget *callstats){
LinphoneCall *call=(LinphoneCall*)g_object_get_data(G_OBJECT(callstats),"call");
switch (linphone_call_get_state(call)){
case LinphoneCallError:
case LinphoneCallEnd:
case LinphoneCallReleased:
gtk_widget_destroy(callstats);
return FALSE;
break;
case LinphoneCallStreamsRunning:
_refresh_call_stats(callstats,call);
break;
default:
break;
}
return TRUE;
}
static void on_call_stats_destroyed(GtkWidget *call_view){
GtkWidget *call_stats=(GtkWidget*)g_object_get_data(G_OBJECT(call_view),"call_stats");
LinphoneCall *call=(LinphoneCall*)g_object_get_data(G_OBJECT(call_stats),"call");
g_source_remove(GPOINTER_TO_INT(g_object_get_data(G_OBJECT(call_stats),"tid")));
g_object_set_data(G_OBJECT(call_view),"call_stats",NULL);
linphone_call_unref(call);
}
static void linphone_gtk_show_call_stats(LinphoneCall *call){
GtkWidget *w=(GtkWidget*)linphone_call_get_user_pointer(call);
GtkWidget *call_stats=(GtkWidget*)g_object_get_data(G_OBJECT(w),"call_stats");
if (call_stats==NULL){
guint tid;
call_stats=linphone_gtk_create_window("call_statistics");
g_object_set_data(G_OBJECT(w),"call_stats",call_stats);
g_object_set_data(G_OBJECT(call_stats),"call",linphone_call_ref(call));
tid=g_timeout_add(1000,(GSourceFunc)refresh_call_stats,call_stats);
g_object_set_data(G_OBJECT(call_stats),"tid",GINT_TO_POINTER(tid));
g_signal_connect_swapped(G_OBJECT(call_stats),"destroy",(GCallback)on_call_stats_destroyed,(gpointer)w);
show_used_codecs(call_stats,call);
refresh_call_stats(call_stats);
gtk_widget_show(call_stats);
}
}
void linphone_gtk_create_in_call_view(LinphoneCall *call){
GtkWidget *call_view=linphone_gtk_create_widget("main","in_call_frame");
GtkWidget *main_window=linphone_gtk_get_main_window ();
@ -217,6 +311,7 @@ void linphone_gtk_create_in_call_view(LinphoneCall *call){
linphone_gtk_enable_hold_button (call,FALSE,TRUE);
linphone_gtk_enable_mute_button(
GTK_BUTTON(linphone_gtk_get_widget(call_view,"incall_mute")),FALSE);
g_signal_connect_swapped(G_OBJECT(linphone_gtk_get_widget(call_view,"quality_indicator")),"button-press-event",(GCallback)linphone_gtk_show_call_stats,call);
}
static void video_button_clicked(GtkWidget *button, LinphoneCall *call){
@ -506,6 +601,7 @@ void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call){
GtkWidget *duration=linphone_gtk_get_widget(callview,"in_call_duration");
guint taskid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(callview),"taskid"));
gboolean in_conf=linphone_call_params_local_conference_mode(linphone_call_get_current_params(call));
GtkWidget *call_stats=(GtkWidget*)g_object_get_data(G_OBJECT(callview),"call_stats");
display_peer_name_in_label(callee,linphone_call_get_remote_address (call));
@ -524,6 +620,7 @@ void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call){
linphone_gtk_in_call_view_enable_audio_view(call, !in_conf);
linphone_gtk_in_call_view_show_encryption(call);
if (in_conf) linphone_gtk_set_in_conference(call);
if (call_stats) show_used_codecs(call_stats,call);
}
void linphone_gtk_in_call_view_set_paused(LinphoneCall *call){
@ -676,3 +773,8 @@ void linphone_gtk_enable_hold_button(LinphoneCall *call, gboolean sensitive, gbo
gtk_widget_set_visible(GTK_WIDGET(button),sensitive);
linphone_gtk_draw_hold_button(GTK_BUTTON(button),!holdon);
}
void linphone_gtk_call_statistics_closed(GtkWidget *call_stats){
gtk_widget_destroy(call_stats);
}

File diff suppressed because it is too large Load diff

View file

@ -74,6 +74,13 @@ public interface LinphoneChatMessage {
*/
LinphoneAddress getPeerAddress();
/**
* get from address associated to this LinphoneChatMessage
*
* @return LinphoneAddress from address
*/
LinphoneAddress getFrom();
/**
* Linphone message can carry external body as defined by rfc2017
* @param message #LinphoneChatMessage

View file

@ -40,12 +40,6 @@ public interface LinphoneChatRoom {
* @param chat message
*/
void sendMessage(LinphoneChatMessage message, LinphoneChatMessage.StateListener listener);
/**
* DEPRECATED
* @param opaque
* @param message
*/
void sendMessage(Object opaque, String message);
/**
* Create a LinphoneChatMessage

View file

@ -491,11 +491,17 @@ public interface LinphoneCore {
*/
void clearCallLogs();
/***
* get payload type from mime type an clock rate
* get payload type from mime type, clock rate, and number of channels.-
*
* return null if not found
*/
PayloadType findPayloadType(String mime, int clockRate, int channels);
/***
* get payload type from mime type and clock rate..
*
* return null if not found
*/
PayloadType findPayloadType(String mime, int clockRate);
/**
* not implemented yet
* @param pt
@ -677,6 +683,10 @@ public interface LinphoneCore {
void startEchoCalibration(Object data) throws LinphoneCoreException;
void enableIpv6(boolean enable);
/**
* @deprecated
* @param i
*/
void adjustSoftwareVolume(int i);
boolean pauseCall(LinphoneCall call);

View file

@ -82,10 +82,9 @@ public interface LinphoneCoreListener {
* invoked when a new linphone chat message is received
* @param lc LinphoneCore
* @param room LinphoneChatRoom involved in this conversation. Can be be created by the framework in case the from is not present in any chat room.
* @param from LinphoneAddress from
* @param message incoming linphone chat message message
*/
void messageReceived(LinphoneCore lc, LinphoneChatRoom cr, LinphoneAddress from, LinphoneChatMessage message);
void messageReceived(LinphoneCore lc, LinphoneChatRoom cr, LinphoneChatMessage message);
/**
* Invoked when echo cancalation calibration is completed

View file

@ -5,13 +5,7 @@ AC_REQUIRE([LP_CHECK_OSIP2])
case $host_alias in
i386-apple*)
OSIP_LIBS="$OSIP_LIBS -framework CoreFoundation -framework CFNetwork -lresolv"
;;
armv6-apple*)
OSIP_LIBS="$OSIP_LIBS -framework CoreFoundation -framework CFNetwork -lresolv"
;;
armv7-apple*)
i386-apple*|armv6-apple*|armv7-apple*|armv7s-apple*)
OSIP_LIBS="$OSIP_LIBS -framework CoreFoundation -framework CFNetwork -lresolv"
;;
x86_64-apple*)

@ -1 +1 @@
Subproject commit 88b9146ccbd33c9d8d3317be92078f6211498907
Subproject commit f225ee612009009075ab6caf7ef91bb3a21fa25f

View file

@ -25,6 +25,7 @@ gtk/loginframe.c
[type: gettext/glade]gtk/buddylookup.ui
[type: gettext/glade]gtk/waiting.ui
[type: gettext/glade]gtk/dscp_settings.ui
[type: gettext/glade]gtk/call_statistics.ui
[type: gettext/glade]gtk/tunnel_config.ui
coreapi/linphonecore.c
coreapi/misc.c