MS2_PLUGINS_INSTALL_PREFIX=$(prefix) \
gtk-mac-bundler $(PACKAGE_BUNDLE_FILE)
printf "[Pango]\nModuleFiles=./etc/pango/pango.modules\n" \
- > $(BUNDLEDIR)/Contents/Resources/etc/pango/pangorc
+ > $(BUNDLEDIR)/Contents/Resources/etc/pango/pangorc
+ cp -f $(BUNDLEDIR)/Contents/Resources/etc/pango/pango.modules $(BUNDLEDIR)/Contents/Resources/etc/pango/pango.modules.orig
+ sed -e 's:@executable_path/../Resources:../..:g' $(BUNDLEDIR)/Contents/Resources/etc/pango/pango.modules.orig > $(BUNDLEDIR)/Contents/Resources/etc/pango/pango.modules
cp -f $(LIBICONV_HACK) $(BUNDLEDIR)/Contents/Resources/lib/.
cd $(BUNDLEDIR)/.. && rm -f $(MACAPPZIP) && zip -r $(MACAPPZIP) $(MACAPPNAME) && cd -
discovery:
touch specs.cpp
$(CC) --include $(top_builddir)/config.h \
- --include $(top_builddir)/mediastreamer2/mediastreamer-config.h \
- --include $(top_builddir)/oRTP/ortp-config.h \
$(TUNNEL_CFLAGS) $(CFLAGS) $(MEDIASTREAMER2_CFLAGS) $(ORTP_CFLAGS) -E -P -v -dD specs.cpp
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
dnl AM_GNU_GETTEXT pollutes CPPFLAGS: workaround this.
CPPFLAGS_save=$CPPFLAGS
AM_GNU_GETTEXT([external])
+ AC_SUBST(INTLLIBS)
CPPFLAGS=$CPPFLAGS_save
LIBS="$LIBS $LIBINTL"
else
#include "config.h"
#endif
+#ifdef HAVE_READLINE
#ifdef HAVE_READLINE_H
#include <readline.h>
-#define HAVE_READLINE
#else
#ifdef HAVE_READLINE_READLINE_H
#include <readline/readline.h>
-#define HAVE_READLINE
#endif
#endif
#ifdef HAVE_HISTORY_H
#include <readline/history.h>
#endif
#endif
+#endif
#undef PARAMS
/**************************************************************************
int TunnelManager::eXosipSelect(int max_fds, fd_set *s1, fd_set *s2, fd_set *s3, struct timeval *tv,void* userdata){
struct timeval begin,cur;
TunnelManager* lTunnelMgr=(TunnelManager*)userdata;
- if (tv!=0 && tv->tv_sec){
+ if (s1 && tv!=0 && tv->tv_sec){
/*this is the select from udp.c, the one that is interesting to us*/
NativeSocket udp_fd=(NativeSocket)eXosip_get_udp_socket();
NativeSocket controlfd=(NativeSocket)eXosip_get_control_fd();
- FD_ZERO(s1);
+ FD_ZERO(s1);
gettimeofday(&begin,NULL);
do{
struct timeval abit;
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;
}
}
-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
lTransport.tls_port=0;
lTransport.dtls_port=0;
- linphone_core_set_sip_transports(mCore, &lTransport);
+ linphone_core_set_sip_transports(mCore, &lTransport);
//register
if (lProxy) {
linphone_proxy_config_done(lProxy);
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
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);
}
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
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() {
mAutoDetectStarted=true;
mCurrentUdpMirrorClient =mUdpMirrorClients.begin();
UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient;
- lUdpMirrorClient.start(TunnelManager::UdpMirrorClientListener,(void*)this);
+ lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this);
}
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);
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;
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;
};
/**
call->media_pending=TRUE;
}
call->resultdesc=new_md;
- if (call->ice_session != NULL) {
- linphone_core_deactivate_ice_for_deactivated_media_streams(call, call->resultdesc);
- }
if ((call->audiostream && call->audiostream->ticker) || (call->videostream && call->videostream->ticker)){
/* we already started media: check if we really need to restart it*/
if (oldmd){
}
call=linphone_call_new_incoming(lc,from_addr,to_addr,h);
- sal_call_set_local_media_description(h,call->localdesc);
/* the call is acceptable so we can now add it to our list */
linphone_core_add_call(lc,call);
}
md=sal_call_get_final_media_description(op);
+ call->params.has_video &= linphone_core_media_description_contains_video_stream(md);
if (call->state==LinphoneCallOutgoingProgress ||
call->state==LinphoneCallOutgoingRinging ||
linphone_core_update_streams (lc,call,md);
linphone_call_set_state(call,LinphoneCallPausedByRemote,"Call paused by remote");
}else{
- if (call->state==LinphoneCallStreamsRunning){
- /*media was running before, the remote as acceted a call modification (that is
- a reinvite made by us. We must notify the application this reinvite was accepted*/
- linphone_call_set_state(call, LinphoneCallUpdated, "Call updated");
- }else{
+ if (call->state!=LinphoneCallUpdating){
if (call->state==LinphoneCallResuming){
if (lc->vtable.display_status){
lc->vtable.display_status(lc,_("Call resumed."));
if (call->media_pending){
SalMediaDescription *md=sal_call_get_final_media_description(op);
if (md && !sal_media_description_empty(md)){
- if (call->state==LinphoneCallStreamsRunning){
- /*media was running before, the remote as acceted a call modification (that is
- a reinvite made by us. We must notify the application this reinvite was accepted*/
- linphone_call_set_state(call, LinphoneCallUpdated, "Call updated");
- }
linphone_core_update_streams (lc,call,md);
linphone_call_set_state (call,LinphoneCallStreamsRunning,"Connected (streams running)");
}else{
call->localdesc->streams[i].proto = SalProtoRtpAvp;
memset(call->localdesc->streams[i].crypto, 0, sizeof(call->localdesc->streams[i].crypto));
}
- linphone_core_start_invite(lc, call, NULL);
+ linphone_core_start_invite(lc, call);
}
return;
}
return LinphoneChatMessageStateIdle;
}
+static int op_equals(LinphoneCall *a, SalOp *b) {
+ return a->op !=b; /*return 0 if equals*/
+}
static void text_delivery_update(SalOp *op, SalTextDeliveryStatus status){
LinphoneChatMessage *chat_msg=(LinphoneChatMessage* )sal_op_get_user_pointer(op);
+ const MSList* calls = linphone_core_get_calls(chat_msg->chat_room->lc);
+
if (chat_msg && chat_msg->cb) {
chat_msg->cb(chat_msg
,chatStatusSal2Linphone(status)
,chat_msg->cb_ud);
}
linphone_chat_message_destroy(chat_msg);
+
+ if (!ms_list_find_custom((MSList*)calls, (MSCompareFunc) op_equals, op)) {
+ /*op was only create for messaging purpose, destroying*/
+ sal_op_release(op);
+ }
}
SalCallbacks linphone_sal_callbacks={
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
- #include "linphonecore.h"
- #include "private.h"
+#include "linphonecore.h"
+#include "private.h"
+#include "lpconfig.h"
LinphoneChatRoom * linphone_core_create_chat_room(LinphoneCore *lc, const char *to){
LinphoneAddress *parsed_url=NULL;
lc->chatrooms=ms_list_remove(lc->chatrooms,(void *) cr);
linphone_address_destroy(cr->peer_url);
ms_free(cr->peer);
- if (cr->op)
- sal_op_release(cr->op);
}
SalOp *op=NULL;
LinphoneCall *call;
char* content_type;
- if((call = linphone_core_get_call_by_remote_address(cr->lc,cr->peer))!=NULL){
- if (call->state==LinphoneCallConnected ||
- call->state==LinphoneCallStreamsRunning ||
- call->state==LinphoneCallPaused ||
- call->state==LinphoneCallPausing ||
- call->state==LinphoneCallPausedByRemote){
- ms_message("send SIP message through the existing call.");
- op = call->op;
- call->pending_message=msg;
+
+ if (lp_config_get_int(cr->lc->config,"sip","chat_use_call_dialogs",1)){
+ if((call = linphone_core_get_call_by_remote_address(cr->lc,cr->peer))!=NULL){
+ if (call->state==LinphoneCallConnected ||
+ call->state==LinphoneCallStreamsRunning ||
+ call->state==LinphoneCallPaused ||
+ call->state==LinphoneCallPausing ||
+ call->state==LinphoneCallPausedByRemote){
+ ms_message("send SIP message through the existing call.");
+ op = call->op;
+ call->pending_message=msg;
+ }
}
}
if (op==NULL){
/*sending out of calls*/
op = sal_op_new(cr->lc->sal);
sal_op_set_route(op,route);
- if (cr->op!=NULL){
- sal_op_release (cr->op);
- cr->op=NULL;
- }
- cr->op=op;
sal_op_set_user_pointer(op, msg); /*if out of call, directly store msg*/
}
if (msg->external_body_url) {
static void ecc_init_filters(EcCalibrator *ecc){
unsigned int rate;
- ecc->ticker=ms_ticker_new();
+ MSTickerParams params={0};
+ params.name="Echo calibrator";
+ params.prio=MS_TICKER_PRIO_HIGH;
+ ecc->ticker=ms_ticker_new_with_params(¶ms);
ecc->sndread=ms_snd_card_create_reader(ecc->play_card);
ms_filter_call_method(ecc->sndread,MS_FILTER_SET_SAMPLE_RATE,&ecc->rate);
+ ms_filter_call_method(ecc->sndread,MS_FILTER_GET_SAMPLE_RATE,&rate);
+ ecc->read_resampler=ms_filter_new(MS_RESAMPLE_ID);
+ ms_filter_call_method(ecc->read_resampler,MS_FILTER_SET_SAMPLE_RATE,&rate);
+ ms_filter_call_method(ecc->read_resampler,MS_FILTER_SET_OUTPUT_SAMPLE_RATE,&ecc->rate);
+
+
ecc->det=ms_filter_new(MS_TONE_DETECTOR_ID);
ms_filter_call_method(ecc->det,MS_FILTER_SET_SAMPLE_RATE,&ecc->rate);
ecc->rec=ms_filter_new(MS_FILE_REC_ID);
- ms_filter_link(ecc->sndread,0,ecc->det,0);
+ ms_filter_link(ecc->sndread,0,ecc->read_resampler,0);
+ ms_filter_link(ecc->read_resampler,0,ecc->det,0);
ms_filter_link(ecc->det,0,ecc->rec,0);
ecc->play=ms_filter_new(MS_FILE_PLAYER_ID);
ecc->gen=ms_filter_new(MS_DTMF_GEN_ID);
ms_filter_call_method(ecc->gen,MS_FILTER_SET_SAMPLE_RATE,&ecc->rate);
- ecc->resampler=ms_filter_new(MS_RESAMPLE_ID);
+ ecc->write_resampler=ms_filter_new(MS_RESAMPLE_ID);
ecc->sndwrite=ms_snd_card_create_writer(ecc->capt_card);
-
- ms_filter_link(ecc->play,0,ecc->gen,0);
- ms_filter_link(ecc->gen,0,ecc->resampler,0);
- ms_filter_link(ecc->resampler,0,ecc->sndwrite,0);
-
+
ms_filter_call_method(ecc->sndwrite,MS_FILTER_SET_SAMPLE_RATE,&ecc->rate);
ms_filter_call_method(ecc->sndwrite,MS_FILTER_GET_SAMPLE_RATE,&rate);
- ms_filter_call_method(ecc->resampler,MS_FILTER_SET_SAMPLE_RATE,&ecc->rate);
- ms_filter_call_method(ecc->resampler,MS_FILTER_SET_OUTPUT_SAMPLE_RATE,&rate);
+ ms_filter_call_method(ecc->write_resampler,MS_FILTER_SET_SAMPLE_RATE,&ecc->rate);
+ ms_filter_call_method(ecc->write_resampler,MS_FILTER_SET_OUTPUT_SAMPLE_RATE,&rate);
+
+ ms_filter_link(ecc->play,0,ecc->gen,0);
+ ms_filter_link(ecc->gen,0,ecc->write_resampler,0);
+ ms_filter_link(ecc->write_resampler,0,ecc->sndwrite,0);
- ms_ticker_attach(ecc->ticker,ecc->play);
ms_ticker_attach(ecc->ticker,ecc->sndread);
+ ms_ticker_attach(ecc->ticker,ecc->play);
+
}
static void ecc_deinit_filters(EcCalibrator *ecc){
- ms_ticker_detach(ecc->ticker,ecc->play);
ms_ticker_detach(ecc->ticker,ecc->sndread);
+ ms_ticker_detach(ecc->ticker,ecc->play);
ms_filter_unlink(ecc->play,0,ecc->gen,0);
- ms_filter_unlink(ecc->gen,0,ecc->resampler,0);
- ms_filter_unlink(ecc->resampler,0,ecc->sndwrite,0);
+ ms_filter_unlink(ecc->gen,0,ecc->write_resampler,0);
+ ms_filter_unlink(ecc->write_resampler,0,ecc->sndwrite,0);
- ms_filter_unlink(ecc->sndread,0,ecc->det,0);
+ ms_filter_unlink(ecc->sndread,0,ecc->read_resampler,0);
+ ms_filter_unlink(ecc->read_resampler,0,ecc->det,0);
ms_filter_unlink(ecc->det,0,ecc->rec,0);
ms_filter_destroy(ecc->sndread);
ms_filter_destroy(ecc->rec);
ms_filter_destroy(ecc->play);
ms_filter_destroy(ecc->gen);
- ms_filter_destroy(ecc->resampler);
+ ms_filter_destroy(ecc->read_resampler);
+ ms_filter_destroy(ecc->write_resampler);
ms_filter_destroy(ecc->sndwrite);
ms_ticker_destroy(ecc->ticker);
MSDtmfGenCustomTone tone;
MSToneDetectorDef expected_tone;
-
ms_filter_set_notify_callback(ecc->det,on_tone_received,ecc);
expected_tone.frequency=2000;
ms_filter_call_method (ecc->det,MS_TONE_DETECTOR_ADD_SCAN,&expected_tone);
- tone.frequency=1000;
+ tone.frequency=1300;
tone.duration=1000;
tone.amplitude=1.0;
ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone);
ms_sleep(1);
- if (ecc->sent_count==3 && ecc->recv_count==3){
- int delay=ecc->acc/3;
- if (delay<0){
- ms_error("Quite surprising calibration result, delay=%i",delay);
- ecc->status=LinphoneEcCalibratorFailed;
- }else{ms_message("Echo calibration estimated delay to be %i ms",delay);
- ecc->delay=delay;
- ecc->status=LinphoneEcCalibratorDone;
+ if (ecc->sent_count==3) {
+ if (ecc->recv_count==3){
+ int delay=ecc->acc/3;
+ if (delay<0){
+ ms_error("Quite surprising calibration result, delay=%i",delay);
+ ecc->status=LinphoneEcCalibratorFailed;
+ }else{
+ ms_message("Echo calibration estimated delay to be %i ms",delay);
+ ecc->delay=delay;
+ ecc->status=LinphoneEcCalibratorDone;
+ }
+ } else if (ecc->recv_count == 0) {
+ ms_message("Echo calibration succeeded, no echo has been detected");
+ ecc->status = LinphoneEcCalibratorDoneNoEcho;
+ } else {
+ ecc->status = LinphoneEcCalibratorFailed;
}
}else{
- ms_error("Echo calibration failed, tones received = %i",ecc->recv_count);
ecc->status=LinphoneEcCalibratorFailed;
}
-
+ if (ecc->status == LinphoneEcCalibratorFailed) {
+ ms_error("Echo calibration failed, tones received = %i",ecc->recv_count);
+ }
}
static void * ecc_thread(void *p){
void linphone_core_remove_friend(LinphoneCore *lc, LinphoneFriend* fl){
MSList *el=ms_list_find(lc->friends,(void *)fl);
if (el!=NULL){
- lc->friends=ms_list_remove_link(lc->friends,el);
linphone_friend_destroy((LinphoneFriend*)el->data);
+ lc->friends=ms_list_remove_link(lc->friends,el);
linphone_core_write_friends_config(lc);
}
}
import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
+import org.linphone.core.LinphoneCallStats;
+import org.linphone.core.LinphoneChatMessage;
import org.linphone.core.LinphoneChatRoom;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
public void globalState(LinphoneCore lc, GlobalState state, String message) {}
public void textReceived(LinphoneCore lc, LinphoneChatRoom cr,LinphoneAddress from, String message) {}
public void callState(LinphoneCore lc, LinphoneCall call, State cstate, String msg) {}
+ public void callStatsUpdated(LinphoneCore lc, LinphoneCall call, LinphoneCallStats stats) {}
public void ecCalibrationStatus(LinphoneCore lc, EcCalibratorStatus status,int delay_ms, Object data) {}
public void callEncryptionChanged(LinphoneCore lc, LinphoneCall call,boolean encrypted, String authenticationToken) {}
public void notifyReceived(LinphoneCore lc, LinphoneCall call, LinphoneAddress from, byte[] event){}
+ public void dtmfReceived(LinphoneCore lc, LinphoneCall call, int dtmf) {}
public static void main(String[] args) {
TutorialNotifier.notify(s);
}
+ @Override
+ public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr, LinphoneChatMessage message) {
+ // TODO Auto-generated method stub
+
+ }
+
}
import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
+import org.linphone.core.LinphoneCallStats;
+import org.linphone.core.LinphoneChatMessage;
import org.linphone.core.LinphoneChatRoom;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
public void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf,String url) {}
public void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf) {}
public void callState(LinphoneCore lc, LinphoneCall call, State cstate, String msg){}
+ public void callStatsUpdated(LinphoneCore lc, LinphoneCall call, LinphoneCallStats stats) {}
public void ecCalibrationStatus(LinphoneCore lc, EcCalibratorStatus status,int delay_ms, Object data) {}
public void callEncryptionChanged(LinphoneCore lc, LinphoneCall call,boolean encrypted, String authenticationToken) {}
public void notifyReceived(LinphoneCore lc, LinphoneCall call, LinphoneAddress from, byte[] event){}
+ public void dtmfReceived(LinphoneCore lc, LinphoneCall call, int dtmf) {}
public void textReceived(LinphoneCore lc, LinphoneChatRoom cr,LinphoneAddress from, String message) {
write("Message ["+message+"] received from ["+from.asString()+"]");
TutorialNotifier.notify(s);
}
+ @Override
+ public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr,
+ LinphoneChatMessage message) {
+ // TODO Auto-generated method stub
+
+ }
+
}
import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
+import org.linphone.core.LinphoneCallStats;
+import org.linphone.core.LinphoneChatMessage;
import org.linphone.core.LinphoneChatRoom;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
public void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf,String url) {}
public void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf) {}
public void textReceived(LinphoneCore lc, LinphoneChatRoom cr,LinphoneAddress from, String message) {}
+ public void callStatsUpdated(LinphoneCore lc, LinphoneCall call, LinphoneCallStats stats) {}
public void ecCalibrationStatus(LinphoneCore lc, EcCalibratorStatus status,int delay_ms, Object data) {}
public void callEncryptionChanged(LinphoneCore lc, LinphoneCall call,boolean encrypted, String authenticationToken) {}
public void notifyReceived(LinphoneCore lc, LinphoneCall call, LinphoneAddress from, byte[] event){}
+ public void dtmfReceived(LinphoneCore lc, LinphoneCall call, int dtmf) {}
/*
* Call state notification listener
*/
TutorialNotifier.notify(s);
}
+ @Override
+ public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr,
+ LinphoneChatMessage message) {
+ // TODO Auto-generated method stub
+
+ }
+
}
import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
+import org.linphone.core.LinphoneCallStats;
+import org.linphone.core.LinphoneChatMessage;
import org.linphone.core.LinphoneChatRoom;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
public void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf) {}
public void textReceived(LinphoneCore lc, LinphoneChatRoom cr,LinphoneAddress from, String message) {}
public void callState(LinphoneCore lc, LinphoneCall call, State cstate, String msg) {}
+ public void callStatsUpdated(LinphoneCore lc, LinphoneCall call, LinphoneCallStats stats) {}
public void ecCalibrationStatus(LinphoneCore lc, EcCalibratorStatus status,int delay_ms, Object data) {}
public void callEncryptionChanged(LinphoneCore lc, LinphoneCall call,boolean encrypted, String authenticationToken) {}
public void notifyReceived(LinphoneCore lc, LinphoneCall call, LinphoneAddress from, byte[] event){}
+ public void dtmfReceived(LinphoneCore lc, LinphoneCall call, int dtmf) {}
public static void main(String[] args) {
// Check tutorial was called with the right number of arguments
TutorialNotifier.notify(s);
}
+ @Override
+ public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr,
+ LinphoneChatMessage message) {
+ // TODO Auto-generated method stub
+
+ }
+
}
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){
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);
}
* @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
**/
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);
/**
return l;
}
+static void update_media_description_from_stun(SalMediaDescription *md, const StunCandidate *ac, const StunCandidate *vc){
+ if (ac->port!=0){
+ strcpy(md->streams[0].rtp_addr,ac->addr);
+ md->streams[0].rtp_port=ac->port;
+ if ((ac->addr[0]!='\0' && vc->addr[0]!='\0' && strcmp(ac->addr,vc->addr)==0) || md->nstreams==1){
+ strcpy(md->addr,ac->addr);
+ }
+ }
+ if (vc->port!=0){
+ strcpy(md->streams[1].rtp_addr,vc->addr);
+ md->streams[1].rtp_port=vc->port;
+ }
+
+}
+
+
static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, LinphoneCall *call, unsigned int session_id, unsigned int session_ver){
MSList *l;
PayloadType *pt;
LinphoneAddress *addr=linphone_address_new(me);
const char *username=linphone_address_get_username (addr);
SalMediaDescription *md=sal_media_description_new();
+
+ if (call->ping_time>0) {
+ linphone_core_adapt_to_network(lc,call->ping_time,&call->params);
+ }
md->session_id=session_id;
md->session_ver=session_ver;
md->streams[i].crypto[1].algo = 0;
md->streams[i].crypto[2].algo = 0;
}
- if ((linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL) && (ice_session_check_list(call->ice_session, i) == NULL)) {
- ice_session_add_check_list(call->ice_session, ice_check_list_new());
- }
}
-
+ update_media_description_from_stun(md,&call->ac,&call->vc);
+ if (call->ice_session != NULL) {
+ linphone_core_update_local_media_description_from_ice(md, call->ice_session);
+ linphone_core_update_ice_state_in_call_stats(call);
+ }
linphone_address_destroy(addr);
return md;
}
return _create_local_media_description(lc,call,id,id);
}
-static int find_port_offset(LinphoneCore *lc){
+static int find_port_offset(LinphoneCore *lc, SalStreamType type){
int offset;
MSList *elem;
- int audio_port;
+ int tried_port;
+ int existing_port;
bool_t already_used=FALSE;
for(offset=0;offset<100;offset+=2){
- audio_port=linphone_core_get_audio_port (lc)+offset;
+ switch (type) {
+ default:
+ case SalAudio:
+ tried_port=linphone_core_get_audio_port (lc)+offset;
+ break;
+ case SalVideo:
+ tried_port=linphone_core_get_video_port (lc)+offset;
+ break;
+ }
already_used=FALSE;
for(elem=lc->calls;elem!=NULL;elem=elem->next){
LinphoneCall *call=(LinphoneCall*)elem->data;
- if (call->audio_port==audio_port) {
+ switch (type) {
+ default:
+ case SalAudio:
+ existing_port = call->audio_port;
+ break;
+ case SalVideo:
+ existing_port = call->video_port;
+ break;
+ }
+ if (existing_port==tried_port) {
already_used=TRUE;
break;
}
return offset;
}
+static int select_random_port(LinphoneCore *lc, SalStreamType type) {
+ MSList *elem;
+ int nb_tries;
+ int tried_port = 0;
+ int existing_port = 0;
+ int min_port = 0, max_port = 0;
+ bool_t already_used = FALSE;
+
+ switch (type) {
+ default:
+ case SalAudio:
+ linphone_core_get_audio_port_range(lc, &min_port, &max_port);
+ break;
+ case SalVideo:
+ linphone_core_get_video_port_range(lc, &min_port, &max_port);
+ break;
+ }
+ tried_port = (rand() % (max_port - min_port) + min_port) & ~0x1;
+ if (tried_port < min_port) tried_port = min_port + 2;
+ for (nb_tries = 0; nb_tries < 100; nb_tries++) {
+ for (elem = lc->calls; elem != NULL; elem = elem->next) {
+ LinphoneCall *call = (LinphoneCall *)elem->data;
+ switch (type) {
+ default:
+ case SalAudio:
+ existing_port = call->audio_port;
+ break;
+ case SalVideo:
+ existing_port = call->video_port;
+ break;
+ }
+ if (existing_port == tried_port) {
+ already_used = TRUE;
+ break;
+ }
+ }
+ if (!already_used) break;
+ }
+ if (nb_tries == 100) {
+ ms_error("Could not find any free port!");
+ return -1;
+ }
+ return tried_port;
+}
+
static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, LinphoneAddress *to){
int port_offset;
+ int min_port, max_port;
call->magic=linphone_call_magic;
call->refcnt=1;
call->state=LinphoneCallIdle;
call->log=linphone_call_log_new(call, from, to);
call->owns_call_log=TRUE;
linphone_core_notify_all_friends(call->core,LinphoneStatusOnThePhone);
- port_offset=find_port_offset (call->core);
- if (port_offset==-1) return;
- call->audio_port=linphone_core_get_audio_port(call->core)+port_offset;
- call->video_port=linphone_core_get_video_port(call->core)+port_offset;
+ linphone_core_get_audio_port_range(call->core, &min_port, &max_port);
+ if (min_port == max_port) {
+ /* Used fixed RTP audio port. */
+ port_offset=find_port_offset (call->core, SalAudio);
+ if (port_offset==-1) return;
+ call->audio_port=linphone_core_get_audio_port(call->core)+port_offset;
+ } else {
+ /* Select random RTP audio port in the specified range. */
+ call->audio_port = select_random_port(call->core, SalAudio);
+ }
+ linphone_core_get_video_port_range(call->core, &min_port, &max_port);
+ if (min_port == max_port) {
+ /* Used fixed RTP video port. */
+ port_offset=find_port_offset (call->core, SalVideo);
+ if (port_offset==-1) return;
+ call->video_port=linphone_core_get_video_port(call->core)+port_offset;
+ } else {
+ /* Select random RTP video port in the specified range. */
+ call->video_port = select_random_port(call->core, SalVideo);
+ }
linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_AUDIO], LINPHONE_CALL_STATS_AUDIO);
linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO], LINPHONE_CALL_STATS_VIDEO);
}
stats->type = type;
stats->received_rtcp = NULL;
stats->sent_rtcp = NULL;
+ stats->ice_state = LinphoneIceStateNotActivated;
}
-static void update_media_description_from_stun(SalMediaDescription *md, const StunCandidate *ac, const StunCandidate *vc){
- if (ac->port!=0){
- strcpy(md->streams[0].rtp_addr,ac->addr);
- md->streams[0].rtp_port=ac->port;
- if ((ac->addr[0]!='\0' && vc->addr[0]!='\0' && strcmp(ac->addr,vc->addr)==0) || md->nstreams==1){
- strcpy(md->addr,ac->addr);
- }
- }
- if (vc->port!=0){
- strcpy(md->streams[1].rtp_addr,vc->addr);
- md->streams[1].rtp_port=vc->port;
- }
-
-}
static void discover_mtu(LinphoneCore *lc, const char *remote){
int mtu;
}
}
-#define STUN_CANDIDATE_INIT {{0},0}
-
LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, const LinphoneCallParams *params)
{
LinphoneCall *call=ms_new0(LinphoneCall,1);
- StunCandidate ac=STUN_CANDIDATE_INIT,vc=STUN_CANDIDATE_INIT;
- int ping_time=-1;
call->dir=LinphoneCallOutgoing;
call->op=sal_op_new(lc->sal);
sal_op_set_user_pointer(call->op,call);
ice_session_set_role(call->ice_session, IR_Controlling);
}
if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseStun) {
- ping_time=linphone_core_run_stun_tests(call->core,call,&ac, &vc);
+ call->ping_time=linphone_core_run_stun_tests(call->core,call);
}
- if (ping_time>=0) {
- linphone_core_adapt_to_network(lc,ping_time,&call->params);
- }
- call->localdesc=create_local_media_description(lc,call);
- update_media_description_from_stun(call->localdesc,&ac,&vc);
call->camera_active=params->has_video;
discover_mtu(lc,linphone_address_get_domain (to));
LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op){
LinphoneCall *call=ms_new0(LinphoneCall,1);
char *from_str;
- int ping_time=-1;
- StunCandidate ac=STUN_CANDIDATE_INIT,vc=STUN_CANDIDATE_INIT;
call->dir=LinphoneCallIncoming;
sal_op_set_user_pointer(op,call);
linphone_address_clean(from);
linphone_core_get_local_ip(lc,linphone_address_get_domain(from),call->localip);
linphone_call_init_common(call, from, to);
+ call->log->call_id=ms_strdup(sal_op_get_call_id(op)); /*must be known at that time*/
linphone_core_init_default_params(lc, &call->params);
call->params.has_video &= !!lc->video_policy.automatically_accept;
+ call->params.has_video &= linphone_core_media_description_contains_video_stream(sal_call_get_remote_media_description(op));
switch (linphone_core_get_firewall_policy(call->core)) {
case LinphonePolicyUseIce:
call->ice_session = ice_session_new();
if (linphone_core_gather_ice_candidates(call->core,call)<0) {
/* Ice candidates gathering failed, proceed with the call anyway. */
linphone_call_delete_ice_session(call);
- linphone_call_stop_media_streams(call);
+ linphone_call_stop_media_streams_for_ice_gathering(call);
}
}
break;
case LinphonePolicyUseStun:
- ping_time=linphone_core_run_stun_tests(call->core,call,&ac, &vc);
+ call->ping_time=linphone_core_run_stun_tests(call->core,call);
/* No break to also destroy ice session in this case. */
default:
break;
}
- if (ping_time>=0) {
- linphone_core_adapt_to_network(lc,ping_time,&call->params);
- };
- call->localdesc=create_local_media_description(lc,call);
- update_media_description_from_stun(call->localdesc,&ac,&vc);
call->camera_active=call->params.has_video;
discover_mtu(lc,linphone_address_get_domain(from));
return "LinphoneCallUpdatedByRemote";
case LinphoneCallIncomingEarlyMedia:
return "LinphoneCallIncomingEarlyMedia";
- case LinphoneCallUpdated:
- return "LinphoneCallUpdated";
+ case LinphoneCallUpdating:
+ return "LinphoneCallUpdating";
case LinphoneCallReleased:
return "LinphoneCallReleased";
}
static void linphone_call_destroy(LinphoneCall *obj)
{
+ linphone_call_delete_ice_session(obj);
if (obj->op!=NULL) {
sal_op_release(obj->op);
obj->op=NULL;
if (obj->auth_token) {
ms_free(obj->auth_token);
}
- if (obj->ice_session) {
- ice_session_destroy(obj->ice_session);
- }
ms_free(obj);
}
return cp->video_codec;
}
+bool_t linphone_call_params_low_bandwidth_enabled(const LinphoneCallParams *cp) {
+ return cp->low_bandwidth;
+}
/**
* Returns whether video is enabled.
**/
void linphone_call_init_audio_stream(LinphoneCall *call){
LinphoneCore *lc=call->core;
AudioStream *audiostream;
- int dscp=linphone_core_get_audio_dscp(lc);
+ int dscp;
+ if (call->audiostream != NULL) return;
call->audiostream=audiostream=audio_stream_new(call->audio_port,call->audio_port+1,linphone_core_ipv6_enabled(lc));
+ dscp=linphone_core_get_audio_dscp(lc);
if (dscp!=-1)
audio_stream_set_dscp(audiostream,dscp);
if (linphone_core_echo_limiter_enabled(lc)){
if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)){
rtp_session_set_pktinfo(audiostream->session, TRUE);
rtp_session_set_symmetric_rtp(audiostream->session, FALSE);
+ if (ice_session_check_list(call->ice_session, 0) == NULL) {
+ ice_session_add_check_list(call->ice_session, ice_check_list_new());
+ }
audiostream->ice_check_list = ice_session_check_list(call->ice_session, 0);
ice_check_list_set_rtp_session(audiostream->ice_check_list, audiostream->session);
}
#ifdef VIDEO_ENABLED
LinphoneCore *lc=call->core;
+ if (!call->params.has_video) {
+ linphone_call_stop_video_stream(call);
+ return;
+ }
+ if (call->videostream != NULL) return;
if ((lc->video_conf.display || lc->video_conf.capture) && call->params.has_video){
int video_recv_buf_size=lp_config_get_int(lc->config,"video","recv_buf_size",0);
int dscp=linphone_core_get_video_dscp(lc);
RtpTransport *vrtcp=lc->rtptf->video_rtcp_func(lc->rtptf->video_rtcp_func_data, call->video_port+1);
rtp_session_set_transports(call->videostream->session,vrtp,vrtcp);
}
- if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL) && (ice_session_check_list(call->ice_session, 1))){
+ if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)){
rtp_session_set_pktinfo(call->videostream->session, TRUE);
rtp_session_set_symmetric_rtp(call->videostream->session, FALSE);
+ if (ice_session_check_list(call->ice_session, 1) == NULL) {
+ ice_session_add_check_list(call->ice_session, ice_check_list_new());
+ }
call->videostream->ice_check_list = ice_session_check_list(call->ice_session, 1);
ice_check_list_set_rtp_session(call->videostream->ice_check_list, call->videostream->session);
}
static int dtmf_tab[16]={'0','1','2','3','4','5','6','7','8','9','*','#','A','B','C','D'};
-static void linphone_core_dtmf_received(RtpSession* s, int dtmf, void* user_data){
- LinphoneCore* lc = (LinphoneCore*)user_data;
+static void linphone_core_dtmf_received(LinphoneCore *lc, int dtmf){
if (dtmf<0 || dtmf>15){
ms_warning("Bad dtmf value %i",dtmf);
return;
if (lc->vtable.dtmf_received!=NULL){
/* replace by our default action*/
audio_stream_play_received_dtmfs(call->audiostream,FALSE);
- rtp_session_signal_connect(call->audiostream->session,"telephone-event",(RtpCallback)linphone_core_dtmf_received,(unsigned long)lc);
+ /*rtp_session_signal_connect(call->audiostream->session,"telephone-event",(RtpCallback)linphone_core_dtmf_received,(unsigned long)lc);*/
}
}
ms_filter_call_method(call->audiostream->soundread,MS_FILE_PLAYER_LOOP,&pause_time);
}
-#define LINPHONE_RTCP_SDES_TOOL "Linphone-" LINPHONE_VERSION
-
static bool_t linphone_call_sound_resources_available(LinphoneCall *call){
LinphoneCore *lc=call->core;
LinphoneCall *current=linphone_core_get_current_call(lc);
static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cname, bool_t muted, bool_t send_ringbacktone, bool_t use_arc){
LinphoneCore *lc=call->core;
int used_pt=-1;
+ char rtcp_tool[128]={0};
+ snprintf(rtcp_tool,sizeof(rtcp_tool)-1,"%s-%s",linphone_core_get_user_agent_name(),linphone_core_get_user_agent_version());
/* look for savp stream first */
const SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc,
SalProtoRtpSavp,SalAudio);
if (send_ringbacktone){
setup_ring_player(lc,call);
}
- audio_stream_set_rtcp_information(call->audiostream, cname, LINPHONE_RTCP_SDES_TOOL);
+ audio_stream_set_rtcp_information(call->audiostream, cname, rtcp_tool);
/* valid local tags are > 0 */
if (stream->proto == SalProtoRtpSavp) {
linphone_call_add_to_conf(call, mute);
}
call->current_params.in_conference=call->params.in_conference;
+ call->current_params.low_bandwidth=call->params.low_bandwidth;
}else ms_warning("No audio stream accepted ?");
}
}
/* look for savp stream first */
const SalStreamDescription *vstream=sal_media_description_find_stream(call->resultdesc,
SalProtoRtpSavp,SalVideo);
+ char rtcp_tool[128]={0};
+ snprintf(rtcp_tool,sizeof(rtcp_tool)-1,"%s-%s",linphone_core_get_user_agent_name(),linphone_core_get_user_agent_version());
+
/* no savp audio stream, use avp */
if (!vstream)
vstream=sal_media_description_find_stream(call->resultdesc,
cam=get_nowebcam_device();
}
if (!is_inactive){
- call->log->video_enabled = TRUE;
+ call->log->video_enabled = TRUE;
video_stream_set_direction (call->videostream, dir);
ms_message("%s lc rotation:%d\n", __FUNCTION__, lc->device_rotation);
video_stream_set_device_rotation(call->videostream, lc->device_rotation);
call->video_profile, rtp_addr, vstream->rtp_port,
rtcp_addr, linphone_core_rtcp_enabled(lc) ? (vstream->rtcp_port) : 0,
used_pt, linphone_core_get_video_jittcomp(lc), cam);
- video_stream_set_rtcp_information(call->videostream, cname,LINPHONE_RTCP_SDES_TOOL);
+ video_stream_set_rtcp_information(call->videostream, cname,rtcp_tool);
}
if (vstream->proto == SalProtoRtpSavp) {
#endif
}
+void linphone_call_stop_media_streams_for_ice_gathering(LinphoneCall *call){
+ audio_stream_unprepare_sound(call->audiostream);
+#ifdef VIDEO_ENABLED
+ if (call->videostream) {
+ video_stream_unprepare_video(call->videostream);
+ }
+#endif
+}
+
void linphone_call_delete_ice_session(LinphoneCall *call){
if (call->ice_session != NULL) {
ice_session_destroy(call->ice_session);
call->ice_session = NULL;
if (call->audiostream != NULL) call->audiostream->ice_check_list = NULL;
if (call->videostream != NULL) call->videostream->ice_check_list = NULL;
+ call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateNotActivated;
+ call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateNotActivated;
}
}
log->quality=audio_stream_get_average_quality_rating(st);
}
-void linphone_call_stop_media_streams(LinphoneCall *call){
+void linphone_call_stop_audio_stream(LinphoneCall *call) {
if (call->audiostream!=NULL) {
- call->audiostream->ice_check_list = NULL;
rtp_session_unregister_event_queue(call->audiostream->session,call->audiostream_app_evq);
ortp_ev_queue_flush(call->audiostream_app_evq);
ortp_ev_queue_destroy(call->audiostream_app_evq);
audio_stream_stop(call->audiostream);
call->audiostream=NULL;
}
+}
-
+void linphone_call_stop_video_stream(LinphoneCall *call) {
#ifdef VIDEO_ENABLED
if (call->videostream!=NULL){
- call->videostream->ice_check_list = NULL;
rtp_session_unregister_event_queue(call->videostream->session,call->videostream_app_evq);
ortp_ev_queue_flush(call->videostream_app_evq);
ortp_ev_queue_destroy(call->videostream_app_evq);
call->videostream=NULL;
}
#endif
+}
+
+void linphone_call_stop_media_streams(LinphoneCall *call){
+ linphone_call_stop_audio_stream(call);
+ linphone_call_stop_video_stream(call);
ms_event_queue_skip(call->core->msevq);
if (call->audio_profile){
* @}
**/
-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){
static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
OrtpEventType evt=ortp_event_get_type(ev);
OrtpEventData *evd=ortp_event_get_data(ev);
+ int ping_time;
if (evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) {
switch (ice_session_state(call->ice_session)) {
case IS_Completed:
+ ice_session_select_candidates(call->ice_session);
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);
}
break;
case IS_Failed:
if (ice_session_has_completed_check_list(call->ice_session) == TRUE) {
+ ice_session_select_candidates(call->ice_session);
if (ice_session_role(call->ice_session) == IR_Controlling) {
/* 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);
}
}
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) {
ice_session_compute_candidates_foundations(call->ice_session);
ice_session_eliminate_redundant_candidates(call->ice_session);
ice_session_choose_default_candidates(call->ice_session);
- ping_time = ice_session_gathering_duration(call->ice_session);
+ ping_time = ice_session_average_gathering_round_trip_time(call->ice_session);
if (ping_time >=0) {
- ping_time /= ice_session_nb_check_lists(call->ice_session);
+ call->ping_time=ping_time;
}
} else {
ms_warning("No STUN answer from [%s], disabling ICE",linphone_core_get_stun_server(call->core));
linphone_call_delete_ice_session(call);
}
switch (call->state) {
- case LinphoneCallStreamsRunning:
+ case LinphoneCallUpdating:
linphone_core_start_update_call(call->core, call);
break;
case LinphoneCallUpdatedByRemote:
linphone_core_start_accept_call_update(call->core, call);
break;
case LinphoneCallOutgoingInit:
- if (ping_time >= 0) {
- linphone_core_adapt_to_network(call->core, ping_time, &call->params);
- }
- linphone_call_stop_media_streams(call);
+ linphone_call_stop_media_streams_for_ice_gathering(call);
linphone_core_proceed_with_invite_if_ready(call->core, call, NULL);
break;
- default:
- if (ping_time >= 0) {
- linphone_core_adapt_to_network(call->core, ping_time, &call->params);
- }
- linphone_call_stop_media_streams(call);
+ case LinphoneCallIdle:
+ linphone_call_stop_media_streams_for_ice_gathering(call);
linphone_core_notify_incoming_call(call->core, call);
break;
+ default:
+ break;
}
} else if (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) {
linphone_core_start_accept_call_update(call->core, call);
+ linphone_core_update_ice_state_in_call_stats(call);
} else if (evt == ORTP_EVENT_ICE_RESTART_NEEDED) {
ice_session_restart(call->ice_session);
ice_session_set_role(call->ice_session, IR_Controlling);
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
} else if ((evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) || (evt == ORTP_EVENT_ICE_GATHERING_FINISHED)
|| (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) || (evt == ORTP_EVENT_ICE_RESTART_NEEDED)) {
handle_ice_events(call, ev);
+ } else if (evt==ORTP_EVENT_TELEPHONE_EVENT){
+ linphone_core_dtmf_received(lc,evd->info.telephone_event);
}
ortp_event_destroy(ev);
}
bool_t linphone_call_is_in_conference(const LinphoneCall *call) {
return call->params.in_conference;
}
+
+
+/**
+ * Perform a zoom of the video displayed during a call.
+ * @param zoom_factor a floating point number describing the zoom factor. A value 1.0 corresponds to no zoom applied.
+ * @param cx a floating point number pointing the horizontal center of the zoom to be applied. This value should be between 0.0 and 1.0.
+ * @param cy a floating point number pointing the vertical center of the zoom to be applied. This value should be between 0.0 and 1.0.
+ *
+ * cx and cy are updated in return in case their coordinates were to excentrated for the requested zoom factor. The zoom ensures that all the screen is fullfilled with the video.
+**/
+void linphone_call_zoom_video(LinphoneCall* call, float zoom_factor, float* cx, float* cy) {
+ VideoStream* vstream = call->videostream;
+ if (vstream) {
+ float zoom[3];
+
+ if (zoom_factor < 1)
+ zoom_factor = 1;
+ float halfsize = 0.5 * 1.0 / zoom_factor;
+
+ if ((*cx - halfsize) < 0)
+ *cx = 0 + halfsize;
+ if ((*cx + halfsize) > 1)
+ *cx = 1 - halfsize;
+ if ((*cy - halfsize) < 0)
+ *cy = 0 + halfsize;
+ if ((*cy + halfsize) > 1)
+ *cy = 1 - halfsize;
+
+ zoom[0] = zoom_factor;
+ zoom[1] = *cx;
+ zoom[2] = *cy;
+ ms_filter_call_method(vstream->output, MS_VIDEO_DISPLAY_ZOOM, &zoom);
+ }else ms_warning("Could not apply zoom: video output wasn't activated.");
+}
+
if (cl->refkey) lp_config_set_string(cfg,logsection,"refkey",cl->refkey);
lp_config_set_float(cfg,logsection,"quality",cl->quality);
lp_config_set_int(cfg,logsection,"video_enabled", cl->video_enabled);
+ lp_config_set_string(cfg,logsection,"call_id",cl->call_id);
}
for(;i<lc->max_call_logs;++i){
snprintf(logsection,sizeof(logsection),"call_log_%i",i);
if (tmp) cl->refkey=ms_strdup(tmp);
cl->quality=lp_config_get_float(cfg,logsection,"quality",-1);
cl->video_enabled=lp_config_get_int(cfg,logsection,"video_enabled",0);
+ cl->call_id=lp_config_get_string(cfg,logsection,"call_id",NULL);
+ if(cl->call_id) cl->call_id=ms_strdup(cl->call_id);
lc->call_logs=ms_list_append(lc->call_logs,cl);
}else break;
}
if (cl->from!=NULL) linphone_address_destroy(cl->from);
if (cl->to!=NULL) linphone_address_destroy(cl->to);
if (cl->refkey!=NULL) ms_free(cl->refkey);
+ if (cl->call_id) ms_free((void*)cl->call_id);
ms_free(cl);
}
sal_use_one_matching_codec_policy(lc->sal,lp_config_get_int(lc->config,"sip","only_one_codec",0));
sal_use_double_registrations(lc->sal,lp_config_get_int(lc->config,"sip","use_double_registrations",1));
sal_set_dscp(lc->sal,linphone_core_get_sip_dscp(lc));
+ sal_use_dates(lc->sal,lp_config_get_int(lc->config,"sip","put_date",0));
}
static void rtp_config_read(LinphoneCore *lc)
{
- int port;
+ int min_port, max_port;
int jitt_comp;
int nortp_timeout;
bool_t rtp_no_xmit_on_audio_mute;
bool_t adaptive_jitt_comp_enabled;
- port=lp_config_get_int(lc->config,"rtp","audio_rtp_port",7078);
- linphone_core_set_audio_port(lc,port);
+ if (lp_config_get_range(lc->config, "rtp", "audio_rtp_port", &min_port, &max_port, 7078, 7078) == TRUE) {
+ if (min_port <= 0) min_port = 1;
+ if (max_port > 65535) max_port = 65535;
+ linphone_core_set_audio_port_range(lc, min_port, max_port);
+ } else {
+ min_port = lp_config_get_int(lc->config, "rtp", "audio_rtp_port", 7078);
+ linphone_core_set_audio_port(lc, min_port);
+ }
- port=lp_config_get_int(lc->config,"rtp","video_rtp_port",9078);
- if (port==0) port=9078;
- linphone_core_set_video_port(lc,port);
+ if (lp_config_get_range(lc->config, "rtp", "video_rtp_port", &min_port, &max_port, 9078, 9078) == TRUE) {
+ if (min_port <= 0) min_port = 1;
+ if (max_port > 65535) max_port = 65535;
+ linphone_core_set_video_port_range(lc, min_port, max_port);
+ } else {
+ min_port = lp_config_get_int(lc->config, "rtp", "video_rtp_port", 9078);
+ linphone_core_set_video_port(lc, min_port);
+ }
jitt_comp=lp_config_get_int(lc->config,"rtp","audio_jitt_comp",60);
linphone_core_set_audio_jittcomp(lc,jitt_comp);
}
#define RANK_END 10000
-static const char *codec_pref_order[]={
- "SILK",
- "speex",
- "iLBC",
- "amr",
- "gsm",
- "pcmu",
- "pcma",
- "VP8",
- "H264",
- "MP4V-ES",
- "H263-1998",
- NULL,
+
+typedef struct codec_desc{
+ const char *name;
+ int rate;
+}codec_desc_t;
+
+static codec_desc_t codec_pref_order[]={
+ {"SILK", 16000},
+ {"speex", 16000},
+ {"speex", 8000},
+ {"pcmu",8000},
+ {"pcma",8000},
+ {"VP8",90000},
+ {"H264",90000},
+ {"MP4V-ES",90000},
+ {NULL,0}
};
-static int find_codec_rank(const char *mime){
+static int find_codec_rank(const char *mime, int clock_rate){
int i;
- for(i=0;codec_pref_order[i]!=NULL;++i){
- if (strcasecmp(codec_pref_order[i],mime)==0)
+ for(i=0;codec_pref_order[i].name!=NULL;++i){
+ if (strcasecmp(codec_pref_order[i].name,mime)==0 && clock_rate==codec_pref_order[i].rate)
return i;
}
return RANK_END;
static int codec_compare(const PayloadType *a, const PayloadType *b){
int ra,rb;
- ra=find_codec_rank(a->mime_type);
- rb=find_codec_rank(b->mime_type);
+ ra=find_codec_rank(a->mime_type,a->clock_rate);
+ rb=find_codec_rank(b->mime_type,b->clock_rate);
if (ra>rb) return 1;
if (ra<rb) return -1;
return 0;
if (pt && ms_filter_codec_supported(pt->mime_type)){
if (ms_list_find(l,pt)==NULL){
/*unranked codecs are disabled by default*/
- if (find_codec_rank(pt->mime_type)!=RANK_END){
+ if (find_codec_rank(pt->mime_type, pt->clock_rate)!=RANK_END){
payload_type_set_flag(pt,PAYLOAD_TYPE_ENABLED);
}
ms_message("Adding new codec %s/%i with fmtp %s",
const char *str;
#ifdef VIDEO_ENABLED
LinphoneVideoPolicy vpol;
+ memset(&vpol, 0, sizeof(LinphoneVideoPolicy));
#endif
build_video_devices_table(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
**/
int linphone_core_get_audio_port(const LinphoneCore *lc)
{
- return lc->rtp_conf.audio_rtp_port;
+ return lc->rtp_conf.audio_rtp_min_port;
+}
+
+/**
+ * Get the audio port range from which is randomly chosen the UDP port used for audio streaming.
+ *
+ * @ingroup network_parameters
+ */
+void linphone_core_get_audio_port_range(const LinphoneCore *lc, int *min_port, int *max_port)
+{
+ *min_port = lc->rtp_conf.audio_rtp_min_port;
+ *max_port = lc->rtp_conf.audio_rtp_max_port;
}
/**
* @ingroup network_parameters
**/
int linphone_core_get_video_port(const LinphoneCore *lc){
- return lc->rtp_conf.video_rtp_port;
+ return lc->rtp_conf.video_rtp_min_port;
+}
+
+/**
+ * Get the video port range from which is randomly chosen the UDP port used for video streaming.
+ *
+ * @ingroup network_parameters
+ */
+void linphone_core_get_video_port_range(const LinphoneCore *lc, int *min_port, int *max_port)
+{
+ *min_port = lc->rtp_conf.video_rtp_min_port;
+ *max_port = lc->rtp_conf.video_rtp_max_port;
}
**/
void linphone_core_set_audio_port(LinphoneCore *lc, int port)
{
- lc->rtp_conf.audio_rtp_port=port;
+ lc->rtp_conf.audio_rtp_min_port=lc->rtp_conf.audio_rtp_max_port=port;
+}
+
+/**
+ * Sets the UDP port range from which to randomly select the port used for audio streaming.
+ */
+void linphone_core_set_audio_port_range(LinphoneCore *lc, int min_port, int max_port)
+{
+ lc->rtp_conf.audio_rtp_min_port=min_port;
+ lc->rtp_conf.audio_rtp_max_port=max_port;
}
/**
* @ingroup network_parameters
**/
void linphone_core_set_video_port(LinphoneCore *lc, int port){
- lc->rtp_conf.video_rtp_port=port;
+ lc->rtp_conf.video_rtp_min_port=lc->rtp_conf.video_rtp_max_port=port;
+}
+
+/**
+ * Sets the UDP port range from which to randomly select the port used for video streaming.
+ */
+void linphone_core_set_video_port_range(LinphoneCore *lc, int min_port, int max_port)
+{
+ lc->rtp_conf.video_rtp_min_port=min_port;
+ lc->rtp_conf.video_rtp_max_port=max_port;
}
/**
strncpy(_ua_version,ver,sizeof(_ua_version));
}
+const char *linphone_core_get_user_agent_name(void){
+ return _ua_name;
+}
+
+const char *linphone_core_get_user_agent_version(void){
+ return _ua_version;
+}
+
static void transport_error(LinphoneCore *lc, const char* transport, int port){
char *msg=ortp_strdup_printf("Could not start %s transport on port %i, maybe this port is already used.",transport,port);
ms_warning("%s",msg);
if (ecs==LinphoneEcCalibratorDone){
int len=lp_config_get_int(lc->config,"sound","ec_tail_len",0);
lp_config_set_int(lc->config, "sound", "ec_delay",MAX(lc->ecc->delay-(len/2),0));
+ } else if (ecs == LinphoneEcCalibratorFailed) {
+ lp_config_set_int(lc->config, "sound", "ec_delay", LP_CONFIG_DEFAULT_INT(lc->config, "ec_delay", 250));
+ } else if (ecs == LinphoneEcCalibratorDoneNoEcho) {
+ linphone_core_enable_echo_cancellation(lc, FALSE);
}
ec_calibrator_destroy(lc->ecc);
lc->ecc=NULL;
ms_warning("ICE candidates gathering from [%s] has not finished yet, proceed with the call without ICE anyway."
,linphone_core_get_stun_server(lc));
linphone_call_delete_ice_session(call);
- linphone_call_stop_media_streams(call);
+ linphone_call_stop_media_streams_for_ice_gathering(call);
}
- linphone_core_start_invite(lc,call,NULL);
+ linphone_core_start_invite(lc,call);
}
if (call->state==LinphoneCallIncomingReceived){
elapsed=curtime-call->start_time;
}
if ((ice_ready == TRUE) && (ping_ready == TRUE)) {
- return linphone_core_start_invite(lc, call, dest_proxy);
+ return linphone_core_start_invite(lc, call);
}
return 0;
}
-int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, LinphoneProxyConfig *dest_proxy){
+int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call){
int err;
char *contact;
char *real_url,*barmsg;
char *from;
+ LinphoneProxyConfig *dest_proxy=call->dest_proxy;
/*try to be best-effort in giving real local or routable contact address */
contact=get_fixed_contact(lc,call,dest_proxy);
linphone_call_init_media_streams(call);
if (lc->ringstream==NULL)
audio_stream_prepare_sound(call->audiostream,lc->sound_conf.play_sndcard,lc->sound_conf.capt_sndcard);
+ call->localdesc=create_local_media_description(lc,call);
if (!lc->sip_conf.sdp_200_ack){
call->media_pending=TRUE;
- if (call->ice_session != NULL)
- linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session);
sal_call_set_local_media_description(call->op,call->localdesc);
}
real_url=linphone_address_as_string(call->log->to);
from=linphone_address_as_string(call->log->from);
err=sal_call(call->op,from,real_url);
+ call->log->call_id=ms_strdup(sal_op_get_call_id(call->op)); /*must be known at that time*/
if (lc->sip_conf.sdp_200_ack){
call->media_pending=TRUE;
{
const char *route=NULL;
const char *from=NULL;
- LinphoneProxyConfig *proxy=NULL;
+ LinphoneProxyConfig *proxy=NULL,*dest_proxy=NULL;
LinphoneAddress *parsed_url2=NULL;
char *real_url=NULL;
- LinphoneProxyConfig *dest_proxy=NULL;
LinphoneCall *call;
bool_t use_ice = FALSE;
parsed_url2=linphone_address_new(from);
call=linphone_call_new_outgoing(lc,parsed_url2,linphone_address_clone(addr),params);
+ call->dest_proxy=dest_proxy;
sal_op_set_route(call->op,route);
if(linphone_core_add_call(lc,call)!= 0)
if (linphone_core_gather_ice_candidates(lc,call)<0) {
/* Ice candidates gathering failed, proceed with the call anyway. */
linphone_call_delete_ice_session(call);
- linphone_call_stop_media_streams(call);
+ linphone_call_stop_media_streams_for_ice_gathering(call);
} else {
use_ice = TRUE;
}
}
- if (dest_proxy==NULL && lc->sip_conf.ping_with_options==TRUE){
+ if (call->dest_proxy==NULL && lc->sip_conf.ping_with_options==TRUE){
/*defer the start of the call after the OPTIONS ping*/
call->ping_replied=FALSE;
call->ping_op=sal_op_new(lc->sal);
sal_op_set_user_pointer(call->ping_op,call);
call->start_time=time(NULL);
}else{
- if (use_ice==FALSE) linphone_core_start_invite(lc,call,dest_proxy);
+ if (use_ice==FALSE) linphone_core_start_invite(lc,call);
}
if (real_url!=NULL) ms_free(real_url);
bool_t propose_early_media=lp_config_get_int(lc->config,"sip","incoming_calls_early_media",FALSE);
const char *ringback_tone=linphone_core_get_remote_ringback_tone (lc);
- if (call->ice_session != NULL)
- linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session);
+ call->localdesc=create_local_media_description(lc,call);
+ sal_call_set_local_media_description(call->op,call->localdesc);
md=sal_call_get_final_media_description(call->op);
if (md && sal_media_description_empty(md)){
sal_call_decline(call->op,SalReasonMedia,NULL);
int linphone_core_start_update_call(LinphoneCore *lc, LinphoneCall *call){
const char *subject;
call->camera_active=call->params.has_video;
- update_local_media_description(lc,call);
if (call->ice_session != NULL)
linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session);
int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){
int err=0;
if (params!=NULL){
+ linphone_call_set_state(call,LinphoneCallUpdating,"Updating call");
#ifdef VIDEO_ENABLED
bool_t has_video = call->params.has_video;
if ((call->ice_session != NULL) && (call->videostream != NULL) && !params->has_video) {
call->videostream->ice_check_list = NULL;
}
call->params = *params;
- if ((call->ice_session != NULL) && (ice_session_state(call->ice_session) != IS_Completed) && !has_video && params->has_video) {
+ update_local_media_description(lc, call);
+ if ((call->ice_session != NULL) && !has_video && call->params.has_video) {
/* Defer call update until the ICE candidates gathering process has finished. */
ms_message("Defer call update to gather ICE candidates");
- update_local_media_description(lc, call);
linphone_call_init_video_stream(call);
video_stream_prepare_video(call->videostream);
if (linphone_core_gather_ice_candidates(lc,call)<0) {
* @return 0 if sucessful, -1 otherwise (actually when this function call is performed outside ot #LinphoneCallUpdatedByRemote state).
**/
int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){
+#ifdef VIDEO_ENABLED
bool_t old_has_video = call->params.has_video;
+#endif
if (call->state!=LinphoneCallUpdatedByRemote){
ms_error("linphone_core_accept_update(): invalid state %s to call this function.",
linphone_call_state_to_string(call->state));
}else
call->params=*params;
+ if (call->params.has_video && !linphone_core_video_enabled(lc)){
+ ms_warning("linphone_core_accept_call_update(): requested video but video support is globally disabled. Refusing video.");
+ call->params.has_video=FALSE;
+ }
if (call->current_params.in_conference) {
ms_warning("Video isn't supported in conference");
call->params.has_video = FALSE;
}
+ call->params.has_video &= linphone_core_media_description_contains_video_stream(sal_call_get_remote_media_description(call->op));
call->camera_active=call->params.has_video;
update_local_media_description(lc,call);
if (call->ice_session != NULL) {
**/
int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params)
{
- LinphoneProxyConfig *cfg=NULL,*dest_proxy=NULL;
+ LinphoneProxyConfig *cfg=NULL;
const char *contact=NULL;
SalOp *replaced;
SalMediaDescription *new_md;
}
linphone_core_get_default_proxy(lc,&cfg);
- dest_proxy=cfg;
- dest_proxy=linphone_core_lookup_known_proxy(lc,call->log->to);
+ call->dest_proxy=cfg;
+ call->dest_proxy=linphone_core_lookup_known_proxy(lc,call->log->to);
- if (cfg!=dest_proxy && dest_proxy!=NULL) {
+ if (cfg!=call->dest_proxy && call->dest_proxy!=NULL) {
ms_message("Overriding default proxy setting for this call:");
- ms_message("The used identity will be %s",linphone_proxy_config_get_identity(dest_proxy));
+ ms_message("The used identity will be %s",linphone_proxy_config_get_identity(call->dest_proxy));
}
/*try to be best-effort in giving real local or routable contact address*/
- contact=get_fixed_contact(lc,call,dest_proxy);
+ contact=get_fixed_contact(lc,call,call->dest_proxy);
if (contact)
sal_op_set_contact(call->op,contact);
- if (call->audiostream==NULL)
- linphone_call_init_media_streams(call);
- if (!was_ringing && call->audiostream->ticker==NULL){
- audio_stream_prepare_sound(call->audiostream,lc->sound_conf.play_sndcard,lc->sound_conf.capt_sndcard);
- }
-
if (params){
call->params=*params;
+ call->params.has_video &= linphone_core_media_description_contains_video_stream(sal_call_get_remote_media_description(call->op));
call->camera_active=call->params.has_video;
update_local_media_description(lc,call);
sal_call_set_local_media_description(call->op,call->localdesc);
}
+ if (call->audiostream==NULL)
+ linphone_call_init_media_streams(call);
+ if (!was_ringing && call->audiostream->ticker==NULL){
+ audio_stream_prepare_sound(call->audiostream,lc->sound_conf.play_sndcard,lc->sound_conf.capt_sndcard);
+ }
+
sal_call_accept(call->op);
if (lc->vtable.display_status!=NULL)
lc->vtable.display_status(lc,_("Connected."));
#endif
lc->video_conf.capture=vcap_enabled;
lc->video_conf.display=display_enabled;
-
+ if (linphone_core_ready(lc)){
+ lp_config_set_int(lc->config,"video","display",lc->video_conf.display);
+ lp_config_set_int(lc->config,"video","capture",lc->video_conf.capture);
+ }
/* need to re-apply network bandwidth settings*/
linphone_core_set_download_bandwidth(lc,
linphone_core_get_download_bandwidth(lc));
**/
void linphone_core_enable_video_preview(LinphoneCore *lc, bool_t val){
lc->video_conf.show_local=val;
+ if (linphone_core_ready(lc))
+ lp_config_set_int(lc->config,"video","show_local",val);
}
/**
if (call && call->videostream){
video_stream_enable_self_view(call->videostream,val);
}
+ if (linphone_core_ready(lc)){
+ lp_config_set_int(lc->config,"video","self_view",val);
+ }
#endif
}
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
}
void rtp_config_uninit(LinphoneCore *lc)
{
rtp_config_t *config=&lc->rtp_conf;
- lp_config_set_int(lc->config,"rtp","audio_rtp_port",config->audio_rtp_port);
- lp_config_set_int(lc->config,"rtp","video_rtp_port",config->video_rtp_port);
+ if (config->audio_rtp_min_port == config->audio_rtp_max_port) {
+ lp_config_set_int(lc->config, "rtp", "audio_rtp_port", config->audio_rtp_min_port);
+ } else {
+ lp_config_set_range(lc->config, "rtp", "audio_rtp_port", config->audio_rtp_min_port, config->audio_rtp_max_port);
+ }
+ if (config->video_rtp_min_port == config->video_rtp_max_port) {
+ lp_config_set_int(lc->config, "rtp", "video_rtp_port", config->video_rtp_min_port);
+ } else {
+ lp_config_set_range(lc->config, "rtp", "video_rtp_port", config->video_rtp_min_port, config->video_rtp_max_port);
+ }
lp_config_set_int(lc->config,"rtp","audio_jitt_comp",config->audio_jitt_comp);
lp_config_set_int(lc->config,"rtp","video_jitt_comp",config->video_jitt_comp);
lp_config_set_int(lc->config,"rtp","nortp_timeout",config->nortp_timeout);
lp_config_set_int(lc->config,"rtp","video_jitt_comp_enabled",config->video_adaptive_jitt_comp_enabled);
}
-void sound_config_uninit(LinphoneCore *lc)
+static void sound_config_uninit(LinphoneCore *lc)
{
sound_config_t *config=&lc->sound_conf;
ms_free(config->cards);
ms_snd_card_manager_destroy();
}
-void video_config_uninit(LinphoneCore *lc)
+static void video_config_uninit(LinphoneCore *lc)
{
lp_config_set_string(lc->config,"video","size",video_size_get_name(linphone_core_get_preferred_video_size(lc)));
lp_config_set_int(lc->config,"video","display",lc->video_conf.display);
lp_config_set_int(lc->config,"video","capture",lc->video_conf.capture);
- lp_config_set_int(lc->config,"video","show_local",linphone_core_video_preview_enabled(lc));
- lp_config_set_int(lc->config,"video","self_view",linphone_core_self_view_enabled(lc));
if (lc->video_conf.cams)
ms_free(lc->video_conf.cams);
}
case LinphoneCallConnected:
case LinphoneCallRefered:
case LinphoneCallIncomingEarlyMedia:
- case LinphoneCallUpdated:
+ case LinphoneCallUpdating:
return TRUE;
default:
break;
void linphone_core_init_default_params(LinphoneCore*lc, LinphoneCallParams *params) {
params->has_video=linphone_core_video_enabled(lc) && lc->video_policy.automatically_initiate;
- params->media_encryption=linphone_core_get_media_encryption(lc);
+ params->media_encryption=linphone_core_get_media_encryption(lc);
params->in_conference=FALSE;
}
-void linphone_call_zoom_video(LinphoneCall* call, float zoom_factor, float* cx, float* cy) {
- VideoStream* vstream = call->videostream;
- if (vstream) {
- float zoom[3];
-
- if (zoom_factor < 1)
- zoom_factor = 1;
- float halfsize = 0.5 * 1.0 / zoom_factor;
-
- if ((*cx - halfsize) < 0)
- *cx = 0 + halfsize;
- if ((*cx + halfsize) > 1)
- *cx = 1 - halfsize;
- if ((*cy - halfsize) < 0)
- *cy = 0 + halfsize;
- if ((*cy + halfsize) > 1)
- *cy = 1 - halfsize;
-
- zoom[0] = zoom_factor;
- zoom[1] = *cx;
- zoom[2] = *cy;
- ms_filter_call_method(vstream->output, MS_VIDEO_DISPLAY_ZOOM, &zoom);
- }else ms_warning("Could not apply zoom: video output wasn't activated.");
-}
+
void linphone_core_set_device_identifier(LinphoneCore *lc,const char* device_id) {
if (lc->device_id) ms_free(lc->device_id);
LinphoneCallStatus status; /**< The status of the call*/
LinphoneAddress *from; /**<Originator of the call as a LinphoneAddress object*/
LinphoneAddress *to; /**<Destination of the call as a LinphoneAddress object*/
- char start_date[128]; /**<Human readable string containg the start date*/
+ char start_date[128]; /**<Human readable string containing the start date*/
int duration; /**<Duration of the call in seconds*/
char *refkey;
void *user_pointer;
int video_enabled;
struct _LinphoneCore *lc;
time_t start_date_time; /**Start date of the call in seconds as expressed in a time_t */
+ const char* call_id; /**unique id of a call*/
} LinphoneCallLog;
bool_t linphone_call_params_local_conference_mode(const LinphoneCallParams *cp);
void linphone_call_params_set_audio_bandwidth_limit(LinphoneCallParams *cp, int bw);
void linphone_call_params_destroy(LinphoneCallParams *cp);
-
+/**
+ * @ingroup call_control
+ * Use to know if this call has been configured in low bandwidth mode.
+ * This mode can be automatically discovered thanks to a stun server when activate_edge_workarounds=1 in section [net] of configuration file
+ * <br> When enabled, this param may transform a call request with video in audio only mode.
+ * @return TRUE if low bandwidth has been configured/detected
+ */
+bool_t linphone_call_params_low_bandwidth_enabled(const LinphoneCallParams *cp);
/**
* Enum describing failure reasons.
* @ingroup initializing
#define LINPHONE_CALL_STATS_AUDIO 0
#define LINPHONE_CALL_STATS_VIDEO 1
+/**
+ * Enum describing ICE states.
+ * @ingroup initializing
+**/
+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 */
+ LinphoneIceStateRelayConnection /**< ICE has established a connection through a relay */
+};
+
+/**
+ * Enum describing Ice states.
+ * @ingroup initializing
+**/
+typedef enum _LinphoneIceState LinphoneIceState;
+
/**
* The LinphoneCallStats objects carries various statistic informations regarding quality of audio or video streams.
*
mblk_t* received_rtcp; /**<Last RTCP packet received, as a mblk_t structure. See oRTP documentation for details how to extract information from it*/
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*/
};
/**
LinphoneCallPausedByRemote, /**<The call is paused by remote end*/
LinphoneCallUpdatedByRemote, /**<The call's parameters change is requested by remote end, used for example when video is added by remote */
LinphoneCallIncomingEarlyMedia, /**<We are proposing early media to an incoming call */
- LinphoneCallUpdated, /**<The remote accepted the call update initiated by us */
+ LinphoneCallUpdating, /**<A call update has been initiated by us */
LinphoneCallReleased /**< The call object is no more retained by the core */
} LinphoneCallState;
void linphone_call_set_user_pointer(LinphoneCall *call, void *user_pointer);
void linphone_call_set_next_video_frame_decoded_callback(LinphoneCall *call, LinphoneCallCbFunc cb, void* user_data);
LinphoneCallState linphone_call_get_transfer_state(LinphoneCall *call);
+void linphone_call_zoom_video(LinphoneCall* call, float zoom_factor, float* cx, float* cy);
/**
* Return TRUE if this call is currently part of a conference
*@param call #LinphoneCall
/*sets the user-agent string in sip messages, must be set before linphone_core_new() or linphone_core_init() */
void linphone_core_set_user_agent(const char *ua_name, const char *version);
const char *linphone_core_get_version(void);
+const char *linphone_core_get_user_agent_name(void);
+const char *linphone_core_get_user_agent_version(void);
LinphoneCore *linphone_core_new(const LinphoneCoreVTable *vtable,
const char *config_path, const char *factory_config, void* userdata);
/* function to be periodically called in a main loop */
+/* For ICE to work properly it should be called every 20ms */
void linphone_core_iterate(LinphoneCore *lc);
#if 0 /*not implemented yet*/
/**
int linphone_core_get_audio_port(const LinphoneCore *lc);
+void linphone_core_get_audio_port_range(const LinphoneCore *lc, int *min_port, int *max_port);
+
int linphone_core_get_video_port(const LinphoneCore *lc);
+void linphone_core_get_video_port_range(const LinphoneCore *lc, int *min_port, int *max_port);
+
int linphone_core_get_nortp_timeout(const LinphoneCore *lc);
void linphone_core_set_audio_port(LinphoneCore *lc, int port);
+void linphone_core_set_audio_port_range(LinphoneCore *lc, int min_port, int max_port);
+
void linphone_core_set_video_port(LinphoneCore *lc, int port);
+void linphone_core_set_video_port_range(LinphoneCore *lc, int min_port, int max_port);
+
void linphone_core_set_nortp_timeout(LinphoneCore *lc, int port);
void linphone_core_set_use_info_for_dtmf(LinphoneCore *lc, bool_t use_info);
*/
LinphoneTunnel *linphone_core_get_tunnel(LinphoneCore *lc);
-void linphone_call_zoom_video(LinphoneCall* call, float zoom_factor, float* cx, float* cy);
-
void linphone_core_set_sip_dscp(LinphoneCore *lc, int dscp);
int linphone_core_get_sip_dscp(const LinphoneCore *lc);
void linphone_core_set_video_dscp(LinphoneCore *lc, int dscp);
int linphone_core_get_video_dscp(const LinphoneCore *lc);
+
+
#ifdef __cplusplus
}
#endif
#ifdef ANDROID
static void linphone_android_log_handler(OrtpLogLevel lev, const char *fmt, va_list args){
int prio;
+ char str[4096];
+ char *current;
+ char *next;
switch(lev){
case ORTP_DEBUG: prio = ANDROID_LOG_DEBUG; break;
case ORTP_MESSAGE: prio = ANDROID_LOG_INFO; break;
case ORTP_FATAL: prio = ANDROID_LOG_FATAL; break;
default: prio = ANDROID_LOG_DEFAULT; break;
}
- __android_log_vprint(prio, LOG_DOMAIN, fmt, args);
+ vsnprintf(str, sizeof(str) - 1, fmt, args);
+ str[sizeof(str) - 1] = '\0';
+ if (strlen(str) < 512) {
+ __android_log_write(prio, LOG_DOMAIN, str);
+ } else {
+ current = str;
+ while ((next = strchr(current, '\n')) != NULL) {
+ *next = '\0';
+ __android_log_write(prio, LOG_DOMAIN, current);
+ current = next + 1;
+ }
+ __android_log_write(prio, LOG_DOMAIN, current);
+ }
}
int dumbMethodForAllowingUsageOfCpuFeaturesFromStaticLibMediastream() {
vTable.call_encryption_changed = callEncryptionChange;
vTable.text_received = text_received;
vTable.message_received = message_received;
+ vTable.dtmf_received = dtmf_received;
vTable.new_subscription_request = new_subscription_request;
vTable.notify_presence_recv = notify_presence_recv;
+ vTable.call_stats_updated = callStatsUpdated;
listenerClass = (jclass)env->NewGlobalRef(env->GetObjectClass( alistener));
callStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCall$State"));
callStateFromIntId = env->GetStaticMethodID(callStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneCall$State;");
+ /*callStatsUpdated(LinphoneCore lc, LinphoneCall call, LinphoneCallStats stats);*/
+ callStatsUpdatedId = env->GetMethodID(listenerClass, "callStatsUpdated", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneCallStats;)V");
+
chatMessageStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneChatMessage$State"));
chatMessageStateFromIntId = env->GetStaticMethodID(chatMessageStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneChatMessage$State;");
/*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");
+ dtmfReceivedId = env->GetMethodID(listenerClass,"dtmfReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;I)V");
proxyClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneProxyConfigImpl"));
proxyCtrId = env->GetMethodID(proxyClass,"<init>", "(J)V");
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");
addressClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneAddressImpl"));
addressCtrId =env->GetMethodID(addressClass,"<init>", "(J)V");
+ callStatsClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCallStatsImpl"));
+ callStatsId = env->GetMethodID(callStatsClass, "<init>", "(JJ)V");
+ callSetAudioStatsId = env->GetMethodID(callClass, "setAudioStats", "(Lorg/linphone/core/LinphoneCallStats;)V");
+ callSetVideoStatsId = env->GetMethodID(callClass, "setVideoStats", "(Lorg/linphone/core/LinphoneCallStats;)V");
}
~LinphoneCoreData() {
env->DeleteGlobalRef(globalStateClass);
env->DeleteGlobalRef(registrationStateClass);
env->DeleteGlobalRef(callStateClass);
+ env->DeleteGlobalRef(callStatsClass);
env->DeleteGlobalRef(chatMessageStateClass);
env->DeleteGlobalRef(proxyClass);
env->DeleteGlobalRef(callClass);
jmethodID notifyPresenceReceivedId;
jmethodID textReceivedId;
jmethodID messageReceivedId;
+ jmethodID dtmfReceivedId;
+ jmethodID callStatsUpdatedId;
jclass globalStateClass;
jmethodID globalStateId;
jmethodID callStateId;
jmethodID callStateFromIntId;
+ jclass callStatsClass;
+ jmethodID callStatsId;
+ jmethodID callSetAudioStatsId;
+ jmethodID callSetVideoStatsId;
+
jclass chatMessageStateClass;
jmethodID chatMessageStateFromIntId;
,env->NewObject(lcData->friendClass,lcData->friendCtrId,(jlong)my_friend)
,url ? env->NewStringUTF(url) : NULL);
}
+ static void dtmf_received(LinphoneCore *lc, LinphoneCall *call, int dtmf) {
+ JNIEnv *env = 0;
+ jint result = jvm->AttachCurrentThread(&env,NULL);
+ if (result != 0) {
+ ms_error("cannot attach VM\n");
+ return;
+ }
+ LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data(lc);
+ env->CallVoidMethod(lcData->listener
+ ,lcData->dtmfReceivedId
+ ,lcData->core
+ ,lcData->getCall(env,call)
+ ,dtmf);
+ }
static void text_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from, const char *message) {
JNIEnv *env = 0;
jint result = jvm->AttachCurrentThread(&env,NULL);
,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) {
}
}
+ static void callStatsUpdated(LinphoneCore *lc, LinphoneCall* call, const LinphoneCallStats *stats) {
+ JNIEnv *env = 0;
+ jobject statsobj;
+ jobject callobj;
+ jint result = jvm->AttachCurrentThread(&env,NULL);
+ if (result != 0) {
+ ms_error("cannot attach VM\n");
+ return;
+ }
+ LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data(lc);
+ statsobj = env->NewObject(lcData->callStatsClass, lcData->callStatsId, (jlong)call, (jlong)stats);
+ callobj = lcData->getCall(env, call);
+ if (stats->type == LINPHONE_CALL_STATS_AUDIO)
+ env->CallVoidMethod(callobj, lcData->callSetAudioStatsId, statsobj);
+ else
+ env->CallVoidMethod(callobj, lcData->callSetVideoStatsId, statsobj);
+ env->CallVoidMethod(lcData->listener, lcData->callStatsUpdatedId, lcData->core, callobj, statsobj);
+ }
};
if (factoryConfig) env->ReleaseStringUTFChars(jfactoryConfig, factoryConfig);
return nativePtr;
}
-extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_delete(JNIEnv* env
+extern "C" void Java_org_linphone_core_LinphoneCoreImpl_delete(JNIEnv* env
,jobject thiz
,jlong lc) {
LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data((LinphoneCore*)lc);
delete lcData;
}
-extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_clearProxyConfigs(JNIEnv* env, jobject thiz,jlong lc) {
+extern "C" void Java_org_linphone_core_LinphoneCoreImpl_clearProxyConfigs(JNIEnv* env, jobject thiz,jlong lc) {
linphone_core_clear_proxy_config((LinphoneCore*)lc);
}
return jProxies;
}
-extern "C" int Java_org_linphone_core_LinphoneCoreImpl_addProxyConfig( JNIEnv* env
+extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_addProxyConfig( JNIEnv* env
,jobject thiz
,jobject jproxyCfg
,jlong lc
LinphoneProxyConfig* proxy = (LinphoneProxyConfig*)pc;
linphone_proxy_config_set_user_data(proxy, env->NewGlobalRef(jproxyCfg));
- return linphone_core_add_proxy_config((LinphoneCore*)lc,(LinphoneProxyConfig*)pc);
+ return (jint)linphone_core_add_proxy_config((LinphoneCore*)lc,(LinphoneProxyConfig*)pc);
}
-extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_clearAuthInfos(JNIEnv* env, jobject thiz,jlong lc) {
+extern "C" void Java_org_linphone_core_LinphoneCoreImpl_clearAuthInfos(JNIEnv* env, jobject thiz,jlong lc) {
linphone_core_clear_all_auth_info((LinphoneCore*)lc);
}
,jobject thiz
,jlong lc) {
- return linphone_core_in_call((LinphoneCore*)lc);
+ return (jboolean)linphone_core_in_call((LinphoneCore*)lc);
}
extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isInComingInvitePending( JNIEnv* env
,jobject thiz
,jlong lc) {
- return linphone_core_inc_invite_pending((LinphoneCore*)lc);
+ return (jboolean)linphone_core_inc_invite_pending((LinphoneCore*)lc);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_acceptCall( JNIEnv* env
,jobject thiz
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getNumberOfCallLogs( JNIEnv* env
,jobject thiz
,jlong lc) {
- return ms_list_size(linphone_core_get_call_logs((LinphoneCore*)lc));
+ return (jint)ms_list_size(linphone_core_get_call_logs((LinphoneCore*)lc));
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setNetworkStateReachable( JNIEnv* env
,jobject thiz
extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isNetworkStateReachable( JNIEnv* env
,jobject thiz
,jlong lc) {
- return linphone_core_is_network_reachable((LinphoneCore*)lc);
+ return (jboolean)linphone_core_is_network_reachable((LinphoneCore*)lc);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setPlaybackGain( JNIEnv* env
linphone_core_set_playback_gain_db((LinphoneCore*)lc,gain);
}
-extern "C" float Java_org_linphone_core_LinphoneCoreImpl_getPlaybackGain( JNIEnv* env
+extern "C" jfloat Java_org_linphone_core_LinphoneCoreImpl_getPlaybackGain( JNIEnv* env
,jobject thiz
,jlong lc) {
- return linphone_core_get_playback_gain_db((LinphoneCore*)lc);
+ return (jfloat)linphone_core_get_playback_gain_db((LinphoneCore*)lc);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_muteMic( JNIEnv* env
linphone_core_stop_dtmf((LinphoneCore*)lc);
}
-extern "C" void Java_org_linphone_core_LinphoneCoreImpl_getMissedCallsCount(JNIEnv* env
+extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getMissedCallsCount(JNIEnv* env
,jobject thiz
,jlong lc) {
- linphone_core_get_missed_calls_count((LinphoneCore*)lc);
+ return (jint)linphone_core_get_missed_calls_count((LinphoneCore*)lc);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_resetMissedCallsCount(JNIEnv* env
extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isMicMuted( JNIEnv* env
,jobject thiz
,jlong lc) {
- return linphone_core_is_mic_muted((LinphoneCore*)lc);
+ return (jboolean)linphone_core_is_mic_muted((LinphoneCore*)lc);
}
extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_findPayloadType(JNIEnv* env
,jobject thiz
return jCodecs;
}
-extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_enablePayloadType(JNIEnv* env
+extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_enablePayloadType(JNIEnv* env
,jobject thiz
,jlong lc
,jlong pt
,jboolean enable) {
- return linphone_core_enable_payload_type((LinphoneCore*)lc,(PayloadType*)pt,enable);
+ return (jint)linphone_core_enable_payload_type((LinphoneCore*)lc,(PayloadType*)pt,enable);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_enableEchoCancellation(JNIEnv* env
,jobject thiz
,jobject thiz
,jlong lc
) {
- return linphone_core_echo_cancellation_enabled((LinphoneCore*)lc);
+ return (jboolean)linphone_core_echo_cancellation_enabled((LinphoneCore*)lc);
}
extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isEchoLimiterEnabled(JNIEnv* env
,jobject thiz
,jlong lc
) {
- return linphone_core_echo_limiter_enabled((LinphoneCore*)lc);
+ return (jboolean)linphone_core_echo_limiter_enabled((LinphoneCore*)lc);
}
extern "C" jobject Java_org_linphone_core_LinphoneCoreImpl_getCurrentCall(JNIEnv* env
if (alternative_contact) env->ReleaseStringUTFChars(jalternative_contact, alternative_contact);
}
-extern "C" long Java_org_linphone_core_LinphoneCoreImpl_createChatRoom(JNIEnv* env
+extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_createChatRoom(JNIEnv* env
,jobject thiz
,jlong lc
,jstring jto) {
const char* to = env->GetStringUTFChars(jto, NULL);
LinphoneChatRoom* lResult = linphone_core_create_chat_room((LinphoneCore*)lc,to);
env->ReleaseStringUTFChars(jto, to);
- return (long)lResult;
+ return (jlong)lResult;
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_enableVideo(JNIEnv* env
extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isVideoEnabled(JNIEnv* env
,jobject thiz
,jlong lc) {
- return linphone_core_video_enabled((LinphoneCore*)lc);
+ return (jboolean)linphone_core_video_enabled((LinphoneCore*)lc);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setPlayFile(JNIEnv* env
,jobject thiz
extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isKeepAliveEnabled(JNIEnv* env
,jobject thiz
,jlong lc) {
- return linphone_core_keep_alive_enabled((LinphoneCore*)lc);
+ return (jboolean)linphone_core_keep_alive_enabled((LinphoneCore*)lc);
}
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_startEchoCalibration(JNIEnv* env
,jobject thiz
,jlong lc
,jobject data) {
- return linphone_core_start_echo_calibration((LinphoneCore*)lc
+ return (jint)linphone_core_start_echo_calibration((LinphoneCore*)lc
, LinphoneCoreData::ecCalibrationStatus
, data?env->NewGlobalRef(data):NULL);
}
-extern "C" int Java_org_linphone_core_LinphoneCoreImpl_getMediaEncryption(JNIEnv* env
+extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getMediaEncryption(JNIEnv* env
,jobject thiz
,jlong lc
) {
- return (int)linphone_core_get_media_encryption((LinphoneCore*)lc);
+ return (jint)linphone_core_get_media_encryption((LinphoneCore*)lc);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setMediaEncryption(JNIEnv* env
,jobject thiz
,jlong lc
- ,int menc) {
+ ,jint menc) {
linphone_core_set_media_encryption((LinphoneCore*)lc,(LinphoneMediaEncryption)menc);
}
-extern "C" int Java_org_linphone_core_LinphoneCallParamsImpl_getMediaEncryption(JNIEnv* env
- ,jobject thiz
- ,jlong cp
- ) {
- return (int)linphone_call_params_get_media_encryption((LinphoneCallParams*)cp);
-}
-
extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_mediaEncryptionSupported(JNIEnv* env
,jobject thiz
,jlong lc, jint menc
) {
- return linphone_core_media_encryption_supported((LinphoneCore*)lc,(LinphoneMediaEncryption)menc);
+ return (jboolean)linphone_core_media_encryption_supported((LinphoneCore*)lc,(LinphoneMediaEncryption)menc);
}
-extern "C" void Java_org_linphone_core_LinphoneCallParamsImpl_setMediaEncryption(JNIEnv* env
- ,jobject thiz
- ,jlong cp
- ,int jmenc) {
- linphone_call_params_set_media_encryption((LinphoneCallParams*)cp,(LinphoneMediaEncryption)jmenc);
-}
-
-extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_getMediaEncryptionMandatory(JNIEnv* env
+extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isMediaEncryptionMandatory(JNIEnv* env
,jobject thiz
,jlong lc
) {
- return linphone_core_is_media_encryption_mandatory((LinphoneCore*)lc);
+ return (jboolean)linphone_core_is_media_encryption_mandatory((LinphoneCore*)lc);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setMediaEncryptionMandatory(JNIEnv* env
return NULL;
}
}
-extern "C" int Java_org_linphone_core_LinphoneProxyConfigImpl_setProxy(JNIEnv* env,jobject thiz,jlong proxyCfg,jstring jproxy) {
+extern "C" jint Java_org_linphone_core_LinphoneProxyConfigImpl_setProxy(JNIEnv* env,jobject thiz,jlong proxyCfg,jstring jproxy) {
const char* proxy = env->GetStringUTFChars(jproxy, NULL);
- int err=linphone_proxy_config_set_server_addr((LinphoneProxyConfig*)proxyCfg,proxy);
+ jint err=linphone_proxy_config_set_server_addr((LinphoneProxyConfig*)proxyCfg,proxy);
env->ReleaseStringUTFChars(jproxy, proxy);
return err;
}
linphone_proxy_config_set_contact_parameters((LinphoneProxyConfig*)proxyCfg, params);
env->ReleaseStringUTFChars(jparams, params);
}
-extern "C" int Java_org_linphone_core_LinphoneProxyConfigImpl_setRoute(JNIEnv* env,jobject thiz,jlong proxyCfg,jstring jroute) {
+extern "C" jint Java_org_linphone_core_LinphoneProxyConfigImpl_setRoute(JNIEnv* env,jobject thiz,jlong proxyCfg,jstring jroute) {
if (jroute != NULL) {
const char* route = env->GetStringUTFChars(jroute, NULL);
- int err=linphone_proxy_config_set_route((LinphoneProxyConfig*)proxyCfg,route);
+ jint err=linphone_proxy_config_set_route((LinphoneProxyConfig*)proxyCfg,route);
env->ReleaseStringUTFChars(jroute, route);
return err;
} else {
- return linphone_proxy_config_set_route((LinphoneProxyConfig*)proxyCfg,NULL);
+ return (jint)linphone_proxy_config_set_route((LinphoneProxyConfig*)proxyCfg,NULL);
}
}
extern "C" jstring Java_org_linphone_core_LinphoneProxyConfigImpl_getRoute(JNIEnv* env,jobject thiz,jlong proxyCfg) {
linphone_proxy_config_enable_register((LinphoneProxyConfig*)proxyCfg,enableRegister);
}
extern "C" jboolean Java_org_linphone_core_LinphoneProxyConfigImpl_isRegistered(JNIEnv* env,jobject thiz,jlong proxyCfg) {
- return linphone_proxy_config_is_registered((LinphoneProxyConfig*)proxyCfg);
+ return (jboolean)linphone_proxy_config_is_registered((LinphoneProxyConfig*)proxyCfg);
}
extern "C" jboolean Java_org_linphone_core_LinphoneProxyConfigImpl_isRegisterEnabled(JNIEnv* env,jobject thiz,jlong proxyCfg) {
- return linphone_proxy_config_register_enabled((LinphoneProxyConfig*)proxyCfg);
+ return (jboolean)linphone_proxy_config_register_enabled((LinphoneProxyConfig*)proxyCfg);
}
extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_edit(JNIEnv* env,jobject thiz,jlong proxyCfg) {
linphone_proxy_config_edit((LinphoneProxyConfig*)proxyCfg);
env->ReleaseStringUTFChars(jnumber, number);
return normalizedNumber;
}
+extern "C" jint Java_org_linphone_core_LinphoneProxyConfigImpl_lookupCCCFromIso(JNIEnv* env, jobject thiz, jlong proxyCfg, jstring jiso) {
+ const char* iso = env->GetStringUTFChars(jiso, NULL);
+ int prefix = linphone_dial_plan_lookup_ccc_from_iso(iso);
+ env->ReleaseStringUTFChars(jiso, iso);
+ return (jint) prefix;
+}
extern "C" jstring Java_org_linphone_core_LinphoneProxyConfigImpl_getDomain(JNIEnv* env
,jobject thiz
,jlong proxyCfg) {
linphone_proxy_config_enable_publish((LinphoneProxyConfig*)proxyCfg,val);
}
extern "C" jboolean Java_org_linphone_core_LinphoneProxyConfigImpl_publishEnabled(JNIEnv* env,jobject thiz,jlong proxyCfg) {
- return linphone_proxy_config_publish_enabled((LinphoneProxyConfig*)proxyCfg);
+ return (jboolean)linphone_proxy_config_publish_enabled((LinphoneProxyConfig*)proxyCfg);
}
//Auth Info
, jstring jrealm) {
const char* username = env->GetStringUTFChars(jusername, NULL);
+ const char* userid = env->GetStringUTFChars(juserid, NULL);
const char* password = env->GetStringUTFChars(jpassword, NULL);
- jlong auth = (jlong)linphone_auth_info_new(username,NULL,password,NULL,NULL);
+ const char* ha1 = env->GetStringUTFChars(jha1, NULL);
+ const char* realm = env->GetStringUTFChars(jrealm, NULL);
+ jlong auth = (jlong)linphone_auth_info_new(username,userid,password,ha1,realm);
env->ReleaseStringUTFChars(jusername, username);
+ env->ReleaseStringUTFChars(juserid, userid);
env->ReleaseStringUTFChars(jpassword, password);
+ env->ReleaseStringUTFChars(jha1, ha1);
+ env->ReleaseStringUTFChars(jrealm, realm);
return auth;
}
if (displayName) {
return env->NewStringUTF(displayName);
} else {
- return 0;
+ return NULL;
}
}
extern "C" jstring Java_org_linphone_core_LinphoneAddressImpl_getUserName(JNIEnv* env
if (userName) {
return env->NewStringUTF(userName);
} else {
- return 0;
+ return NULL;
}
}
extern "C" jstring Java_org_linphone_core_LinphoneAddressImpl_getDomain(JNIEnv* env
if (domain) {
return env->NewStringUTF(domain);
} else {
- return 0;
+ return NULL;
}
}
,jlong ptr) {
return (jlong)((LinphoneCallLog*)ptr)->from;
}
-extern "C" int Java_org_linphone_core_LinphoneCallLogImpl_getStatus(JNIEnv* env
+extern "C" jint Java_org_linphone_core_LinphoneCallLogImpl_getStatus(JNIEnv* env
,jobject thiz
,jlong ptr) {
- return (jlong)((LinphoneCallLog*)ptr)->status;
+ return (jint)((LinphoneCallLog*)ptr)->status;
}
extern "C" jlong Java_org_linphone_core_LinphoneCallLogImpl_getTo(JNIEnv* env
,jobject thiz
extern "C" jint Java_org_linphone_core_LinphoneCallLogImpl_getCallDuration(JNIEnv* env
,jobject thiz
,jlong ptr) {
- return ((LinphoneCallLog*)ptr)->duration;
+ return (jint)((LinphoneCallLog*)ptr)->duration;
+}
+
+/* CallStats */
+extern "C" jint Java_org_linphone_core_LinphoneCallStatsImpl_getMediaType(JNIEnv *env, jobject thiz, jlong stats_ptr) {
+ return (jint)((LinphoneCallStats *)stats_ptr)->type;
+}
+extern "C" jint Java_org_linphone_core_LinphoneCallStatsImpl_getIceState(JNIEnv *env, jobject thiz, jlong stats_ptr) {
+ return (jint)((LinphoneCallStats *)stats_ptr)->ice_state;
+}
+extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getDownloadBandwidth(JNIEnv *env, jobject thiz, jlong stats_ptr) {
+ return (jfloat)((LinphoneCallStats *)stats_ptr)->download_bandwidth;
+}
+extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getUploadBandwidth(JNIEnv *env, jobject thiz, jlong stats_ptr) {
+ return (jfloat)((LinphoneCallStats *)stats_ptr)->upload_bandwidth;
+}
+extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getSenderLossRate(JNIEnv *env, jobject thiz, jlong stats_ptr) {
+ const LinphoneCallStats *stats = (LinphoneCallStats *)stats_ptr;
+ const report_block_t *srb = NULL;
+
+ if (!stats || !stats->sent_rtcp)
+ return (jfloat)0.0;
+ /* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */
+ if (stats->sent_rtcp->b_cont != NULL)
+ msgpullup(stats->sent_rtcp, -1);
+ if (rtcp_is_SR(stats->sent_rtcp))
+ srb = rtcp_SR_get_report_block(stats->sent_rtcp, 0);
+ else if (rtcp_is_RR(stats->sent_rtcp))
+ srb = rtcp_RR_get_report_block(stats->sent_rtcp, 0);
+ if (!srb)
+ return (jfloat)0.0;
+ return (jfloat)(100.0 * report_block_get_fraction_lost(srb) / 256.0);
+}
+extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getReceiverLossRate(JNIEnv *env, jobject thiz, jlong stats_ptr) {
+ const LinphoneCallStats *stats = (LinphoneCallStats *)stats_ptr;
+ const report_block_t *rrb = NULL;
+
+ if (!stats || !stats->received_rtcp)
+ return (jfloat)0.0;
+ /* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */
+ if (stats->received_rtcp->b_cont != NULL)
+ msgpullup(stats->received_rtcp, -1);
+ if (rtcp_is_RR(stats->received_rtcp))
+ rrb = rtcp_RR_get_report_block(stats->received_rtcp, 0);
+ else if (rtcp_is_SR(stats->received_rtcp))
+ rrb = rtcp_SR_get_report_block(stats->received_rtcp, 0);
+ if (!rrb)
+ return (jfloat)0.0;
+ return (jfloat)(100.0 * report_block_get_fraction_lost(rrb) / 256.0);
+}
+extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getSenderInterarrivalJitter(JNIEnv *env, jobject thiz, jlong stats_ptr, jlong call_ptr) {
+ LinphoneCallStats *stats = (LinphoneCallStats *)stats_ptr;
+ const LinphoneCall *call = (LinphoneCall *)call_ptr;
+ const LinphoneCallParams *params;
+ const PayloadType *pt;
+ const report_block_t *srb = NULL;
+
+ if (!stats || !call || !stats->sent_rtcp)
+ return (jfloat)0.0;
+ params = linphone_call_get_current_params(call);
+ if (!params)
+ return (jfloat)0.0;
+ /* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */
+ if (stats->sent_rtcp->b_cont != NULL)
+ msgpullup(stats->sent_rtcp, -1);
+ if (rtcp_is_SR(stats->sent_rtcp))
+ srb = rtcp_SR_get_report_block(stats->sent_rtcp, 0);
+ else if (rtcp_is_RR(stats->sent_rtcp))
+ srb = rtcp_RR_get_report_block(stats->sent_rtcp, 0);
+ if (!srb)
+ return (jfloat)0.0;
+ if (stats->type == LINPHONE_CALL_STATS_AUDIO)
+ pt = linphone_call_params_get_used_audio_codec(params);
+ else
+ pt = linphone_call_params_get_used_video_codec(params);
+ return (jfloat)((float)report_block_get_interarrival_jitter(srb) / (float)pt->clock_rate);
+}
+extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getReceiverInterarrivalJitter(JNIEnv *env, jobject thiz, jlong stats_ptr, jlong call_ptr) {
+ LinphoneCallStats *stats = (LinphoneCallStats *)stats_ptr;
+ const LinphoneCall *call = (LinphoneCall *)call_ptr;
+ const LinphoneCallParams *params;
+ const PayloadType *pt;
+ const report_block_t *rrb = NULL;
+
+ if (!stats || !call || !stats->received_rtcp)
+ return (jfloat)0.0;
+ params = linphone_call_get_current_params(call);
+ if (!params)
+ return (jfloat)0.0;
+ /* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */
+ if (stats->received_rtcp->b_cont != NULL)
+ msgpullup(stats->received_rtcp, -1);
+ if (rtcp_is_SR(stats->received_rtcp))
+ rrb = rtcp_SR_get_report_block(stats->received_rtcp, 0);
+ else if (rtcp_is_RR(stats->received_rtcp))
+ rrb = rtcp_RR_get_report_block(stats->received_rtcp, 0);
+ if (!rrb)
+ return (jfloat)0.0;
+ if (stats->type == LINPHONE_CALL_STATS_AUDIO)
+ pt = linphone_call_params_get_used_audio_codec(params);
+ else
+ pt = linphone_call_params_get_used_video_codec(params);
+ return (jfloat)((float)report_block_get_interarrival_jitter(rrb) / (float)pt->clock_rate);
+}
+extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getRoundTripDelay(JNIEnv *env, jobject thiz, jlong stats_ptr) {
+ return (jfloat)((LinphoneCallStats *)stats_ptr)->round_trip_delay;
+}
+extern "C" jlong Java_org_linphone_core_LinphoneCallStatsImpl_getLatePacketsCumulativeNumber(JNIEnv *env, jobject thiz, jlong stats_ptr, jlong call_ptr) {
+ LinphoneCallStats *stats = (LinphoneCallStats *)stats_ptr;
+ LinphoneCall *call = (LinphoneCall *)call_ptr;
+ rtp_stats_t rtp_stats;
+
+ if (!stats || !call)
+ return (jlong)0;
+ memset(&rtp_stats, 0, sizeof(rtp_stats));
+ if (stats->type == LINPHONE_CALL_STATS_AUDIO)
+ audio_stream_get_local_rtp_stats(call->audiostream, &rtp_stats);
+#ifdef VIDEO_ENABLED
+ else
+ video_stream_get_local_rtp_stats(call->videostream, &rtp_stats);
+#endif
+ return (jlong)rtp_stats.outoftime;
+}
+extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getJitterBufferSize(JNIEnv *env, jobject thiz, jlong stats_ptr) {
+ return (jfloat)((LinphoneCallStats *)stats_ptr)->jitter_stats.jitter_buffer_size_ms;
}
/*payloadType*/
}
extern "C" jint Java_org_linphone_core_PayloadTypeImpl_getRate(JNIEnv* env,jobject thiz, jlong ptr) {
PayloadType* pt = (PayloadType*)ptr;
- return payload_type_get_rate(pt);
+ return (jint)payload_type_get_rate(pt);
}
//LinphoneCall
extern "C" jboolean Java_org_linphone_core_LinphoneCallImpl_isEchoCancellationEnabled( JNIEnv* env
,jobject thiz
,jlong ptr) {
- return linphone_call_echo_cancellation_enabled((LinphoneCall*)ptr);
+ return (jboolean)linphone_call_echo_cancellation_enabled((LinphoneCall*)ptr);
}
extern "C" void Java_org_linphone_core_LinphoneCallImpl_enableEchoLimiter( JNIEnv* env
extern "C" jboolean Java_org_linphone_core_LinphoneCallImpl_isEchoLimiterEnabled( JNIEnv* env
,jobject thiz
,jlong ptr) {
- return linphone_call_echo_limiter_enabled((LinphoneCall*)ptr);
+ return (jboolean)linphone_call_echo_limiter_enabled((LinphoneCall*)ptr);
}
extern "C" jobject Java_org_linphone_core_LinphoneCallImpl_getReplacedCall( JNIEnv* env
//LinphoneFriend
-extern "C" long Java_org_linphone_core_LinphoneFriendImpl_newLinphoneFriend(JNIEnv* env
+extern "C" jlong Java_org_linphone_core_LinphoneFriendImpl_newLinphoneFriend(JNIEnv* env
,jobject thiz
,jstring jFriendUri) {
LinphoneFriend* lResult;
} else {
lResult = linphone_friend_new();
}
- return (long)lResult;
+ return (jlong)lResult;
}
extern "C" void Java_org_linphone_core_LinphoneFriendImpl_setAddress(JNIEnv* env
,jobject thiz
,jlong linphoneAddress) {
linphone_friend_set_addr((LinphoneFriend*)ptr,(LinphoneAddress*)linphoneAddress);
}
-extern "C" long Java_org_linphone_core_LinphoneFriendImpl_getAddress(JNIEnv* env
+extern "C" jlong Java_org_linphone_core_LinphoneFriendImpl_getAddress(JNIEnv* env
,jobject thiz
,jlong ptr) {
- return (long)linphone_friend_get_address((LinphoneFriend*)ptr);
+ return (jlong)linphone_friend_get_address((LinphoneFriend*)ptr);
}
extern "C" void Java_org_linphone_core_LinphoneFriendImpl_setIncSubscribePolicy(JNIEnv* env
,jobject thiz
extern "C" jint Java_org_linphone_core_LinphoneFriendImpl_getIncSubscribePolicy(JNIEnv* env
,jobject thiz
,jlong ptr) {
- return linphone_friend_get_inc_subscribe_policy((LinphoneFriend*)ptr);
+ return (jint)linphone_friend_get_inc_subscribe_policy((LinphoneFriend*)ptr);
}
extern "C" void Java_org_linphone_core_LinphoneFriendImpl_enableSubscribes(JNIEnv* env
,jobject thiz
extern "C" jboolean Java_org_linphone_core_LinphoneFriendImpl_isSubscribesEnabled(JNIEnv* env
,jobject thiz
,jlong ptr) {
- return linphone_friend_subscribes_enabled((LinphoneFriend*)ptr);
+ return (jboolean)linphone_friend_subscribes_enabled((LinphoneFriend*)ptr);
}
-extern "C" jboolean Java_org_linphone_core_LinphoneFriendImpl_getStatus(JNIEnv* env
+extern "C" jint Java_org_linphone_core_LinphoneFriendImpl_getStatus(JNIEnv* env
,jobject thiz
,jlong ptr) {
- return linphone_friend_get_status((LinphoneFriend*)ptr);
+ return (jint)linphone_friend_get_status((LinphoneFriend*)ptr);
}
extern "C" void Java_org_linphone_core_LinphoneFriendImpl_edit(JNIEnv* env
,jobject thiz
,jlong ptr) {
linphone_friend_done((LinphoneFriend*)ptr);
}
+extern "C" void Java_org_linphone_core_LinphoneCoreImpl_removeFriend(JNIEnv* env
+ ,jobject thiz
+ ,jlong ptr
+ ,jlong lf) {
+ linphone_core_remove_friend((LinphoneCore*)ptr, (LinphoneFriend*)lf);
+}
+extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_getFriendByAddress(JNIEnv* env
+ ,jobject thiz
+ ,jlong ptr
+ ,jstring jaddress) {
+ const char* address = env->GetStringUTFChars(jaddress, NULL);
+ LinphoneFriend *lf = linphone_core_get_friend_by_address((LinphoneCore*)ptr, address);
+ env->ReleaseStringUTFChars(jaddress, address);
+ return (jlong) lf;
+}
//LinphoneChatRoom
-extern "C" long Java_org_linphone_core_LinphoneChatRoomImpl_getPeerAddress(JNIEnv* env
+extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_getPeerAddress(JNIEnv* env
,jobject thiz
,jlong ptr) {
- return (long) linphone_chat_room_get_peer_address((LinphoneChatRoom*)ptr);
+ return (jlong) linphone_chat_room_get_peer_address((LinphoneChatRoom*)ptr);
}
extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_createLinphoneChatMessage(JNIEnv* env
,jobject thiz
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 (jlong) linphone_chat_message_get_from((LinphoneChatMessage*)ptr);
+}
+extern "C" jlong Java_org_linphone_core_LinphoneChatMessageImpl_getPeerAddress(JNIEnv* env
,jobject thiz
,jlong ptr) {
- return (long) linphone_chat_message_get_peer_address((LinphoneChatMessage*)ptr);
+ return (jlong) linphone_chat_message_get_peer_address((LinphoneChatMessage*)ptr);
}
extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_sendMessage(JNIEnv* env
,jobject thiz
}
-extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setFirewallPolicy(JNIEnv *env, jobject thiz, jlong lc, int enum_value){
+extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setFirewallPolicy(JNIEnv *env, jobject thiz, jlong lc, jint enum_value){
linphone_core_set_firewall_policy((LinphoneCore*)lc,(LinphoneFirewallPolicy)enum_value);
}
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getFirewallPolicy(JNIEnv *env, jobject thiz, jlong lc){
- return linphone_core_get_firewall_policy((LinphoneCore*)lc);
+ return (jint)linphone_core_get_firewall_policy((LinphoneCore*)lc);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setStunServer(JNIEnv *env, jobject thiz, jlong lc, jstring jserver){
return jvalue;
}
+//CallParams
+
+extern "C" jlong Java_org_linphone_core_LinphoneCallParamsImpl_getUsedAudioCodec(JNIEnv *env, jobject thiz, jlong cp) {
+ return (jlong)linphone_call_params_get_used_audio_codec((LinphoneCallParams *)cp);
+}
+
+extern "C" jlong Java_org_linphone_core_LinphoneCallParamsImpl_getUsedVideoCodec(JNIEnv *env, jobject thiz, jlong cp) {
+ return (jlong)linphone_call_params_get_used_video_codec((LinphoneCallParams *)cp);
+}
+
+extern "C" jint Java_org_linphone_core_LinphoneCallParamsImpl_getMediaEncryption(JNIEnv* env
+ ,jobject thiz
+ ,jlong cp
+ ) {
+ return (jint)linphone_call_params_get_media_encryption((LinphoneCallParams*)cp);
+}
+
+extern "C" void Java_org_linphone_core_LinphoneCallParamsImpl_setMediaEncryption(JNIEnv* env
+ ,jobject thiz
+ ,jlong cp
+ ,jint jmenc) {
+ linphone_call_params_set_media_encryption((LinphoneCallParams*)cp,(LinphoneMediaEncryption)jmenc);
+}
+
extern "C" void Java_org_linphone_core_LinphoneCallParamsImpl_audioBandwidth(JNIEnv *env, jobject thiz, jlong lcp, jint bw){
linphone_call_params_set_audio_bandwidth_limit((LinphoneCallParams*)lcp, bw);
}
}
extern "C" jboolean Java_org_linphone_core_LinphoneCallParamsImpl_getVideoEnabled(JNIEnv *env, jobject thiz, jlong lcp){
- return linphone_call_params_video_enabled((LinphoneCallParams*)lcp);
+ return (jboolean)linphone_call_params_video_enabled((LinphoneCallParams*)lcp);
}
extern "C" jboolean Java_org_linphone_core_LinphoneCallParamsImpl_localConferenceMode(JNIEnv *env, jobject thiz, jlong lcp){
- return linphone_call_params_local_conference_mode((LinphoneCallParams*)lcp);
+ return (jboolean)linphone_call_params_local_conference_mode((LinphoneCallParams*)lcp);
}
extern "C" void Java_org_linphone_core_LinphoneCallParamsImpl_destroy(JNIEnv *env, jobject thiz, jlong lc){
}
extern "C" jlong Java_org_linphone_core_LinphoneCallImpl_getRemoteParams(JNIEnv *env, jobject thiz, jlong lc){
+ if (linphone_call_get_remote_params((LinphoneCall*)lc) == NULL) {
+ return (jlong) 0;
+ }
return (jlong) linphone_call_params_copy(linphone_call_get_remote_params((LinphoneCall*)lc));
}
return (jlong) linphone_call_params_copy(linphone_call_get_current_params((LinphoneCall*)lc));
}
-extern "C" jlong Java_org_linphone_core_LinphoneCallImpl_enableCamera(JNIEnv *env, jobject thiz, jlong lc, jboolean b){
+extern "C" void Java_org_linphone_core_LinphoneCallImpl_enableCamera(JNIEnv *env, jobject thiz, jlong lc, jboolean b){
linphone_call_enable_camera((LinphoneCall *)lc, (bool_t) b);
}
extern "C" jboolean Java_org_linphone_core_LinphoneCallImpl_cameraEnabled(JNIEnv *env, jobject thiz, jlong lc){
- linphone_call_camera_enabled((LinphoneCall *)lc);
+ return (jboolean)linphone_call_camera_enabled((LinphoneCall *)lc);
}
extern "C" jobject Java_org_linphone_core_LinphoneCoreImpl_inviteAddressWithParams(JNIEnv *env, jobject thiz, jlong lc, jlong addr, jlong params){
linphone_core_set_upload_ptime((LinphoneCore *)lc, (int) ptime);
}
-extern "C" int Java_org_linphone_core_LinphoneProxyConfigImpl_getState(JNIEnv* env,jobject thiz,jlong ptr) {
- return (int) linphone_proxy_config_get_state((const LinphoneProxyConfig *) ptr);
+extern "C" jint Java_org_linphone_core_LinphoneProxyConfigImpl_getState(JNIEnv* env,jobject thiz,jlong ptr) {
+ return (jint) linphone_proxy_config_get_state((const LinphoneProxyConfig *) ptr);
}
extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_setExpires(JNIEnv* env,jobject thiz,jlong ptr,jint delay) {
linphone_proxy_config_expires((LinphoneProxyConfig *) ptr, (int) delay);
}
extern "C" jint Java_org_linphone_core_LinphoneCallImpl_getDuration(JNIEnv* env,jobject thiz,jlong ptr) {
- linphone_call_get_duration((LinphoneCall *) ptr);
+ return (jint)linphone_call_get_duration((LinphoneCall *) ptr);
}
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getSignalingTransportPort(JNIEnv* env,jobject thiz,jlong ptr, jint code) {
}
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_pauseCall(JNIEnv *env,jobject thiz,jlong pCore, jlong pCall) {
- return linphone_core_pause_call((LinphoneCore *) pCore, (LinphoneCall *) pCall);
+ return (jint)linphone_core_pause_call((LinphoneCore *) pCore, (LinphoneCall *) pCall);
}
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_pauseAllCalls(JNIEnv *env,jobject thiz,jlong pCore) {
- return linphone_core_pause_all_calls((LinphoneCore *) pCore);
+ return (jint)linphone_core_pause_all_calls((LinphoneCore *) pCore);
}
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_resumeCall(JNIEnv *env,jobject thiz,jlong pCore, jlong pCall) {
- return linphone_core_resume_call((LinphoneCore *) pCore, (LinphoneCall *) pCall);
+ return (jint)linphone_core_resume_call((LinphoneCore *) pCore, (LinphoneCall *) pCall);
}
extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isInConference(JNIEnv *env,jobject thiz,jlong pCore) {
- return linphone_core_is_in_conference((LinphoneCore *) pCore);
+ return (jboolean)linphone_core_is_in_conference((LinphoneCore *) pCore);
}
extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_enterConference(JNIEnv *env,jobject thiz,jlong pCore) {
- return 0 == linphone_core_enter_conference((LinphoneCore *) pCore);
+ return (jboolean)(0 == linphone_core_enter_conference((LinphoneCore *) pCore));
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_leaveConference(JNIEnv *env,jobject thiz,jlong pCore) {
linphone_core_leave_conference((LinphoneCore *) pCore);
linphone_core_terminate_conference((LinphoneCore *) pCore);
}
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getConferenceSize(JNIEnv *env,jobject thiz,jlong pCore) {
- return linphone_core_get_conference_size((LinphoneCore *) pCore);
+ return (jint)linphone_core_get_conference_size((LinphoneCore *) pCore);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_terminateAllCalls(JNIEnv *env,jobject thiz,jlong pCore) {
linphone_core_terminate_all_calls((LinphoneCore *) pCore);
return lcd->getCall(env,lCall);
}
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getCallsNb(JNIEnv *env,jobject thiz,jlong pCore) {
- return ms_list_size(linphone_core_get_calls((LinphoneCore *) pCore));
+ return (jint)ms_list_size(linphone_core_get_calls((LinphoneCore *) pCore));
}
-extern "C" void Java_org_linphone_core_LinphoneCoreImpl_transferCall(JNIEnv *env,jobject thiz,jlong pCore, jlong pCall, jstring jReferTo) {
+extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_transferCall(JNIEnv *env,jobject thiz,jlong pCore, jlong pCall, jstring jReferTo) {
const char* cReferTo=env->GetStringUTFChars(jReferTo, NULL);
- linphone_core_transfer_call((LinphoneCore *) pCore, (LinphoneCall *) pCall, cReferTo);
+ jint err = linphone_core_transfer_call((LinphoneCore *) pCore, (LinphoneCall *) pCall, cReferTo);
env->ReleaseStringUTFChars(jReferTo, cReferTo);
+ return err;
}
-extern "C" void Java_org_linphone_core_LinphoneCoreImpl_transferCallToAnother(JNIEnv *env,jobject thiz,jlong pCore, jlong pCall, jlong pDestCall) {
- linphone_core_transfer_call_to_another((LinphoneCore *) pCore, (LinphoneCall *) pCall, (LinphoneCall *) pDestCall);
+extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_transferCallToAnother(JNIEnv *env,jobject thiz,jlong pCore, jlong pCall, jlong pDestCall) {
+ return (jint)linphone_core_transfer_call_to_another((LinphoneCore *) pCore, (LinphoneCall *) pCall, (LinphoneCall *) pDestCall);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setZrtpSecretsCache(JNIEnv *env,jobject thiz,jlong pCore, jstring jFile) {
break;
ms_message("Existing device %d : %s\n", i, devices[i]);
if (i==id) {
- return linphone_core_set_video_device(lc, devices[i]);
+ return (jint)linphone_core_set_video_device(lc, devices[i]);
}
}
return -1;
}
extern "C" jboolean Java_org_linphone_core_LinphoneCallImpl_isAuthenticationTokenVerified(JNIEnv* env,jobject thiz,jlong ptr) {
LinphoneCall *call = (LinphoneCall *) ptr;
- return linphone_call_get_authentication_token_verified(call);
+ return (jboolean)linphone_call_get_authentication_token_verified(call);
}
extern "C" void Java_org_linphone_core_LinphoneCallImpl_setAuthenticationTokenVerified(JNIEnv* env,jobject thiz,jlong ptr,jboolean verified) {
LinphoneCall *call = (LinphoneCall *) ptr;
extern "C" jfloat Java_org_linphone_core_LinphoneCallImpl_getPlayVolume(JNIEnv* env, jobject thiz, jlong ptr) {
LinphoneCall *call = (LinphoneCall *) ptr;
- return linphone_call_get_play_volume(call);
+ return (jfloat)linphone_call_get_play_volume(call);
}
extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_soundResourcesLocked(JNIEnv* env,jobject thiz,jlong ptr){
- return linphone_core_sound_resources_locked((LinphoneCore *) ptr);
+ return (jboolean)linphone_core_sound_resources_locked((LinphoneCore *) ptr);
}
// Needed by Galaxy S (can't switch to/from speaker while playing and still keep mic working)
}
extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isTunnelAvailable(JNIEnv *env,jobject thiz){
- return linphone_core_tunnel_available();
+ return (jboolean)linphone_core_tunnel_available();
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setVideoPolicy(JNIEnv *env, jobject thiz, jlong lc, jboolean autoInitiate, jboolean autoAccept){
ms_set_cpu_count(count);
}
+extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setAudioPort(JNIEnv *env, jobject thiz, jlong lc, jint port) {
+ linphone_core_set_audio_port((LinphoneCore *)lc, port);
+}
+
+extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setVideoPort(JNIEnv *env, jobject thiz, jlong lc, jint port) {
+ linphone_core_set_video_port((LinphoneCore *)lc, port);
+}
+
+extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setAudioPortRange(JNIEnv *env, jobject thiz, jlong lc, jint min_port, jint max_port) {
+ linphone_core_set_audio_port_range((LinphoneCore *)lc, min_port, max_port);
+}
+
+extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setVideoPortRange(JNIEnv *env, jobject thiz, jlong lc, jint min_port, jint max_port) {
+ linphone_core_set_video_port_range((LinphoneCore *)lc, min_port, max_port);
+}
+
+extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setIncomingTimeout(JNIEnv *env, jobject thiz, jlong lc, jint timeout) {
+ linphone_core_set_inc_timeout((LinphoneCore *)lc, timeout);
+}
+
extern "C" jstring Java_org_linphone_core_LinphoneCoreImpl_getVersion(JNIEnv* env,jobject thiz,jlong ptr) {
jstring jvalue =env->NewStringUTF(linphone_core_get_version());
return jvalue;
* Enum describing the result of the echo canceller calibration process.
**/
typedef enum {
- LinphoneEcCalibratorInProgress,
- LinphoneEcCalibratorDone,
- LinphoneEcCalibratorFailed
+ LinphoneEcCalibratorInProgress, /**< The echo canceller calibration process is on going. */
+ LinphoneEcCalibratorDone, /**< The echo canceller calibration has been performed and produced an echo delay measure. */
+ LinphoneEcCalibratorFailed, /**< The echo canceller calibration process has failed. */
+ LinphoneEcCalibratorDoneNoEcho /**< The echo canceller calibration has been performed and no echo has been detected. */
}LinphoneEcCalibratorStatus;
if (pos2==NULL) pos2=pos1+strlen(pos1);
else {
*pos2='\0'; /*replace the '\n' */
- pos2--;
}
/* remove ending white spaces */
- for (; pos2>pos1 && *pos2==' ';pos2--) *pos2='\0';
+ for (; pos2>pos1 && pos2[-1]==' ';pos2--) pos2[-1]='\0';
+
if (pos2-pos1>=0){
/* found a pair key,value */
if (cur!=NULL){
ms_free(item->value);
item->value=strdup(pos1);
}
- /*printf("Found %s %s=%s\n",cur->name,key,pos1);*/
+ /*printf("Found %s %s={%s}\n",cur->name,key,pos1);*/
}else{
ms_warning("found key,item but no sections");
}
return default_string;
}
+bool_t lp_config_get_range(LpConfig *lpconfig, const char *section, const char *key, int *min, int *max, int default_min, int default_max) {
+ const char *str = lp_config_get_string(lpconfig, section, key, NULL);
+ if (str != NULL) {
+ char *minusptr = strchr(str, '-');
+ if ((minusptr == NULL) || (minusptr == str)) {
+ *min = default_min;
+ *max = default_max;
+ return FALSE;
+ }
+ *min = atoi(str);
+ *max = atoi(minusptr + 1);
+ return TRUE;
+ } else {
+ *min = default_min;
+ *max = default_max;
+ return TRUE;
+ }
+}
+
int lp_config_get_int(LpConfig *lpconfig,const char *section, const char *key, int default_value){
const char *str=lp_config_get_string(lpconfig,section,key,NULL);
if (str!=NULL) {
lpconfig->modified++;
}
+void lp_config_set_range(LpConfig *lpconfig, const char *section, const char *key, int min_value, int max_value) {
+ char tmp[30];
+ snprintf(tmp, sizeof(tmp), "%i-%i", min_value, max_value);
+ lp_config_set_string(lpconfig, section, key, tmp);
+}
+
void lp_config_set_int(LpConfig *lpconfig,const char *section, const char *key, int value){
char tmp[30];
snprintf(tmp,sizeof(tmp),"%i",value);
extern "C" {
#endif
+
+#define LP_CONFIG_DEFAULT_STRING(config, name, default) \
+ (config) ? (lp_config_get_string(config, "default_values", name, default)) : (default)
+
+#define LP_CONFIG_DEFAULT_INT(config, name, default) \
+ (config) ? (lp_config_get_int(config, "default_values", name, default)) : (default)
+
+#define LP_CONFIG_DEFAULT_INT64(config, name, default) \
+ (config) ? (lp_config_get_int64(config, "default_values", name, default)) : (default)
+
+#define LP_CONFIG_DEFAULT_FLOAT(config, name, default) \
+ (config) ? (lp_config_get_float(config, "default_values", name, default)) : (default)
+
+
LpConfig * lp_config_new(const char *filename);
int lp_config_read_file(LpConfig *lpconfig, const char *filename);
/**
**/
const char *lp_config_get_string(LpConfig *lpconfig, const char *section, const char *key, const char *default_string);
int lp_config_read_file(LpConfig *lpconfig, const char *filename);
+/**
+ * Retrieves a configuration item as a range, given its section, key, and default min and max values.
+ *
+ * @ingroup misc
+ * @return TRUE if the value is successfully parsed as a range, FALSE otherwise.
+ * If FALSE is returned, min and max are filled respectively with default_min and default_max values.
+ */
+bool_t lp_config_get_range(LpConfig *lpconfig, const char *section, const char *key, int *min, int *max, int default_min, int default_max);
/**
* Retrieves a configuration item as an integer, given its section, key, and default value.
*
* @ingroup misc
**/
void lp_config_set_string(LpConfig *lpconfig,const char *section, const char *key, const char *value);
+/**
+ * Sets a range config item
+ *
+ * @ingroup misc
+ */
+void lp_config_set_range(LpConfig *lpconfig, const char *section, const char *key, int min_value, int max_value);
/**
* Sets an integer config item
*
}
/* this functions runs a simple stun test and return the number of milliseconds to complete the tests, or -1 if the test were failed.*/
-int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call, StunCandidate *ac, StunCandidate *vc){
+int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){
const char *server=linphone_core_get_stun_server(lc);
+ StunCandidate *ac=&call->ac;
+ StunCandidate *vc=&call->vc;
if (lc->sip_conf.ipv6_enabled){
ms_warning("stun support is not implemented for ipv6");
params->up_bw=params->down_bw=edge_bw;
params->up_ptime=params->down_ptime=edge_ptime;
params->has_video=FALSE;
-
+ params->low_bandwidth=TRUE;
}/*else use default settings */
}
}
lc->vtable.display_status(lc, _("ICE local candidates gathering in progress..."));
/* Gather local host candidates. */
- if (linphone_core_get_local_ip_for(AF_INET, NULL, local_addr) < 0) {
+ if (linphone_core_get_local_ip_for(AF_INET, server, local_addr) < 0) {
ms_error("Fail to get local ip");
return -1;
}
- ice_add_local_candidate(audio_check_list, "host", local_addr, call->audio_port, 1, NULL);
- ice_add_local_candidate(audio_check_list, "host", local_addr, call->audio_port + 1, 2, NULL);
- if (call->params.has_video && (video_check_list != NULL)) {
+ if ((ice_check_list_state(audio_check_list) != ICL_Completed) && (ice_check_list_candidates_gathered(audio_check_list) == FALSE)) {
+ ice_add_local_candidate(audio_check_list, "host", local_addr, call->audio_port, 1, NULL);
+ ice_add_local_candidate(audio_check_list, "host", local_addr, call->audio_port + 1, 2, NULL);
+ call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateInProgress;
+ }
+ if (call->params.has_video && (video_check_list != NULL)
+ && (ice_check_list_state(video_check_list) != ICL_Completed) && (ice_check_list_candidates_gathered(video_check_list) == FALSE)) {
ice_add_local_candidate(video_check_list, "host", local_addr, call->video_port, 1, NULL);
ice_add_local_candidate(video_check_list, "host", local_addr, call->video_port + 1, 2, NULL);
+ call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateInProgress;
}
ms_message("ICE: gathering candidate from [%s]",server);
return 0;
}
+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;
+
+ 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))) {
+ if (ice_check_list_state(audio_check_list) == ICL_Completed) {
+ 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;
+ }
+ } else {
+ call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateFailed;
+ }
+ if (call->params.has_video && (video_check_list != NULL)) {
+ if (ice_check_list_state(video_check_list) == ICL_Completed) {
+ 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_VIDEO].ice_state = LinphoneIceStateFailed;
+ }
+ }
+ } else if (session_state == IS_Running) {
+ call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateInProgress;
+ if (call->params.has_video && (video_check_list != NULL)) {
+ call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateInProgress;
+ }
+ } 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;
+ }
+ }
+}
+
void linphone_core_update_local_media_description_from_ice(SalMediaDescription *desc, IceSession *session)
{
const char *rtp_addr, *rtcp_addr;
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;
if ((ice_check_list_state(cl) == ICL_Completed) && (ice_session_role(session) == IR_Controlling)) {
int rtp_port, rtcp_port;
memset(stream->ice_remote_candidates, 0, sizeof(stream->ice_remote_candidates));
- ice_check_list_selected_valid_remote_candidate(cl, &rtp_addr, &rtp_port, &rtcp_addr, &rtcp_port);
- strncpy(stream->ice_remote_candidates[0].addr, rtp_addr, sizeof(stream->ice_remote_candidates[0].addr));
- stream->ice_remote_candidates[0].port = rtp_port;
- strncpy(stream->ice_remote_candidates[1].addr, rtcp_addr, sizeof(stream->ice_remote_candidates[1].addr));
- stream->ice_remote_candidates[1].port = rtcp_port;
+ if (ice_check_list_selected_valid_remote_candidate(cl, &rtp_addr, &rtp_port, &rtcp_addr, &rtcp_port) == TRUE) {
+ strncpy(stream->ice_remote_candidates[0].addr, rtp_addr, sizeof(stream->ice_remote_candidates[0].addr));
+ stream->ice_remote_candidates[0].port = rtp_port;
+ strncpy(stream->ice_remote_candidates[1].addr, rtcp_addr, sizeof(stream->ice_remote_candidates[1].addr));
+ stream->ice_remote_candidates[1].port = rtcp_port;
+ } else {
+ ms_error("ice: Selected valid remote candidates should be present if the check list is in the Completed state");
+ }
+ } else {
+ for (j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES; j++) {
+ stream->ice_remote_candidates[j].addr[0] = '\0';
+ stream->ice_remote_candidates[j].port = 0;
+ }
}
}
}
break;
}
}
- if ((stream->ice_mismatch == TRUE) || (stream->rtp_port == 0)) {
+ if (stream->ice_mismatch == TRUE) {
ice_check_list_set_state(cl, ICL_Failed);
+ } else if (stream->rtp_port == 0) {
+ ice_session_remove_check_list(call->ice_session, cl);
} else {
if ((stream->ice_pwd[0] != '\0') && (stream->ice_ufrag[0] != '\0'))
ice_check_list_set_remote_credentials(cl, stream->ice_ufrag, stream->ice_pwd);
int componentID = j + 1;
if (candidate->addr[0] == '\0') break;
get_default_addr_and_port(componentID, md, stream, &addr, &port);
+ if (j == 0) {
+ /* If we receive a re-invite and we finished ICE processing on our side, use the candidates given by the remote. */
+ ice_check_list_unselect_valid_pairs(cl);
+ }
ice_add_losing_pair(cl, j + 1, candidate->addr, candidate->port, addr, port);
losing_pairs_added = TRUE;
}
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);
}
}
-void linphone_core_deactivate_ice_for_deactivated_media_streams(LinphoneCall *call, const SalMediaDescription *md)
+bool_t linphone_core_media_description_contains_video_stream(const SalMediaDescription *md)
{
int i;
+
for (i = 0; i < md->nstreams; i++) {
- IceCheckList *cl = ice_session_check_list(call->ice_session, i);
- if (cl && (md->streams[i].rtp_port == 0)) {
- if (ice_check_list_state(cl) != ICL_Completed) ice_check_list_set_state(cl, ICL_Failed);
- }
+ if ((md->streams[i].type == SalVideo) && (md->streams[i].rtp_port != 0))
+ return TRUE;
}
+ return FALSE;
}
LinphoneCall * is_a_linphone_call(void *user_pointer){
if (getifaddrs(&ifpstart) < 0) {
return -1;
}
-
+#ifndef __linux
+ #define UP_FLAG IFF_UP /* interface is up */
+#else
+ #define UP_FLAG IFF_RUNNING /* resources allocated */
+#endif
+
for (ifp = ifpstart; ifp != NULL; ifp = ifp->ifa_next) {
if (ifp->ifa_addr && ifp->ifa_addr->sa_family == type
- && (ifp->ifa_flags & IFF_RUNNING) && !(ifp->ifa_flags & IFF_LOOPBACK))
+ && (ifp->ifa_flags & UP_FLAG) && !(ifp->ifa_flags & IFF_LOOPBACK))
{
getnameinfo(ifp->ifa_addr,
(type == AF_INET6) ?
bool_t real_early_media; /*send real media even during early media (for outgoing calls)*/
bool_t in_conference; /*in conference mode */
bool_t pad;
-
+ bool_t low_bandwidth;
};
typedef struct _CallCallbackObj
char* external_body_url;
LinphoneAddress* from;
};
-
+
+typedef struct StunCandidate{
+ char addr[64];
+ int port;
+}StunCandidate;
+
+
struct _LinphoneCall
{
int magic; /*used to distinguish from proxy config*/
LinphoneCallState state;
LinphoneCallState transfer_state; /*idle if no transfer*/
LinphoneReason reason;
+ LinphoneProxyConfig *dest_proxy;
int refcnt;
void * user_pointer;
int audio_port;
int video_port;
+ StunCandidate ac,vc; /*audio video ip/port discovered by STUN*/
struct _AudioStream *audiostream; /**/
struct _VideoStream *videostream;
MSAudioEndpoint *endpoint; /*used for conferencing*/
LinphoneCallParams remote_params;
int up_bw; /*upload bandwidth setting at the time the call is started. Used to detect if it changes during a call */
int audio_bw; /*upload bandwidth used by audio */
+ OrtpEvQueue *audiostream_app_evq;
+ char *auth_token;
+ OrtpEvQueue *videostream_app_evq;
+ CallCallbackObj nextVideoFrameDecoded;
+ LinphoneCallStats stats[2];
+ IceSession *ice_session;
+ LinphoneChatMessage* pending_message;
+ int ping_time;
bool_t refer_pending;
bool_t media_pending;
bool_t audio_muted;
bool_t camera_active;
+
bool_t all_muted; /*this flag is set during early medias*/
bool_t playing_ringbacktone;
bool_t owns_call_log;
bool_t ringing_beep; /* whether this call is ringing through an already existent current call*/
- OrtpEvQueue *audiostream_app_evq;
- char *auth_token;
- OrtpEvQueue *videostream_app_evq;
+
bool_t videostream_encrypted;
bool_t audiostream_encrypted;
bool_t auth_token_verified;
bool_t defer_update;
+
bool_t was_automatically_paused;
bool_t ping_replied;
- CallCallbackObj nextVideoFrameDecoded;
- LinphoneCallStats stats[2];
- IceSession *ice_session;
- LinphoneChatMessage* pending_message;
};
void linphone_core_update_allocated_audio_bandwidth(LinphoneCore *lc);
void linphone_core_update_allocated_audio_bandwidth_in_call(LinphoneCall *call, const PayloadType *pt);
-typedef struct StunCandidate{
- char addr[64];
- int port;
-}StunCandidate;
-
-int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call, StunCandidate *ac, StunCandidate *vc);
+int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call);
void linphone_core_adapt_to_network(LinphoneCore *lc, int ping_time_ms, LinphoneCallParams *params);
int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call);
+void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call);
void linphone_core_update_local_media_description_from_ice(SalMediaDescription *desc, IceSession *session);
void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md);
-void linphone_core_deactivate_ice_for_deactivated_media_streams(LinphoneCall *call, const SalMediaDescription *md);
+bool_t linphone_core_media_description_contains_video_stream(const SalMediaDescription *md);
void linphone_core_send_initial_subscribes(LinphoneCore *lc);
void linphone_core_write_friends_config(LinphoneCore* lc);
void linphone_call_init_media_streams(LinphoneCall *call);
void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_muted, bool_t send_ringbacktone);
void linphone_call_start_media_streams_for_ice_gathering(LinphoneCall *call);
+void linphone_call_stop_audio_stream(LinphoneCall *call);
+void linphone_call_stop_video_stream(LinphoneCall *call);
void linphone_call_stop_media_streams(LinphoneCall *call);
void linphone_call_delete_ice_session(LinphoneCall *call);
+void linphone_call_stop_media_streams_for_ice_gathering(LinphoneCall *call);
const char * linphone_core_get_identity(LinphoneCore *lc);
const char * linphone_core_get_route(LinphoneCore *lc);
void linphone_core_stop_waiting(LinphoneCore *lc);
int linphone_core_proceed_with_invite_if_ready(LinphoneCore *lc, LinphoneCall *call, LinphoneProxyConfig *dest_proxy);
-int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, LinphoneProxyConfig *dest_proxy);
+int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call);
int linphone_core_start_update_call(LinphoneCore *lc, LinphoneCall *call);
int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call);
void linphone_core_start_refered_call(LinphoneCore *lc, LinphoneCall *call);
struct _LinphoneCore *lc;
char *peer;
LinphoneAddress *peer_url;
- SalOp *op;
void * user_data;
};
typedef struct rtp_config
{
- int audio_rtp_port;
- int video_rtp_port;
+ int audio_rtp_min_port;
+ int audio_rtp_max_port;
+ int video_rtp_min_port;
+ int video_rtp_max_port;
int audio_jitt_comp; /*jitter compensation*/
int video_jitt_comp; /*jitter compensation*/
int nortp_timeout;
ms_thread_t thread;
MSSndCard *play_card,*capt_card;
MSFilter *sndread,*det,*rec;
- MSFilter *play, *gen, *sndwrite,*resampler;
+ MSFilter *play, *gen, *sndwrite;
+ MSFilter *read_resampler,*write_resampler;
MSTicker *ticker;
LinphoneEcCalibrationCallback cb;
void *cb_data;
lp_config_set_int(lc->config,"sip","default_proxy",linphone_core_get_default_proxy(lc,NULL));
}
-#define DEFAULT_INT(config,name,default) \
- config?lp_config_get_int(config,"default_values",#name,default):default
-#define DEFAULT_STRING(config,name,default) \
- config?lp_config_get_string(config,"default_values",#name,default):default
-
static void linphone_proxy_config_init(LinphoneCore* lc,LinphoneProxyConfig *obj){
memset(obj,0,sizeof(LinphoneProxyConfig));
obj->magic=linphone_proxy_config_magic;
- obj->expires=DEFAULT_INT((lc?lc->config:NULL),reg_expires,3600);
- obj->dial_prefix=ms_strdup(DEFAULT_STRING((lc?lc->config:NULL),dial_prefix,'\0'));
- obj->dial_escape_plus=DEFAULT_INT((lc?lc->config:NULL),dial_escape_plus,0);
+ obj->expires=LP_CONFIG_DEFAULT_INT((lc?lc->config:NULL),"reg_expires",3600);
+ obj->dial_prefix=ms_strdup(LP_CONFIG_DEFAULT_STRING((lc?lc->config:NULL),"dial_prefix",'\0'));
+ obj->dial_escape_plus=LP_CONFIG_DEFAULT_INT((lc?lc->config:NULL),"dial_escape_plus",0);
}
/**
linphone_proxy_config_set_contact_parameters(cfg,lp_config_get_string(config,key,"contact_parameters",NULL));
- linphone_proxy_config_expires(cfg,lp_config_get_int(config,key,"reg_expires",DEFAULT_INT(config,reg_expires,600)));
+ linphone_proxy_config_expires(cfg,lp_config_get_int(config,key,"reg_expires",LP_CONFIG_DEFAULT_INT(config,"reg_expires",600)));
linphone_proxy_config_enableregister(cfg,lp_config_get_int(config,key,"reg_sendregister",0));
linphone_proxy_config_enable_publish(cfg,lp_config_get_int(config,key,"publish",0));
- linphone_proxy_config_set_dial_escape_plus(cfg,lp_config_get_int(config,key,"dial_escape_plus",DEFAULT_INT(config,dial_escape_plus,0)));
- linphone_proxy_config_set_dial_prefix(cfg,lp_config_get_string(config,key,"dial_prefix",DEFAULT_STRING(config,dial_prefix,NULL)));
+ linphone_proxy_config_set_dial_escape_plus(cfg,lp_config_get_int(config,key,"dial_escape_plus",LP_CONFIG_DEFAULT_INT(config,"dial_escape_plus",0)));
+ linphone_proxy_config_set_dial_prefix(cfg,lp_config_get_string(config,key,"dial_prefix",LP_CONFIG_DEFAULT_STRING(config,"dial_prefix",NULL)));
tmp=lp_config_get_string(config,key,"type",NULL);
if (tmp!=NULL && strlen(tmp)>0)
const char *sal_op_get_network_origin(const SalOp *op){
return ((SalOpBase*)op)->origin;
}
-
+const char* sal_op_get_call_id(const SalOp *op) {
+ return ((SalOpBase*)op)->call_id;
+}
void __sal_op_init(SalOp *b, Sal *sal){
memset(b,0,sizeof(SalOpBase));
((SalOpBase*)b)->root=sal;
sal_media_description_unref(b->local_media);
if (b->remote_media)
sal_media_description_unref(b->remote_media);
+ if (b->call_id)
+ ms_free((void*)b->call_id);
ms_free(op);
}
SalMediaDescription *local_media;
SalMediaDescription *remote_media;
void *user_pointer;
+ const char* call_id;
} SalOpBase;
void sal_use_session_timers(Sal *ctx, int expires);
void sal_use_double_registrations(Sal *ctx, bool_t enabled);
void sal_expire_old_registration_contacts(Sal *ctx, bool_t enabled);
+void sal_use_dates(Sal *ctx, bool_t enabled);
void sal_reuse_authorization(Sal *ctx, bool_t enabled);
void sal_use_one_matching_codec_policy(Sal *ctx, bool_t one_matching_codec);
void sal_use_rport(Sal *ctx, bool_t use_rports);
/*returns far-end "User-Agent" string */
const char *sal_op_get_remote_ua(const SalOp *op);
void *sal_op_get_user_pointer(const SalOp *op);
+const char* sal_op_get_call_id(const SalOp *op);
/*Call API*/
int sal_call_set_local_media_description(SalOp *h, SalMediaDescription *desc);
sal->rootCa = 0;
sal->verify_server_certs=TRUE;
sal->expire_old_contact=FALSE;
+ sal->add_dates=FALSE;
sal->dscp=-1;
return sal;
}
ctx->expire_old_contact=enabled;
}
+void sal_use_dates(Sal *ctx, bool_t enabled){
+ ctx->add_dates=enabled;
+#ifdef EXOSIP_OPT_REGISTER_WITH_DATE
+ {
+ int tmp=enabled;
+ eXosip_set_option(EXOSIP_OPT_REGISTER_WITH_DATE,&tmp);
+ }
+#else
+ if (enabled) ms_warning("Exosip does not support EXOSIP_OPT_REGISTER_WITH_DATE option.");
+#endif
+}
+
void sal_use_rport(Sal *ctx, bool_t use_rports){
ctx->use_rports=use_rports;
}
int err;
const char *route;
osip_message_t *invite=NULL;
+ osip_call_id_t *callid;
sal_op_set_from(h,from);
sal_op_set_to(h,to);
sal_exosip_fix_route(h);
ms_error("Fail to send invite ! Error code %d", err);
return -1;
}else{
+ callid=osip_message_get_call_id(invite);
+ osip_call_id_to_str(callid,(char **)(&h->base.call_id));
sal_add_call(h->base.root,h);
}
return 0;
osip_call_info_t *call_info;
char *tmp;
sdp_message_t *sdp=eXosip_get_sdp_info(ev->request);
+ osip_call_id_t *callid=osip_message_get_call_id(ev->request);
+ osip_call_id_to_str(callid,(char**)(&op->base.call_id));
set_network_origin(op,ev->request);
set_remote_ua(op,ev->request);
op->tid=ev->tid;
op->cid=ev->cid;
op->did=ev->did;
-
sal_add_call(op->base.root,op);
sal->callbacks.call_received(op);
}
osip_message_set_route(msg,tmp);
}
+
int sal_register(SalOp *h, const char *proxy, const char *from, int expires){
osip_message_t *msg;
const char *contact=sal_op_get_contact(h);
eXosip_register_build_register(h->rid,expires,&msg);
sal_register_add_route(msg,proxy);
}
- if (msg)
+ if (msg){
eXosip_register_send_register(h->rid,msg);
+ }
eXosip_unlock();
h->expires=expires;
return (msg != NULL) ? 0 : -1;
bool_t reuse_authorization;
bool_t verify_server_certs;
bool_t expire_old_contact;
+ bool_t add_dates;
};
struct SalOp{
buddylookup.ui \
tunnel_config.ui \
waiting.ui \
- dscp_settings.ui
+ dscp_settings.ui \
+ call_statistics.ui
PIXMAPS= \
stock_people.png
--- /dev/null
+<?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"><b>Call statistics and information</b></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>
<?xml version="1.0" encoding="UTF-8"?>
<interface>
- <requires lib="gtk+" version="2.24"/>
+ <requires lib="gtk+" version="2.18"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkDialog" id="dscp_settings">
<property name="can_focus">False</property>
}
}
+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 LinphoneIceStateFailed:
+ return _("ICE failed");
+ 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 ();
gtk_button_set_label(GTK_BUTTON(button),_("Stop"));
gtk_button_set_image(GTK_BUTTON(button),image);
gtk_widget_show(image);
+ g_signal_connect_swapped(G_OBJECT(linphone_gtk_get_widget(call_view,"quality_indicator")),"button-press-event",(GCallback)linphone_gtk_show_call_stats,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));
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){
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);
+}
+
linphone_gtk_visibility_set(shown,window_name,w,TRUE);
if (icon_path) {
GdkPixbuf *pbuf=create_pixbuf(icon_path);
- gtk_window_set_icon(GTK_WINDOW(w),pbuf);
- g_object_unref(G_OBJECT(pbuf));
+ if(pbuf != NULL) {
+ gtk_window_set_icon(GTK_WINDOW(w),pbuf);
+ g_object_unref(G_OBJECT(pbuf));
+ }
}
}
}
if (search_icon){
GdkPixbuf *pbuf=create_pixbuf(search_icon);
- gtk_image_set_from_pixbuf(GTK_IMAGE(linphone_gtk_get_widget(w,"directory_search_button_icon")),pbuf);
- g_object_unref(G_OBJECT(pbuf));
+ if(pbuf != NULL) {
+ gtk_image_set_from_pixbuf(GTK_IMAGE(linphone_gtk_get_widget(w,"directory_search_button_icon")),pbuf);
+ g_object_unref(G_OBJECT(pbuf));
+ }
}
if (home){
gchar *tmp;
<property name="width_request">90</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="events">GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
<property name="tooltip_text" translatable="yes">Call quality rating</property>
</object>
<packing>
import java.util.Vector;
/**
- * Object representing a Call. calls are created using {@link LinphoneCore#invite(LinphoneAddress)} or passed to the application by listener {@link LinphoneCoreListener#callState(LinphoneCore, LinphoneCall, State, String)}
+ * Object representing a call. Calls are created using {@link LinphoneCore#invite(LinphoneAddress)} or passed to the application by listener {@link LinphoneCoreListener#callState}
*
*/
* @Return LinphoneCallLog
**/
LinphoneCallLog getCallLog();
+
+ /**
+ * Set the audio statistics associated with this call.
+ * @return LinphoneCallStats
+ */
+ void setAudioStats(LinphoneCallStats stats);
+
+ /**
+ * Set the video statistics associated with this call.
+ * @return LinphoneCallStats
+ */
+ void setVideoStats(LinphoneCallStats stats);
+
+ /**
+ * Get the audio statistics associated with this call.
+ * @return LinphoneCallStats
+ */
+ LinphoneCallStats getAudioStats();
+
+ /**
+ * Get the video statistics associated with this call.
+ * @return LinphoneCallStats
+ */
+ LinphoneCallStats getVideoStats();
LinphoneCallParams getRemoteParams();
* @return the call duration, in seconds
*/
public int getCallDuration();
+ /**
+ * @return the call id from signaling
+ */
+ public int getCallId();
}
* @param value 0 to disable limitation
*/
void setAudioBandwidth(int value);
-
+
/**
* return selected media encryption
* @return MediaEncryption.None MediaEncryption.SRTP or MediaEncryption.ZRTP
* @params menc: MediaEncryption.None, MediaEncryption.SRTP or MediaEncryption.ZRTP
*/
void setMediaEnctyption(MediaEncryption menc);
-
+
+ /**
+ * Get the currently used audio codec
+ * @return PayloadType or null
+ */
+ PayloadType getUsedAudioCodec();
+
+ /**
+ * Get the currently used video codec
+ * @return PayloadType or null
+ */
+ PayloadType getUsedVideoCodec();
}
--- /dev/null
+/*
+LinPhoneCallStats.java
+Copyright (C) 2010 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+package org.linphone.core;
+
+import java.util.Vector;
+
+
+public interface LinphoneCallStats {
+ static public class MediaType {
+ static private Vector values = new Vector();
+ /**
+ * Audio
+ */
+ static public MediaType Audio = new MediaType(0, "Audio");
+ /**
+ * Video
+ */
+ static public MediaType Video = new MediaType(1, "Video");
+ protected final int mValue;
+ private final String mStringValue;
+
+ private MediaType(int value, String stringValue) {
+ mValue = value;
+ values.addElement(this);
+ mStringValue = stringValue;
+ }
+ public static MediaType fromInt(int value) {
+ for (int i = 0; i < values.size(); i++) {
+ MediaType mtype = (MediaType) values.elementAt(i);
+ if (mtype.mValue == value) return mtype;
+ }
+ throw new RuntimeException("MediaType not found [" + value + "]");
+ }
+ public String toString() {
+ return mStringValue;
+ }
+ }
+ static public class IceState {
+ static private Vector values = new Vector();
+ /**
+ * Not activated
+ */
+ static public IceState NotActivated = new IceState(0, "Not activated");
+ /**
+ * Failed
+ */
+ static public IceState Failed = new IceState(1, "Failed");
+ /**
+ * In progress
+ */
+ static public IceState InProgress = new IceState(2, "In progress");
+ /**
+ * Host connection
+ */
+ static public IceState HostConnection = new IceState(3, "Host connection");
+ /**
+ * Reflexive connection
+ */
+ static public IceState ReflexiveConnection = new IceState(4, "Reflexive connection");
+ /**
+ * Relay connection
+ */
+ static public IceState RelayConnection = new IceState(5, "Relay connection");
+ protected final int mValue;
+ private final String mStringValue;
+
+ private IceState(int value, String stringValue) {
+ mValue = value;
+ values.addElement(this);
+ mStringValue = stringValue;
+ }
+ public static IceState fromInt(int value) {
+ for (int i = 0; i < values.size(); i++) {
+ IceState mstate = (IceState) values.elementAt(i);
+ if (mstate.mValue == value) return mstate;
+ }
+ throw new RuntimeException("IceState not found [" + value + "]");
+ }
+ public String toString() {
+ return mStringValue;
+ }
+ }
+
+ /**
+ * Get the stats media type
+ * @return MediaType
+ */
+ public MediaType getMediaType();
+
+ /**
+ * Get the ICE state
+ */
+ public IceState getIceState();
+
+ /**
+ * Get the download bandwidth in kbit/s
+ * @return The download bandwidth
+ */
+ public float getDownloadBandwidth();
+
+ /**
+ * Get the upload bandwidth in kbit/s
+ * @return The upload bandwidth
+ */
+ public float getUploadBandwidth();
+
+ /**
+ * Get the sender loss rate since last report
+ * @return The sender loss rate
+ */
+ public float getSenderLossRate();
+
+ /**
+ * Get the receiver loss rate since last report
+ * @return The receiver loss rate
+ */
+ public float getReceiverLossRate();
+
+ /**
+ * Get the sender interarrival jitter
+ * @return The interarrival jitter at last emitted sender report
+ */
+ public float getSenderInterarrivalJitter();
+
+ /**
+ * Get the receiver interarrival jitter
+ * @return The interarrival jitter at last received receiver report
+ */
+ public float getReceiverInterarrivalJitter();
+
+ /**
+ * Get the round trip delay
+ * @return The round trip delay in seconds, -1 if the information is not available
+ */
+ public float getRoundTripDelay();
+
+ /**
+ * Get the cumulative number of late packets
+ * @return The cumulative number of late packets
+ */
+ public long getLatePacketsCumulativeNumber();
+
+ /**
+ * Get the jitter buffer size
+ * @return The jitter buffer size in milliseconds
+ */
+ public float getJitterBufferSize();
+}
*/
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
* @param chat message
*/
void sendMessage(LinphoneChatMessage message, LinphoneChatMessage.StateListener listener);
- /**
- * DEPRECATED
- * @param opaque
- * @param message
- */
- void sendMessage(Object opaque, String message);
/**
* Create a LinphoneChatMessage
import java.util.Vector;
-import org.linphone.core.LinphoneCallLog;
-import org.linphone.core.LinphoneCallParams;
-
/**
* Linphone core main object created by method {@link LinphoneCoreFactory#createLinphoneCore(LinphoneCoreListener, String, String, Object)}.
*
static public class EcCalibratorStatus {
static private Vector values = new Vector();
+ /* Do not change the values of these constants or the strings associated with them to prevent breaking
+ the collection of echo canceller calibration results during the wizard! */
public static final int IN_PROGRESS_STATUS=0;
public static final int DONE_STATUS=1;
public static final int FAILED_STATUS=2;
+ public static final int DONE_NO_ECHO_STATUS=3;
/**
* Calibration in progress
*/
- static public EcCalibratorStatus InProgress = new EcCalibratorStatus(IN_PROGRESS_STATUS,"InProgress");
+ static public EcCalibratorStatus InProgress = new EcCalibratorStatus(IN_PROGRESS_STATUS,"InProgress");
/**
- * Calibration done
+ * Calibration done that produced an echo delay measure
*/
- static public EcCalibratorStatus Done = new EcCalibratorStatus(DONE_STATUS,"Done");
+ static public EcCalibratorStatus Done = new EcCalibratorStatus(DONE_STATUS,"Done");
/**
- * Calibration in progress
+ * Calibration failed
*/
static public EcCalibratorStatus Failed = new EcCalibratorStatus(FAILED_STATUS,"Failed");
+ /**
+ * Calibration done with no echo detected
+ */
+ static public EcCalibratorStatus DoneNoEcho = new EcCalibratorStatus(DONE_NO_ECHO_STATUS, "DoneNoEcho");
private final int mValue;
private final String mStringValue;
* Accept an incoming call.
*
* Basically the application is notified of incoming calls within the
- * {@link LinphoneCoreListener#inviteReceived(LinphoneCore, String)} listener.
+ * {@link LinphoneCoreListener#callState} listener method.
* The application can later respond positively to the call using
* this method.
* @throws LinphoneCoreException
* Accept an incoming call.
*
* Basically the application is notified of incoming calls within the
- * {@link LinphoneCoreListener#inviteReceived(LinphoneCore, String)} listener.
+ * {@link LinphoneCoreListener#callState} listener method.
* The application can later respond positively to the call using
* this method.
* @throws LinphoneCoreException
* Accept call modifications initiated by other end.
*
* Basically the application is notified of incoming calls within the
- * {@link LinphoneCoreListener#inviteReceived(LinphoneCore, String)} listener.
+ * {@link LinphoneCoreListener#callState} listener method.
* The application can later respond positively to the call using
* this method.
* @throws LinphoneCoreException
* Prevent LinphoneCore from performing an automatic answer
*
* Basically the application is notified of incoming calls within the
- * {@link LinphoneCoreListener#inviteReceived(LinphoneCore, String)} listener.
+ * {@link LinphoneCoreListener#callState} listener method.
* The application can later respond positively to the call using
* this method.
* @throws LinphoneCoreException
*/
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
void startEchoCalibration(Object data) throws LinphoneCoreException;
void enableIpv6(boolean enable);
+ /**
+ * @deprecated
+ * @param i
+ */
void adjustSoftwareVolume(int i);
boolean pauseCall(LinphoneCall call);
* return the version code of linphone core
*/
public String getVersion();
+
+ /**
+ * remove a linphone friend from linphone core and linphonerc
+ */
+ void removeFriend(LinphoneFriend lf);
+
+ /**
+ * return a linphone friend (if exists) that matches the sip address
+ */
+ LinphoneFriend findFriendByAddress(String sipUri);
+
+ /**
+ * Sets the UDP port used for audio streaming.
+ **/
+ void setAudioPort(int port);
+
+ /**
+ * Sets the UDP port range from which to randomly select the port used for audio streaming.
+ */
+ void setAudioPortRange(int minPort, int maxPort);
+
+ /**
+ * Sets the UDP port used for video streaming.
+ **/
+ void setVideoPort(int port);
+
+ /**
+ * Sets the UDP port range from which to randomly select the port used for video streaming.
+ */
+ void setVideoPortRange(int minPort, int maxPort);
+
+ /**
+ * Set the incoming call timeout in seconds.
+ * If an incoming call isn't answered for this timeout period, it is
+ * automatically declined.
+ **/
+ void setIncomingTimeout(int timeout);
}
*This interface holds all callbacks that the application should implement. None is mandatory.
*/
public interface LinphoneCoreListener {
-
- /**< Notifies the application that it should show up
- * @return */
- void show(LinphoneCore lc);
-
/**< Ask the application some authentication information
* @return */
void authInfoRequested(LinphoneCore lc,String realm,String username);
- /**< Callback that notifies various events with human readable text.
- * @return */
- void displayStatus(LinphoneCore lc,String message);
-
- /**< Callback to display a message to the user
- * @return */
- void displayMessage(LinphoneCore lc,String message);
-
- /** Callback to display a warning to the user
- * @return */
- void displayWarning(LinphoneCore lc,String message);
-
/** General State notification
* @param state LinphoneCore.State
* @return
* */
void callState(LinphoneCore lc, LinphoneCall call, LinphoneCall.State cstate,String message);
+ /**
+ * Call stats notification
+ */
+ void callStatsUpdated(LinphoneCore lc, LinphoneCall call, LinphoneCallStats stats);
+
/**
* Callback to display change in encryption state.
* @param encrypted true if all streams of the call are encrypted
* 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 a new dtmf is received
+ * @param lc LinphoneCore
+ * @param call LinphoneCall involved in the dtmf sending
+ * @param dtmf value of the dtmf sent
+ */
+ void dtmfReceived(LinphoneCore lc, LinphoneCall call, int dtmf);
+
/**
* Invoked when echo cancalation calibration is completed
* @param lc LinphoneCore
*
*/
void notifyReceived(LinphoneCore lc, LinphoneCall call, LinphoneAddress from, byte[] event);
+
+
+ /**< @Deprecated Notifies the application that it should show up
+ * @return */
+ void show(LinphoneCore lc);
+ /**< @Deprecated Callback that notifies various events with human readable text.
+ * @return */
+ void displayStatus(LinphoneCore lc,String message);
+
+ /**< @Deprecated Callback to display a message to the user
+ * @return */
+ void displayMessage(LinphoneCore lc,String message);
+
+ /** @Deprecated Callback to display a warning to the user
+ * @return */
+ void displayWarning(LinphoneCore lc,String message);
+
}
*/
String toString();
-
+ /**
+ * Return the native pointer for this object
+ */
+ long getNativePtr();
}
* @param parameters to add
*/
public void setContactParameters(String params);
+
+ /**
+ * Return the international prefix for the given country
+ * @param country iso code
+ */
+ public int lookupCCCFromIso(String iso);
}
LibLinphone package is organized in submodules.
<ul>
- <li><a href="#proxy">Managing proxies</a>
+ <li><a href="#proxy">Managing proxies</a></li>
</ul>
<ul>
- <li><a href="#buddy">Managing Buddies and buddy list and presence</a>
+ <li><a href="#buddy">Managing Buddies and buddy list and presence</a></li>
</ul>
<ul>
- <li><a href="#chat">Chat room and Messaging</a>
+ <li><a href="#chat">Chat room and Messaging</a></li>
</ul>
+<ul>
+ <li><a href="#echo">Sound and echo cancellation settings</a></li>
+</ul>
+
<h2>Related Documentation</h2>
System.out.println("Message ["+message+"] received from ["+from+"] ");
}
</code>
+</pre>
+
+<h3>
+<a name="echo">Sound and echo cancellation settings</a>
+</h3>
+<b>Sound levels</b>
+<br>
+It is possible to tune the microphone input gain and speaker/receiver output gain by setting parameters into the linphonerc factory config file loaded when instanciating the {@link org.linphone.core.LinphoneCore LinphoneCore}. These gains are liblinphone's internal software gains and are unrelated to volume levels managed by the operating system. For example: <br>
+<pre>
+<code>
+[sound]
+#set the speaker or receiver playback gain in dbm0 (0 db = no change).
+playback_gain_db=-3
+#set the microphone gain in linear scale:
+mic_gain=0.1
+</code>
+</pre>
+
+<br>
+
+<b>Echo cancellation</b>
+<br>
+On Android devices, there are two kind of situations regarding echo cancellation:<br>
+<ul>
+ <li>The new (after 2011) high end devices, on which manufacturers often include a hardware echo cancellation. If available, liblinphone will make use of it and no software correction is required. Source file linphone-android/submodules/linphone/mediastreamer2/java/src/org/linphone/mediastream/video/capture/hwconf/Hacks.java contains a method hasBuiltInEchoCanceller() that returns true if an hardware echo canceller is available, based on device model identifier. The current list is incomplete.</li>
+ <li>The other devices, for which it is recommended to enable the software echo canceller of liblinphone.</li>
+</ul>
+
+<br>
+<b>Echo calibration tool</b>
+<br>
+The echo calibration procedure is a five second audio test which consists in playing small beeps to the receiver while the microphone input is recorded.
+If the device is subject to echo (or doesn't have hardware echo cancellation), then beeps recorded by the microphone will be detected and a measurement of echo delay can be computed.
+Echo calibration procedure can be started by calling {@link org.linphone.core.LinphoneCore#startEchoCalibration LinphoneCore.startEchoCalibration}.
+The measurement of the echo delay is important to save CPU computations by restricting the temporal area where the software echo canceller has to perform.
+<br>
+
+<br>
+<b>Echo limiter</b>
+<br>
+The echo limiter is a liblinphone algorithm to clear out echo with a brute force method. It consists in cutting down the microphone signal when active signal is played by the speaker/receiver, to prevent voice to feed back into the microphone. This algorithm has disadvantages compared to the hardware or software echo cancellers because the remote user will be not hear any background noise when speaking, which is confusing. As a result the echo limiter method shall be used only under situation where echo canceller can't perform, that is loud signals with heavy saturations, which usually happens when using the device in speaker mode. Echo limiter can be enabled or disabled during a call with {@link org.linphone.core.LinphoneCall#enableEchoLimiter LinphoneCall.enableEchoLimiter()}.
+<br>
+
+<br>
+<b>Recommandations to applications for optimal audio performance</b>
+<br>
+
+<br>
+In order to benefit from the best echo cancellation solution, we recommend applications to run the following procedure, when they are run for the first time:<br>
+<ul>
+ <li>Use the Hacks.hasBuiltInEchoCanceller() method to first check if the device has hardware echo cancellation. If yes, then echo canceller must be turned off.</li>
+ <li>If hasBuiltInEchoCanceller() returned false, then it is recommended to run the echo calibration procedure. This procedure can produce the following results:
+ <ul>
+ <li>success with no echo detected: it means that the device has an hardware echo canceller but is not (yet) referenced in our list of devices having hardware echo cancellation. Echo cancellation should be disabled with {@link org.linphone.core.LinphoneCore#enableEchoCancellation LinphoneCore.enableEchoCancellation(false)}</li>
+ <li>success with an estimated echo delay: the echo canceller should be enabled.</li>
+ <li>failure: it means that some echo has been detected but the delay could not be estimated. In this case it is recommended to activate the echo canceller. A typical for android minimum delay of 250 ms will be used as default.</li>
+ </ul>
+ </li>
+</ul>
+
+During calls, the echo limiter should be disabled while using the receiver, but enabled while using the hands-free speaker. It is also recommended to disable echo canceller while using the echo limiter, because the first one would be useless. Therefore you should have the following situations:
+<ul>
+ <li>While using the receiver</li>
+ <ul>
+ <li>Echo canceller enabled, unless the device has hardware echo cancellation</li>
+ <li>Echo limiter disabled</li>
+ </ul>
+ <li>While using the hands-free speaker</li>
+ <ul>
+ <li>Echo canceller disabled</li>
+ <li>Echo limiter enabled, unless the device has hardware echo cancellation.</li>
+ </ul>
+ </li>
+</ul>
+Controlling echo limiter during a call has to be done with {@link org.linphone.core.LinphoneCall#enableEchoLimiter LinphoneCall.enableEchoLimiter()}.
+Controlling echo canceller during a call has to be done with {@link org.linphone.core.LinphoneCall#enableEchoCancellation LinphoneCall.enableEchoCancellation()}.
+
+
+<br><br>
+<b>Echo limiter settings</b>
+<br>
+Echo limiter requires settings to be defined in linphonerc factory config file for correction operation.
+Typical settings are:
<pre>
+<code>
+[sound]
+el_type=mic
+#speaker energy threshold (linear scale) above which echo limiter decreases mic gain.
+el_thres=0.03
+#attenuation applied to mic gain (linear scale)
+el_force=100000
+#minimum time in milliseconds during which attenuation is applied
+el_sustain=600
+#double talk detection: threshold of ratio mic-energy/speaker-energy above which mic input is sent anyway.
+el_transmit_thres=1.7
+#noise gate floorgain (gain applied when no voice is detected).
+ng_floorgain=0.01
+</code>
+</pre>
+
+Up to date settings must be found from linphone-android/res/raw/linphonerc file.
+
+<br>
+
</body>
</html>
\ No newline at end of file
--- /dev/null
+/*
+LinphoneAddressImpl.java
+Copyright (C) 2010 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+package org.linphone.core;
+
+
+
+public class LinphoneAddressImpl implements LinphoneAddress {
+ protected final long nativePtr;
+ boolean ownPtr = false;
+ private native long newLinphoneAddressImpl(String uri,String displayName);
+ private native void delete(long ptr);
+ private native String getDisplayName(long ptr);
+ private native String getUserName(long ptr);
+ private native String getDomain(long ptr);
+ private native String toUri(long ptr);
+ private native void setDisplayName(long ptr,String name);
+ private native String toString(long ptr);
+
+ protected LinphoneAddressImpl(String identity) {
+ nativePtr = newLinphoneAddressImpl(identity, null);
+ }
+
+ protected LinphoneAddressImpl(String username,String domain,String displayName) {
+ nativePtr = newLinphoneAddressImpl("sip:"+username+"@"+domain, displayName);
+ }
+ protected LinphoneAddressImpl(long aNativePtr,boolean javaOwnPtr) {
+ nativePtr = aNativePtr;
+ ownPtr=javaOwnPtr;
+ }
+ protected LinphoneAddressImpl(long aNativePtr) {
+ nativePtr = aNativePtr;
+ ownPtr=false;
+ }
+ protected void finalize() throws Throwable {
+ if (ownPtr) delete(nativePtr);
+ }
+ public String getDisplayName() {
+ return getDisplayName(nativePtr);
+ }
+ public String getDomain() {
+ return getDomain(nativePtr);
+ }
+ public String getUserName() {
+ return getUserName(nativePtr);
+ }
+
+ public String toString() {
+ return toString(nativePtr);
+ }
+ public String toUri() {
+ return toUri(nativePtr);
+ }
+ public void setDisplayName(String name) {
+ setDisplayName(nativePtr,name);
+ }
+ public String asString() {
+ return toString();
+ }
+ public String asStringUriOnly() {
+ return toUri(nativePtr);
+ }
+ public void clean() {
+ throw new RuntimeException("Not implemented");
+ }
+ public String getPort() {
+ return String.valueOf(getPortInt());
+ }
+ public int getPortInt() {
+ return getPortInt();
+ }
+ public void setDomain(String domain) {
+ throw new RuntimeException("Not implemented");
+ }
+ public void setPort(String port) {
+ throw new RuntimeException("Not implemented");
+ }
+ public void setPortInt(int port) {
+ throw new RuntimeException("Not implemented");
+ }
+ public void setUserName(String username) {
+ throw new RuntimeException("Not implemented");
+ }
+
+}
--- /dev/null
+/*
+LinphoneAuthInfoImpl.java
+Copyright (C) 2010 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+package org.linphone.core;
+
+class LinphoneAuthInfoImpl implements LinphoneAuthInfo {
+ protected final long nativePtr;
+ private native long newLinphoneAuthInfo(String username, String userid, String passwd, String ha1,String realm);
+ private native void delete(long ptr);
+ protected LinphoneAuthInfoImpl(String username,String password, String realm) {
+ nativePtr = newLinphoneAuthInfo(username,"",password,"","");
+ }
+ protected void finalize() throws Throwable {
+ delete(nativePtr);
+ }
+ public String getPassword() {
+ // TODO Auto-generated method stub
+ throw new RuntimeException("not implemeneted yet");
+ }
+ public String getRealm() {
+ // TODO Auto-generated method stub
+ throw new RuntimeException("not implemeneted yet");
+ }
+ public String getUsername() {
+ // TODO Auto-generated method stub
+ throw new RuntimeException("not implemeneted yet");
+ }
+ public void setPassword(String password) {
+ // TODO Auto-generated method stub
+ throw new RuntimeException("not implemeneted yet");
+ }
+ public void setRealm(String realm) {
+ // TODO Auto-generated method stub
+ throw new RuntimeException("not implemeneted yet");
+ }
+ public void setUsername(String username) {
+ // TODO Auto-generated method stub
+ throw new RuntimeException("not implemeneted yet");
+ }
+}
--- /dev/null
+/*
+LinphoneCallImpl.java
+Copyright (C) 2010 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+package org.linphone.core;
+
+
+class LinphoneCallImpl implements LinphoneCall {
+
+ protected final long nativePtr;
+ boolean ownPtr = false;
+ private LinphoneCallStats audioStats;
+ private LinphoneCallStats videoStats;
+
+ native private void finalize(long nativePtr);
+ native private long getCallLog(long nativePtr);
+ private native boolean isIncoming(long nativePtr);
+ native private long getRemoteAddress(long nativePtr);
+ native private int getState(long nativePtr);
+ private native long getCurrentParamsCopy(long nativePtr);
+ private native long getRemoteParams(long nativePtr);
+ private native void enableCamera(long nativePtr, boolean enabled);
+ private native boolean cameraEnabled(long nativePtr);
+ private native void enableEchoCancellation(long nativePtr,boolean enable);
+ private native boolean isEchoCancellationEnabled(long nativePtr) ;
+ private native void enableEchoLimiter(long nativePtr,boolean enable);
+ private native boolean isEchoLimiterEnabled(long nativePtr);
+ private native Object getReplacedCall(long nativePtr);
+ private native int getDuration(long nativePtr);
+ private native float getCurrentQuality(long nativePtr);
+ private native float getAverageQuality(long nativePtr);
+
+ /*
+ * This method must always be called from JNI, nothing else.
+ */
+ private LinphoneCallImpl(long aNativePtr) {
+ nativePtr = aNativePtr;
+ }
+ protected void finalize() throws Throwable {
+ finalize(nativePtr);
+ }
+ public LinphoneCallLog getCallLog() {
+ long lNativePtr = getCallLog(nativePtr);
+ if (lNativePtr!=0) {
+ return new LinphoneCallLogImpl(lNativePtr);
+ } else {
+ return null;
+ }
+ }
+ public void setAudioStats(LinphoneCallStats stats) {
+ audioStats = stats;
+ }
+ public void setVideoStats(LinphoneCallStats stats) {
+ videoStats = stats;
+ }
+ public LinphoneCallStats getAudioStats() {
+ return audioStats;
+ }
+ public LinphoneCallStats getVideoStats() {
+ return videoStats;
+ }
+ public CallDirection getDirection() {
+ return isIncoming(nativePtr)?CallDirection.Incoming:CallDirection.Outgoing;
+ }
+ public LinphoneAddress getRemoteAddress() {
+ long lNativePtr = getRemoteAddress(nativePtr);
+ if (lNativePtr!=0) {
+ return new LinphoneAddressImpl(lNativePtr);
+ } else {
+ return null;
+ }
+ }
+ public State getState() {
+ return LinphoneCall.State.fromInt(getState(nativePtr));
+ }
+ public LinphoneCallParams getCurrentParamsCopy() {
+ return new LinphoneCallParamsImpl(getCurrentParamsCopy(nativePtr));
+ }
+ public LinphoneCallParams getRemoteParams() {
+ long remoteParamsPtr = getRemoteParams(nativePtr);
+ if (remoteParamsPtr == 0) {
+ return null;
+ }
+ return new LinphoneCallParamsImpl(remoteParamsPtr);
+ }
+ public void enableCamera(boolean enabled) {
+ enableCamera(nativePtr, enabled);
+ }
+ public boolean cameraEnabled() {
+ return cameraEnabled(nativePtr);
+ }
+
+ @Override
+ public boolean equals(Object call) {
+ if (this == call) return true;
+ if (call == null) return false;
+ if (!(call instanceof LinphoneCallImpl)) return false;
+ return nativePtr == ((LinphoneCallImpl)call).nativePtr;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 17;
+ result = 31 * result + (int) (nativePtr ^ (nativePtr >>> 32));
+ return result;
+ }
+ public void enableEchoCancellation(boolean enable) {
+ enableEchoCancellation(nativePtr,enable);
+
+ }
+ public boolean isEchoCancellationEnabled() {
+ return isEchoCancellationEnabled(nativePtr);
+ }
+ public void enableEchoLimiter(boolean enable) {
+ enableEchoLimiter(nativePtr,enable);
+ }
+ public boolean isEchoLimiterEnabled() {
+ return isEchoLimiterEnabled(nativePtr);
+ }
+ public LinphoneCall getReplacedCall(){
+ return (LinphoneCall)getReplacedCall(nativePtr);
+ }
+
+ public int getDuration() {
+ return getDuration(nativePtr);
+ }
+ public float getAverageQuality() {
+ return getAverageQuality(nativePtr);
+ }
+ public float getCurrentQuality() {
+ return getCurrentQuality(nativePtr);
+ }
+
+ private native String getAuthenticationToken(long nativePtr);
+ public String getAuthenticationToken(){
+ return getAuthenticationToken(nativePtr);
+ }
+
+ private native boolean isAuthenticationTokenVerified(long nativePtr);
+ public boolean isAuthenticationTokenVerified(){
+ return isAuthenticationTokenVerified(nativePtr);
+ }
+
+ private native void setAuthenticationTokenVerified(long nativePtr, boolean verified);
+ public void setAuthenticationTokenVerified(boolean verified){
+ setAuthenticationTokenVerified(nativePtr, verified);
+ }
+
+ public boolean isInConference() {
+ LinphoneCallParamsImpl params = new LinphoneCallParamsImpl(getCurrentParamsCopy(nativePtr));
+ return params.localConferenceMode();
+ }
+
+ @Override
+ public String toString() {
+ return "Call " + nativePtr;
+ }
+
+ private native float getPlayVolume(long nativePtr);
+ public float getPlayVolume() {
+ return getPlayVolume(nativePtr);
+ }
+
+ private native void takeSnapshot(long nativePtr, String path);
+ public void takeSnapshot(String path) {
+ takeSnapshot(nativePtr, path);
+ }
+
+ private native void zoomVideo(long nativePtr, float factor, float cx, float cy);
+ public void zoomVideo(float factor, float cx, float cy) {
+ zoomVideo(nativePtr, factor, cx, cy);
+ }
+}
--- /dev/null
+/*
+LinPhoneCallLogImpl.java
+Copyright (C) 2010 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+package org.linphone.core;
+
+
+class LinphoneCallLogImpl implements LinphoneCallLog {
+
+ protected final long nativePtr;
+
+ private native long getFrom(long nativePtr);
+ private native long getTo(long nativePtr);
+ private native boolean isIncoming(long nativePtr);
+ private native int getStatus(long nativePtr);
+ private native String getStartDate(long nativePtr);
+ private native int getCallDuration(long nativePtr);
+ private native int getCallId(long nativePtr);
+
+ LinphoneCallLogImpl(long aNativePtr) {
+ nativePtr = aNativePtr;
+ }
+
+ public CallDirection getDirection() {
+ return isIncoming(nativePtr)?CallDirection.Incoming:CallDirection.Outgoing;
+ }
+
+ public LinphoneAddress getFrom() {
+ return new LinphoneAddressImpl(getFrom(nativePtr));
+ }
+
+ public LinphoneAddress getTo() {
+ return new LinphoneAddressImpl(getTo(nativePtr));
+ }
+ public CallStatus getStatus() {
+ return LinphoneCallLog.CallStatus.fromInt(getStatus(nativePtr));
+ }
+
+ public long getNativePtr() {
+ return nativePtr;
+ }
+
+ public String getStartDate() {
+ return getStartDate(nativePtr);
+ }
+
+ public int getCallDuration() {
+ return getCallDuration(nativePtr);
+ }
+ public int getCallId() {
+ return getCallId(nativePtr);
+ }
+}
--- /dev/null
+/*
+LinphoneCallParamsImpl.java
+Copyright (C) 2010 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+package org.linphone.core;
+
+import org.linphone.core.LinphoneCore.MediaEncryption;
+
+public class LinphoneCallParamsImpl implements LinphoneCallParams {
+ protected final long nativePtr;
+
+ public LinphoneCallParamsImpl(long nativePtr) {
+ this.nativePtr = nativePtr;
+ }
+
+ private native void enableVideo(long nativePtr, boolean b);
+ private native boolean getVideoEnabled(long nativePtr);
+ private native void audioBandwidth(long nativePtr, int bw);
+ private native void setMediaEncryption(long nativePtr, int menc);
+ private native int getMediaEncryption(long nativePtr);
+ private native long getUsedAudioCodec(long nativePtr);
+ private native long getUsedVideoCodec(long nativePtr);
+ private native void destroy(long nativePtr);
+
+
+ public boolean getVideoEnabled() {
+ return getVideoEnabled(nativePtr);
+ }
+
+ public void setVideoEnabled(boolean b) {
+ enableVideo(nativePtr, b);
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ destroy(nativePtr);
+ super.finalize();
+ }
+
+ public void setAudioBandwidth(int value) {
+ audioBandwidth(nativePtr, value);
+ }
+
+ public MediaEncryption getMediaEncryption() {
+ return MediaEncryption.fromInt(getMediaEncryption(nativePtr));
+ }
+
+ public void setMediaEnctyption(MediaEncryption menc) {
+ setMediaEncryption(nativePtr, menc.mValue);
+ }
+
+ public PayloadType getUsedAudioCodec() {
+ long ptr = getUsedAudioCodec(nativePtr);
+ if (ptr == 0) return null;
+ return new PayloadTypeImpl(ptr);
+ }
+
+ public PayloadType getUsedVideoCodec() {
+ long ptr = getUsedVideoCodec(nativePtr);
+ if (ptr == 0) return null;
+ return new PayloadTypeImpl(ptr);
+ }
+
+ private native boolean localConferenceMode(long nativePtr);
+ public boolean localConferenceMode() {
+ return localConferenceMode(nativePtr);
+ }
+}
--- /dev/null
+/*
+LinPhoneCallStatsImpl.java
+Copyright (C) 2010 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+package org.linphone.core;
+
+
+class LinphoneCallStatsImpl implements LinphoneCallStats {
+ private int mediaType;
+ private int iceState;
+ private float downloadBandwidth;
+ private float uploadBandwidth;
+ private float senderLossRate;
+ private float receiverLossRate;
+ private float senderInterarrivalJitter;
+ private float receiverInterarrivalJitter;
+ private float roundTripDelay;
+ private long latePacketsCumulativeNumber;
+ private float jitterBufferSize;
+
+ private native int getMediaType(long nativeStatsPtr);
+ private native int getIceState(long nativeStatsPtr);
+ private native float getDownloadBandwidth(long nativeStatsPtr);
+ private native float getUploadBandwidth(long nativeStatsPtr);
+ private native float getSenderLossRate(long nativeStatsPtr);
+ private native float getReceiverLossRate(long nativeStatsPtr);
+ private native float getSenderInterarrivalJitter(long nativeStatsPtr, long nativeCallPtr);
+ private native float getReceiverInterarrivalJitter(long nativeStatsPtr, long nativeCallPtr);
+ private native float getRoundTripDelay(long nativeStatsPtr);
+ private native long getLatePacketsCumulativeNumber(long nativeStatsPtr, long nativeCallPtr);
+ private native float getJitterBufferSize(long nativeStatsPtr);
+
+ protected LinphoneCallStatsImpl(long nativeCallPtr, long nativeStatsPtr) {
+ mediaType = getMediaType(nativeStatsPtr);
+ iceState = getIceState(nativeStatsPtr);
+ downloadBandwidth = getDownloadBandwidth(nativeStatsPtr);
+ uploadBandwidth = getUploadBandwidth(nativeStatsPtr);
+ senderLossRate = getSenderLossRate(nativeStatsPtr);
+ receiverLossRate = getReceiverLossRate(nativeStatsPtr);
+ senderInterarrivalJitter = getSenderInterarrivalJitter(nativeStatsPtr, nativeCallPtr);
+ receiverInterarrivalJitter = getReceiverInterarrivalJitter(nativeStatsPtr, nativeCallPtr);
+ roundTripDelay = getRoundTripDelay(nativeStatsPtr);
+ latePacketsCumulativeNumber = getLatePacketsCumulativeNumber(nativeStatsPtr, nativeCallPtr);
+ jitterBufferSize = getJitterBufferSize(nativeStatsPtr);
+ }
+
+ public MediaType getMediaType() {
+ return MediaType.fromInt(mediaType);
+ }
+
+ public IceState getIceState() {
+ return IceState.fromInt(iceState);
+ }
+
+ public float getDownloadBandwidth() {
+ return downloadBandwidth;
+ }
+
+ public float getUploadBandwidth() {
+ return uploadBandwidth;
+ }
+
+ public float getSenderLossRate() {
+ return senderLossRate;
+ }
+
+ public float getReceiverLossRate() {
+ return receiverLossRate;
+ }
+
+ public float getSenderInterarrivalJitter() {
+ return senderInterarrivalJitter;
+ }
+
+ public float getReceiverInterarrivalJitter() {
+ return receiverInterarrivalJitter;
+ }
+
+ public float getRoundTripDelay() {
+ return roundTripDelay;
+ }
+
+ public long getLatePacketsCumulativeNumber() {
+ return latePacketsCumulativeNumber;
+ }
+
+ public float getJitterBufferSize() {
+ return jitterBufferSize;
+ }
+}
--- /dev/null
+package org.linphone.core;
+
+public class LinphoneChatMessageImpl implements LinphoneChatMessage {
+ protected final long nativePtr;
+ private native void setUserData(long ptr);
+ private native String getMessage(long ptr);
+ private native long getPeerAddress(long ptr);
+ private native String getExternalBodyUrl(long ptr);
+ private native void setExternalBodyUrl(long ptr, String url);
+ private native long getFrom(long ptr);
+
+ protected LinphoneChatMessageImpl(long aNativePtr) {
+ nativePtr = aNativePtr;
+ setUserData();
+ }
+
+ public long getNativePtr() {
+ return nativePtr;
+ }
+
+ @Override
+ public Object getUserData() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void setUserData() {
+ setUserData(nativePtr);
+ }
+
+ @Override
+ public String getMessage() {
+ return getMessage(nativePtr);
+ }
+
+ @Override
+ public LinphoneAddress getPeerAddress() {
+ return new LinphoneAddressImpl(getPeerAddress(nativePtr));
+ }
+
+ @Override
+ public String getExternalBodyUrl() {
+ return getExternalBodyUrl(nativePtr);
+ }
+
+ @Override
+ public void setExternalBodyUrl(String url) {
+ setExternalBodyUrl(nativePtr, url);
+ }
+
+ @Override
+ public LinphoneAddress getFrom() {
+ return new LinphoneAddressImpl(getFrom(nativePtr));
+ }
+}
--- /dev/null
+/*
+LinphoneChatRoomImpl.java
+Copyright (C) 2010 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+package org.linphone.core;
+
+import org.linphone.core.LinphoneChatMessage.StateListener;
+
+class LinphoneChatRoomImpl implements LinphoneChatRoom {
+ protected final long nativePtr;
+ private native long createLinphoneChatMessage(long ptr, String message);
+ private native long getPeerAddress(long ptr);
+ private native void sendMessage(long ptr, String message);
+ private native void sendMessage2(long ptr, long message, StateListener listener);
+
+ protected LinphoneChatRoomImpl(long aNativePtr) {
+ nativePtr = aNativePtr;
+ }
+
+ public LinphoneAddress getPeerAddress() {
+ return new LinphoneAddressImpl(getPeerAddress(nativePtr));
+ }
+
+ public void sendMessage(String message) {
+ sendMessage(nativePtr,message);
+ }
+
+ @Override
+ public void sendMessage(LinphoneChatMessage message, StateListener listener) {
+ sendMessage2(nativePtr, message.getNativePtr(), listener);
+
+ }
+
+ @Override
+ public LinphoneChatMessage createLinphoneChatMessage(String message) {
+ return new LinphoneChatMessageImpl(createLinphoneChatMessage(nativePtr, message));
+ }
+}
--- /dev/null
+/*
+LinphoneCoreFactoryImpl.java
+Copyright (C) 2010 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+package org.linphone.core;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.linphone.mediastream.Version;
+
+import android.util.Log;
+
+public class LinphoneCoreFactoryImpl extends LinphoneCoreFactory {
+
+ private static boolean loadOptionalLibrary(String s) {
+ try {
+ System.loadLibrary(s);
+ return true;
+ } catch (Throwable e) {
+ Log.w("Unable to load optional library lib", s);
+ }
+ return false;
+ }
+
+ static {
+ // FFMPEG (audio/video)
+ loadOptionalLibrary("avutil");
+ loadOptionalLibrary("swscale");
+ loadOptionalLibrary("avcore");
+
+ if (!hasNeonInCpuFeatures()) {
+ boolean noNeonLibrariesLoaded = loadOptionalLibrary("avcodecnoneon");
+ if (!noNeonLibrariesLoaded) {
+ loadOptionalLibrary("avcodec");
+ }
+ } else {
+ loadOptionalLibrary("avcodec");
+ }
+
+ // OPENSSL (cryptography)
+ // lin prefix avoids collision with libs in /system/lib
+ loadOptionalLibrary("lincrypto");
+ loadOptionalLibrary("linssl");
+
+ // Secure RTP and key negotiation
+ loadOptionalLibrary("srtp");
+ loadOptionalLibrary("zrtpcpp"); // GPLv3+
+
+ // Tunnel
+ loadOptionalLibrary("tunnelclient");
+
+ // g729 A implementation
+ loadOptionalLibrary("bcg729");
+
+ //Main library
+ if (!hasNeonInCpuFeatures()) {
+ try {
+ if (!isArmv7() && !Version.isX86()) {
+ System.loadLibrary("linphonearmv5");
+ } else {
+ System.loadLibrary("linphonenoneon");
+ }
+ Log.w("linphone", "No-neon liblinphone loaded");
+ } catch (UnsatisfiedLinkError ule) {
+ Log.w("linphone", "Failed to load no-neon liblinphone, loading neon liblinphone");
+ System.loadLibrary("linphone");
+ }
+ } else {
+ System.loadLibrary("linphone");
+ }
+
+ Version.dumpCapabilities();
+ }
+ @Override
+ public LinphoneAuthInfo createAuthInfo(String username, String password,
+ String realm) {
+ return new LinphoneAuthInfoImpl(username,password,realm);
+ }
+
+ @Override
+ public LinphoneAddress createLinphoneAddress(String username,
+ String domain, String displayName) {
+ return new LinphoneAddressImpl(username,domain,displayName);
+ }
+
+ @Override
+ public LinphoneAddress createLinphoneAddress(String identity) {
+ return new LinphoneAddressImpl(identity);
+ }
+
+ @Override
+ public LinphoneCore createLinphoneCore(LinphoneCoreListener listener,
+ String userConfig, String factoryConfig, Object userdata)
+ throws LinphoneCoreException {
+ try {
+ return new LinphoneCoreImpl(listener,new File(userConfig),new File(factoryConfig),userdata);
+ } catch (IOException e) {
+ throw new LinphoneCoreException("Cannot create LinphoneCore",e);
+ }
+ }
+
+ @Override
+ public LinphoneCore createLinphoneCore(LinphoneCoreListener listener) throws LinphoneCoreException {
+ try {
+ return new LinphoneCoreImpl(listener);
+ } catch (IOException e) {
+ throw new LinphoneCoreException("Cannot create LinphoneCore",e);
+ }
+ }
+
+ @Override
+ public LinphoneProxyConfig createProxyConfig(String identity, String proxy,
+ String route, boolean enableRegister) throws LinphoneCoreException {
+ return new LinphoneProxyConfigImpl(identity,proxy,route,enableRegister);
+ }
+
+ @Override
+ public native void setDebugMode(boolean enable);
+
+ @Override
+ public void setLogHandler(LinphoneLogHandler handler) {
+ //not implemented on Android
+
+ }
+
+ @Override
+ public LinphoneFriend createLinphoneFriend(String friendUri) {
+ return new LinphoneFriendImpl(friendUri);
+ }
+
+ @Override
+ public LinphoneFriend createLinphoneFriend() {
+ return createLinphoneFriend(null);
+ }
+
+ public static boolean hasNeonInCpuFeatures()
+ {
+ ProcessBuilder cmd;
+ boolean result = false;
+
+ try {
+ String[] args = {"/system/bin/cat", "/proc/cpuinfo"};
+ cmd = new ProcessBuilder(args);
+
+ Process process = cmd.start();
+ InputStream in = process.getInputStream();
+ byte[] re = new byte[1024];
+ while(in.read(re) != -1){
+ String line = new String(re);
+ if (line.contains("Features")) {
+ result = line.contains("neon");
+ break;
+ }
+ }
+ in.close();
+ } catch(IOException ex){
+ ex.printStackTrace();
+ }
+ return result;
+ }
+
+ public static boolean isArmv7()
+ {
+ return System.getProperty("os.arch").contains("armv7");
+ }
+}
--- /dev/null
+/*
+LinphoneCoreImpl.java
+Copyright (C) 2010 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+package org.linphone.core;
+
+import java.io.File;
+import java.io.IOException;
+
+
+class LinphoneCoreImpl implements LinphoneCore {
+
+ private final LinphoneCoreListener mListener; //to make sure to keep a reference on this object
+ private long nativePtr = 0;
+ private native long newLinphoneCore(LinphoneCoreListener listener,String userConfig,String factoryConfig,Object userdata);
+ private native void iterate(long nativePtr);
+ private native long getDefaultProxyConfig(long nativePtr);
+
+ private native void setDefaultProxyConfig(long nativePtr,long proxyCfgNativePtr);
+ private native int addProxyConfig(LinphoneProxyConfig jprtoxyCfg,long nativePtr,long proxyCfgNativePtr);
+ private native void clearAuthInfos(long nativePtr);
+
+ private native void clearProxyConfigs(long nativePtr);
+ private native void addAuthInfo(long nativePtr,long authInfoNativePtr);
+ private native Object invite(long nativePtr,String uri);
+ private native void terminateCall(long nativePtr, long call);
+ private native long getRemoteAddress(long nativePtr);
+ private native boolean isInCall(long nativePtr);
+ private native boolean isInComingInvitePending(long nativePtr);
+ private native void acceptCall(long nativePtr, long call);
+ private native long getCallLog(long nativePtr,int position);
+ private native int getNumberOfCallLogs(long nativePtr);
+ private native void delete(long nativePtr);
+ private native void setNetworkStateReachable(long nativePtr,boolean isReachable);
+ private native boolean isNetworkStateReachable(long nativePtr);
+ private native void setPlaybackGain(long nativeptr, float gain);
+ private native float getPlaybackGain(long nativeptr);
+ private native void muteMic(long nativePtr,boolean isMuted);
+ private native long interpretUrl(long nativePtr,String destination);
+ private native Object inviteAddress(long nativePtr,long to);
+ private native Object inviteAddressWithParams(long nativePtrLc,long to, long nativePtrParam);
+ private native void sendDtmf(long nativePtr,char dtmf);
+ private native void clearCallLogs(long nativePtr);
+ private native boolean isMicMuted(long nativePtr);
+ private native long findPayloadType(long nativePtr, String mime, int clockRate, int channels);
+ private native int enablePayloadType(long nativePtr, long payloadType, boolean enable);
+ private native void enableEchoCancellation(long nativePtr,boolean enable);
+ private native boolean isEchoCancellationEnabled(long nativePtr);
+ private native Object getCurrentCall(long nativePtr) ;
+ private native void playDtmf(long nativePtr,char dtmf,int duration);
+ private native void stopDtmf(long nativePtr);
+ private native void setVideoWindowId(long nativePtr, Object wid);
+ private native void setPreviewWindowId(long nativePtr, Object wid);
+ private native void setDeviceRotation(long nativePtr, int rotation);
+ private native void addFriend(long nativePtr,long friend);
+ private native void setPresenceInfo(long nativePtr,int minute_away, String alternative_contact,int status);
+ private native long createChatRoom(long nativePtr,String to);
+ private native void enableVideo(long nativePtr,boolean vcap_enabled,boolean display_enabled);
+ private native boolean isVideoEnabled(long nativePtr);
+ private native void setFirewallPolicy(long nativePtr, int enum_value);
+ private native int getFirewallPolicy(long nativePtr);
+ private native void setStunServer(long nativePtr, String stun_server);
+ private native String getStunServer(long nativePtr);
+ private native long createDefaultCallParams(long nativePtr);
+ private native int updateCall(long ptrLc, long ptrCall, long ptrParams);
+ private native void setUploadBandwidth(long nativePtr, int bw);
+ private native void setDownloadBandwidth(long nativePtr, int bw);
+ private native void setPreferredVideoSize(long nativePtr, int width, int heigth);
+ private native int[] getPreferredVideoSize(long nativePtr);
+ private native void setRing(long nativePtr, String path);
+ private native String getRing(long nativePtr);
+ private native void setRootCA(long nativePtr, String path);
+ private native long[] listVideoPayloadTypes(long nativePtr);
+ private native long[] getProxyConfigList(long nativePtr);
+ private native long[] listAudioPayloadTypes(long nativePtr);
+ private native void enableKeepAlive(long nativePtr,boolean enable);
+ private native boolean isKeepAliveEnabled(long nativePtr);
+ private native int startEchoCalibration(long nativePtr,Object data);
+ private native int getSignalingTransportPort(long nativePtr, int code);
+ private native void setSignalingTransportPorts(long nativePtr, int udp, int tcp, int tls);
+ private native void enableIpv6(long nativePtr,boolean enable);
+ private native int pauseCall(long nativePtr, long callPtr);
+ private native int pauseAllCalls(long nativePtr);
+ private native int resumeCall(long nativePtr, long callPtr);
+ private native void setUploadPtime(long nativePtr, int ptime);
+ private native void setDownloadPtime(long nativePtr, int ptime);
+ private native void setZrtpSecretsCache(long nativePtr, String file);
+ private native void enableEchoLimiter(long nativePtr2, boolean val);
+ private native int setVideoDevice(long nativePtr2, int id);
+ private native int getVideoDevice(long nativePtr2);
+ private native int getMediaEncryption(long nativePtr);
+ private native void setMediaEncryption(long nativePtr, int menc);
+ private native boolean isMediaEncryptionMandatory(long nativePtr);
+ private native void setMediaEncryptionMandatory(long nativePtr, boolean yesno);
+ private native void removeCallLog(long nativePtr, long callLogPtr);
+ private native int getMissedCallsCount(long nativePtr);
+ private native void resetMissedCallsCount(long nativePtr);
+ private native String getVersion(long nativePtr);
+ private native void setAudioPort(long nativePtr, int port);
+ private native void setVideoPort(long nativePtr, int port);
+ private native void setAudioPortRange(long nativePtr, int minPort, int maxPort);
+ private native void setVideoPortRange(long nativePtr, int minPort, int maxPort);
+ private native void setIncomingTimeout(long nativePtr, int timeout);
+
+ LinphoneCoreImpl(LinphoneCoreListener listener, File userConfig,File factoryConfig,Object userdata) throws IOException {
+ mListener=listener;
+ nativePtr = newLinphoneCore(listener,userConfig.getCanonicalPath(),factoryConfig.getCanonicalPath(),userdata);
+ }
+ LinphoneCoreImpl(LinphoneCoreListener listener) throws IOException {
+ mListener=listener;
+ nativePtr = newLinphoneCore(listener,null,null,null);
+ }
+
+ protected void finalize() throws Throwable {
+
+ }
+
+ public synchronized void addAuthInfo(LinphoneAuthInfo info) {
+ isValid();
+ addAuthInfo(nativePtr,((LinphoneAuthInfoImpl)info).nativePtr);
+ }
+
+
+
+ public synchronized LinphoneProxyConfig getDefaultProxyConfig() {
+ isValid();
+ long lNativePtr = getDefaultProxyConfig(nativePtr);
+ if (lNativePtr!=0) {
+ return new LinphoneProxyConfigImpl(lNativePtr);
+ } else {
+ return null;
+ }
+ }
+
+ public synchronized LinphoneCall invite(String uri) {
+ isValid();
+ return (LinphoneCall)invite(nativePtr,uri);
+ }
+
+ public synchronized void iterate() {
+ isValid();
+ iterate(nativePtr);
+ }
+
+ public synchronized void setDefaultProxyConfig(LinphoneProxyConfig proxyCfg) {
+ isValid();
+ setDefaultProxyConfig(nativePtr,((LinphoneProxyConfigImpl)proxyCfg).nativePtr);
+ }
+ public synchronized void addProxyConfig(LinphoneProxyConfig proxyCfg) throws LinphoneCoreException{
+ isValid();
+ if (addProxyConfig(proxyCfg,nativePtr,((LinphoneProxyConfigImpl)proxyCfg).nativePtr) !=0) {
+ throw new LinphoneCoreException("bad proxy config");
+ }
+ }
+ public synchronized void clearAuthInfos() {
+ isValid();
+ clearAuthInfos(nativePtr);
+
+ }
+ public synchronized void clearProxyConfigs() {
+ isValid();
+ clearProxyConfigs(nativePtr);
+ }
+ public synchronized void terminateCall(LinphoneCall aCall) {
+ isValid();
+ if (aCall!=null)terminateCall(nativePtr,((LinphoneCallImpl)aCall).nativePtr);
+ }
+ public synchronized LinphoneAddress getRemoteAddress() {
+ isValid();
+ long ptr = getRemoteAddress(nativePtr);
+ if (ptr==0) {
+ return null;
+ } else {
+ return new LinphoneAddressImpl(ptr);
+ }
+ }
+ public synchronized boolean isIncall() {
+ isValid();
+ return isInCall(nativePtr);
+ }
+ public synchronized boolean isInComingInvitePending() {
+ isValid();
+ return isInComingInvitePending(nativePtr);
+ }
+ public synchronized void acceptCall(LinphoneCall aCall) {
+ isValid();
+ acceptCall(nativePtr,((LinphoneCallImpl)aCall).nativePtr);
+
+ }
+ public synchronized LinphoneCallLog[] getCallLogs() {
+ isValid();
+ LinphoneCallLog[] logs = new LinphoneCallLog[getNumberOfCallLogs(nativePtr)];
+ for (int i=0;i < getNumberOfCallLogs(nativePtr);i++) {
+ logs[i] = new LinphoneCallLogImpl(getCallLog(nativePtr, i));
+ }
+ return logs;
+ }
+ public synchronized void destroy() {
+ isValid();
+ delete(nativePtr);
+ nativePtr = 0;
+ }
+
+ private void isValid() {
+ if (nativePtr == 0) {
+ throw new RuntimeException("object already destroyed");
+ }
+ }
+ public synchronized void setNetworkReachable(boolean isReachable) {
+ setNetworkStateReachable(nativePtr,isReachable);
+ }
+ public synchronized void setPlaybackGain(float gain) {
+ setPlaybackGain(nativePtr,gain);
+
+ }
+ public synchronized float getPlaybackGain() {
+ return getPlaybackGain(nativePtr);
+ }
+ public synchronized void muteMic(boolean isMuted) {
+ muteMic(nativePtr,isMuted);
+ }
+ public synchronized LinphoneAddress interpretUrl(String destination) throws LinphoneCoreException {
+ long lAddress = interpretUrl(nativePtr,destination);
+ if (lAddress != 0) {
+ return new LinphoneAddressImpl(lAddress,true);
+ } else {
+ throw new LinphoneCoreException("Cannot interpret ["+destination+"]");
+ }
+ }
+ public synchronized LinphoneCall invite(LinphoneAddress to) throws LinphoneCoreException {
+ LinphoneCall call = (LinphoneCall)inviteAddress(nativePtr,((LinphoneAddressImpl)to).nativePtr);
+ if (call!=null) {
+ return call;
+ } else {
+ throw new LinphoneCoreException("Unable to invite address " + to.asString());
+ }
+ }
+
+ public synchronized void sendDtmf(char number) {
+ sendDtmf(nativePtr,number);
+ }
+ public synchronized void clearCallLogs() {
+ clearCallLogs(nativePtr);
+ }
+ public synchronized boolean isMicMuted() {
+ return isMicMuted(nativePtr);
+ }
+ public synchronized PayloadType findPayloadType(String mime, int clockRate, int channels) {
+ isValid();
+ long playLoadType = findPayloadType(nativePtr, mime, clockRate, channels);
+ if (playLoadType == 0) {
+ return null;
+ } else {
+ return new PayloadTypeImpl(playLoadType);
+ }
+ }
+ public synchronized void enablePayloadType(PayloadType pt, boolean enable)
+ throws LinphoneCoreException {
+ isValid();
+ if (enablePayloadType(nativePtr,((PayloadTypeImpl)pt).nativePtr,enable) != 0) {
+ throw new LinphoneCoreException("cannot enable payload type ["+pt+"]");
+ }
+
+ }
+ public synchronized void enableEchoCancellation(boolean enable) {
+ isValid();
+ enableEchoCancellation(nativePtr, enable);
+ }
+ public synchronized boolean isEchoCancellationEnabled() {
+ isValid();
+ return isEchoCancellationEnabled(nativePtr);
+
+ }
+
+ public synchronized LinphoneCall getCurrentCall() {
+ isValid();
+ return (LinphoneCall)getCurrentCall(nativePtr);
+ }
+
+ public int getPlayLevel() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+ public void setPlayLevel(int level) {
+ // TODO Auto-generated method stub
+
+ }
+ public void enableSpeaker(boolean value) {
+ // TODO Auto-generated method stub
+
+ }
+ public boolean isSpeakerEnabled() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+ public synchronized void playDtmf(char number, int duration) {
+ playDtmf(nativePtr,number, duration);
+
+ }
+ public synchronized void stopDtmf() {
+ stopDtmf(nativePtr);
+ }
+
+ public synchronized void addFriend(LinphoneFriend lf) throws LinphoneCoreException {
+ addFriend(nativePtr,((LinphoneFriendImpl)lf).nativePtr);
+
+ }
+ public synchronized void setPresenceInfo(int minute_away, String alternative_contact,
+ OnlineStatus status) {
+ setPresenceInfo(nativePtr,minute_away,alternative_contact,status.mValue);
+
+ }
+ public synchronized LinphoneChatRoom createChatRoom(String to) {
+ return new LinphoneChatRoomImpl(createChatRoom(nativePtr,to));
+ }
+ public synchronized void setPreviewWindow(Object w) {
+ setPreviewWindowId(nativePtr,w);
+ }
+ public synchronized void setVideoWindow(Object w) {
+ setVideoWindowId(nativePtr, w);
+ }
+ public synchronized void setDeviceRotation(int rotation) {
+ setDeviceRotation(nativePtr, rotation);
+ }
+
+ public synchronized void enableVideo(boolean vcap_enabled, boolean display_enabled) {
+ enableVideo(nativePtr,vcap_enabled, display_enabled);
+ }
+ public synchronized boolean isVideoEnabled() {
+ return isVideoEnabled(nativePtr);
+ }
+ public synchronized FirewallPolicy getFirewallPolicy() {
+ return FirewallPolicy.fromInt(getFirewallPolicy(nativePtr));
+ }
+ public synchronized String getStunServer() {
+ return getStunServer(nativePtr);
+ }
+ public synchronized void setFirewallPolicy(FirewallPolicy pol) {
+ setFirewallPolicy(nativePtr,pol.value());
+ }
+ public synchronized void setStunServer(String stunServer) {
+ setStunServer(nativePtr,stunServer);
+ }
+
+ public synchronized LinphoneCallParams createDefaultCallParameters() {
+ return new LinphoneCallParamsImpl(createDefaultCallParams(nativePtr));
+ }
+
+ public synchronized LinphoneCall inviteAddressWithParams(LinphoneAddress to, LinphoneCallParams params) throws LinphoneCoreException {
+ long ptrDestination = ((LinphoneAddressImpl)to).nativePtr;
+ long ptrParams =((LinphoneCallParamsImpl)params).nativePtr;
+
+ LinphoneCall call = (LinphoneCall)inviteAddressWithParams(nativePtr, ptrDestination, ptrParams);
+ if (call!=null) {
+ return call;
+ } else {
+ throw new LinphoneCoreException("Unable to invite with params " + to.asString());
+ }
+ }
+
+ public synchronized int updateCall(LinphoneCall call, LinphoneCallParams params) {
+ long ptrCall = ((LinphoneCallImpl) call).nativePtr;
+ long ptrParams = params!=null ? ((LinphoneCallParamsImpl)params).nativePtr : 0;
+
+ return updateCall(nativePtr, ptrCall, ptrParams);
+ }
+ public synchronized void setUploadBandwidth(int bw) {
+ setUploadBandwidth(nativePtr, bw);
+ }
+
+ public synchronized void setDownloadBandwidth(int bw) {
+ setDownloadBandwidth(nativePtr, bw);
+ }
+
+ public synchronized void setPreferredVideoSize(VideoSize vSize) {
+ setPreferredVideoSize(nativePtr, vSize.width, vSize.height);
+ }
+
+ public synchronized VideoSize getPreferredVideoSize() {
+ int[] nativeSize = getPreferredVideoSize(nativePtr);
+
+ VideoSize vSize = new VideoSize();
+ vSize.width = nativeSize[0];
+ vSize.height = nativeSize[1];
+ return vSize;
+ }
+ public synchronized void setRing(String path) {
+ setRing(nativePtr, path);
+ }
+ public synchronized String getRing() {
+ return getRing(nativePtr);
+ }
+
+ public synchronized void setRootCA(String path) {
+ setRootCA(nativePtr, path);
+ }
+
+ public synchronized LinphoneProxyConfig[] getProxyConfigList() {
+ long[] typesPtr = getProxyConfigList(nativePtr);
+ if (typesPtr == null) return null;
+
+ LinphoneProxyConfig[] proxies = new LinphoneProxyConfig[typesPtr.length];
+
+ for (int i=0; i < proxies.length; i++) {
+ proxies[i] = new LinphoneProxyConfigImpl(typesPtr[i]);
+ }
+
+ return proxies;
+ }
+
+ public synchronized PayloadType[] getVideoCodecs() {
+ long[] typesPtr = listVideoPayloadTypes(nativePtr);
+ if (typesPtr == null) return null;
+
+ PayloadType[] codecs = new PayloadType[typesPtr.length];
+
+ for (int i=0; i < codecs.length; i++) {
+ codecs[i] = new PayloadTypeImpl(typesPtr[i]);
+ }
+
+ return codecs;
+ }
+ public synchronized PayloadType[] getAudioCodecs() {
+ long[] typesPtr = listAudioPayloadTypes(nativePtr);
+ if (typesPtr == null) return null;
+
+ PayloadType[] codecs = new PayloadType[typesPtr.length];
+
+ for (int i=0; i < codecs.length; i++) {
+ codecs[i] = new PayloadTypeImpl(typesPtr[i]);
+ }
+
+ return codecs;
+ }
+ public synchronized boolean isNetworkReachable() {
+ return isNetworkStateReachable(nativePtr);
+ }
+
+ public synchronized void enableKeepAlive(boolean enable) {
+ enableKeepAlive(nativePtr,enable);
+
+ }
+ public synchronized boolean isKeepAliveEnabled() {
+ return isKeepAliveEnabled(nativePtr);
+ }
+ public synchronized void startEchoCalibration(Object data) throws LinphoneCoreException {
+ startEchoCalibration(nativePtr, data);
+ }
+
+ public synchronized Transports getSignalingTransportPorts() {
+ Transports transports = new Transports();
+ transports.udp = getSignalingTransportPort(nativePtr, 0);
+ transports.tcp = getSignalingTransportPort(nativePtr, 1);
+ transports.tls = getSignalingTransportPort(nativePtr, 3);
+ // See C struct LCSipTransports in linphonecore.h
+ // Code is the index in the structure
+ return transports;
+ }
+ public synchronized void setSignalingTransportPorts(Transports transports) {
+ setSignalingTransportPorts(nativePtr, transports.udp, transports.tcp, transports.tls);
+ }
+
+ public synchronized void enableIpv6(boolean enable) {
+ enableIpv6(nativePtr,enable);
+ }
+ public synchronized void adjustSoftwareVolume(int i) {
+ //deprecated, does the same as setPlaybackGain().
+ }
+
+ public synchronized boolean pauseCall(LinphoneCall call) {
+ return 0 == pauseCall(nativePtr, ((LinphoneCallImpl) call).nativePtr);
+ }
+ public synchronized boolean resumeCall(LinphoneCall call) {
+ return 0 == resumeCall(nativePtr, ((LinphoneCallImpl) call).nativePtr);
+ }
+ public synchronized boolean pauseAllCalls() {
+ return 0 == pauseAllCalls(nativePtr);
+ }
+ public synchronized void setDownloadPtime(int ptime) {
+ setDownloadPtime(nativePtr,ptime);
+
+ }
+ public synchronized void setUploadPtime(int ptime) {
+ setUploadPtime(nativePtr,ptime);
+ }
+
+ public synchronized void setZrtpSecretsCache(String file) {
+ setZrtpSecretsCache(nativePtr,file);
+ }
+ public synchronized void enableEchoLimiter(boolean val) {
+ enableEchoLimiter(nativePtr,val);
+ }
+ public void setVideoDevice(int id) {
+ Log.i("Setting camera id :", id);
+ if (setVideoDevice(nativePtr, id) != 0) {
+ Log.e("Failed to set video device to id:", id);
+ }
+ }
+ public int getVideoDevice() {
+ return getVideoDevice(nativePtr);
+ }
+
+
+ private native void leaveConference(long nativePtr);
+ public synchronized void leaveConference() {
+ leaveConference(nativePtr);
+ }
+
+ private native boolean enterConference(long nativePtr);
+ public synchronized boolean enterConference() {
+ return enterConference(nativePtr);
+ }
+
+ private native boolean isInConference(long nativePtr);
+ public synchronized boolean isInConference() {
+ return isInConference(nativePtr);
+ }
+
+ private native void terminateConference(long nativePtr);
+ public synchronized void terminateConference() {
+ terminateConference(nativePtr);
+ }
+ private native int getConferenceSize(long nativePtr);
+ public synchronized int getConferenceSize() {
+ return getConferenceSize(nativePtr);
+ }
+ private native int getCallsNb(long nativePtr);
+ public synchronized int getCallsNb() {
+ return getCallsNb(nativePtr);
+ }
+ private native void terminateAllCalls(long nativePtr);
+ public synchronized void terminateAllCalls() {
+ terminateAllCalls(nativePtr);
+ }
+ private native Object getCall(long nativePtr, int position);
+ public synchronized LinphoneCall[] getCalls() {
+ int size = getCallsNb(nativePtr);
+ LinphoneCall[] calls = new LinphoneCall[size];
+ for (int i=0; i < size; i++) {
+ calls[i]=((LinphoneCall)getCall(nativePtr, i));
+ }
+ return calls;
+ }
+ private native void addAllToConference(long nativePtr);
+ public synchronized void addAllToConference() {
+ addAllToConference(nativePtr);
+
+ }
+ private native void addToConference(long nativePtr, long nativePtrLcall);
+ public synchronized void addToConference(LinphoneCall call) {
+ addToConference(nativePtr, getCallPtr(call));
+
+ }
+ private native void removeFromConference(long nativePtr, long nativeCallPtr);
+ public synchronized void removeFromConference(LinphoneCall call) {
+ removeFromConference(nativePtr,getCallPtr(call));
+ }
+
+ private long getCallPtr(LinphoneCall call) {
+ return ((LinphoneCallImpl)call).nativePtr;
+ }
+
+ private long getCallParamsPtr(LinphoneCallParams callParams) {
+ return ((LinphoneCallParamsImpl)callParams).nativePtr;
+ }
+
+ private native int transferCall(long nativePtr, long callPtr, String referTo);
+ public synchronized void transferCall(LinphoneCall call, String referTo) {
+ transferCall(nativePtr, getCallPtr(call), referTo);
+ }
+
+ private native int transferCallToAnother(long nativePtr, long callPtr, long destPtr);
+ public synchronized void transferCallToAnother(LinphoneCall call, LinphoneCall dest) {
+ transferCallToAnother(nativePtr, getCallPtr(call), getCallPtr(dest));
+ }
+
+ private native Object findCallFromUri(long nativePtr, String uri);
+ @Override
+ public synchronized LinphoneCall findCallFromUri(String uri) {
+ return (LinphoneCall) findCallFromUri(nativePtr, uri);
+ }
+
+ public synchronized MediaEncryption getMediaEncryption() {
+ return MediaEncryption.fromInt(getMediaEncryption(nativePtr));
+ }
+ public synchronized boolean isMediaEncryptionMandatory() {
+ return isMediaEncryptionMandatory(nativePtr);
+ }
+ public synchronized void setMediaEncryption(MediaEncryption menc) {
+ setMediaEncryption(nativePtr, menc.mValue);
+ }
+ public synchronized void setMediaEncryptionMandatory(boolean yesno) {
+ setMediaEncryptionMandatory(nativePtr, yesno);
+ }
+
+ private native int getMaxCalls(long nativePtr);
+ public synchronized int getMaxCalls() {
+ return getMaxCalls(nativePtr);
+ }
+ @Override
+ public boolean isMyself(String uri) {
+ LinphoneProxyConfig lpc = getDefaultProxyConfig();
+ if (lpc == null) return false;
+ return uri.equals(lpc.getIdentity());
+ }
+
+ private native boolean soundResourcesLocked(long nativePtr);
+ public synchronized boolean soundResourcesLocked() {
+ return soundResourcesLocked(nativePtr);
+ }
+
+ private native void setMaxCalls(long nativePtr, int max);
+ @Override
+ public synchronized void setMaxCalls(int max) {
+ setMaxCalls(nativePtr, max);
+ }
+ private native boolean isEchoLimiterEnabled(long nativePtr);
+ @Override
+ public synchronized boolean isEchoLimiterEnabled() {
+ return isEchoLimiterEnabled(nativePtr);
+ }
+ private native boolean mediaEncryptionSupported(long nativePtr, int menc);
+ @Override
+ public synchronized boolean mediaEncryptionSupported(MediaEncryption menc) {
+ return mediaEncryptionSupported(nativePtr,menc.mValue);
+ }
+
+ private native void setPlayFile(long nativePtr, String path);
+
+ @Override
+ public synchronized void setPlayFile(String path) {
+ setPlayFile(nativePtr, path);
+ }
+
+
+ private native void tunnelAddServerAndMirror(long nativePtr, String host, int port, int mirror, int ms);
+ @Override
+ public synchronized void tunnelAddServerAndMirror(String host, int port, int mirror, int ms) {
+ tunnelAddServerAndMirror(nativePtr, host, port, mirror, ms);
+ }
+
+ private native void tunnelAutoDetect(long nativePtr);
+ @Override
+ public synchronized void tunnelAutoDetect() {
+ tunnelAutoDetect(nativePtr);
+ }
+
+ private native void tunnelCleanServers(long nativePtr);
+ @Override
+ public synchronized void tunnelCleanServers() {
+ tunnelCleanServers(nativePtr);
+ }
+
+ private native void tunnelEnable(long nativePtr, boolean enable);
+ @Override
+ public synchronized void tunnelEnable(boolean enable) {
+ tunnelEnable(nativePtr, enable);
+ }
+
+ @Override
+ public native boolean isTunnelAvailable();
+
+ private native void acceptCallWithParams(long nativePtr, long aCall,
+ long params);
+ @Override
+ public synchronized void acceptCallWithParams(LinphoneCall aCall,
+ LinphoneCallParams params) throws LinphoneCoreException {
+ acceptCallWithParams(nativePtr, getCallPtr(aCall), getCallParamsPtr(params));
+ }
+
+ private native void acceptCallUpdate(long nativePtr, long aCall, long params);
+ @Override
+ public synchronized void acceptCallUpdate(LinphoneCall aCall, LinphoneCallParams params)
+ throws LinphoneCoreException {
+ acceptCallUpdate(nativePtr, getCallPtr(aCall), getCallParamsPtr(params));
+ }
+
+ private native void deferCallUpdate(long nativePtr, long aCall);
+ @Override
+ public synchronized void deferCallUpdate(LinphoneCall aCall)
+ throws LinphoneCoreException {
+ deferCallUpdate(nativePtr, getCallPtr(aCall));
+ }
+
+ private native void setVideoPolicy(long nativePtr, boolean autoInitiate, boolean autoAccept);
+ public synchronized void setVideoPolicy(boolean autoInitiate, boolean autoAccept) {
+ setVideoPolicy(nativePtr, autoInitiate, autoAccept);
+ }
+ private native void setUserAgent(long nativePtr, String name, String version);
+ @Override
+ public void setUserAgent(String name, String version) {
+ setUserAgent(nativePtr,name,version);
+ }
+
+ private native void setCpuCountNative(int count);
+ public void setCpuCount(int count)
+ {
+ setCpuCountNative(count);
+ }
+
+ public int getMissedCallsCount() {
+ return getMissedCallsCount(nativePtr);
+ }
+
+ public void removeCallLog(LinphoneCallLog log) {
+ removeCallLog(nativePtr, ((LinphoneCallLogImpl) log).getNativePtr());
+ }
+
+ public void resetMissedCallsCount() {
+ resetMissedCallsCount(nativePtr);
+ }
+
+ private native void tunnelSetHttpProxy(long nativePtr, String proxy_host, int port,
+ String username, String password);
+ @Override
+ public void tunnelSetHttpProxy(String proxy_host, int port,
+ String username, String password) {
+ tunnelSetHttpProxy(nativePtr, proxy_host, port, username, password);
+ }
+
+ private native void refreshRegisters(long nativePtr);
+ public void refreshRegisters() {
+ refreshRegisters(nativePtr);
+ }
+
+ @Override
+ public String getVersion() {
+ return getVersion(nativePtr);
+ }
+
+ @Override
+ public PayloadType findPayloadType(String mime, int clockRate) {
+ return null;
+ }
+
+ private native void removeFriend(long ptr, long lf);
+ @Override
+ public void removeFriend(LinphoneFriend lf) {
+ removeFriend(nativePtr, lf.getNativePtr());
+ }
+
+ private native long getFriendByAddress(long ptr, String sipUri);
+ @Override
+ public LinphoneFriend findFriendByAddress(String sipUri) {
+ long ptr = getFriendByAddress(nativePtr, sipUri);
+ if (ptr == 0) {
+ return null;
+ }
+ return new LinphoneFriendImpl(ptr);
+ }
+
+ public void setAudioPort(int port) {
+ setAudioPort(nativePtr, port);
+ }
+
+ public void setVideoPort(int port) {
+ setVideoPort(nativePtr, port);
+ }
+
+ public void setAudioPortRange(int minPort, int maxPort) {
+ setAudioPortRange(nativePtr, minPort, maxPort);
+ }
+
+ public void setVideoPortRange(int minPort, int maxPort) {
+ setVideoPortRange(nativePtr, minPort, maxPort);
+ }
+
+ public void setIncomingTimeout(int timeout) {
+ setIncomingTimeout(nativePtr, timeout);
+ }
+}
--- /dev/null
+/*
+LinphoneFriendImpl.java
+Copyright (C) 2010 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+package org.linphone.core;
+
+import java.io.Serializable;
+
+class LinphoneFriendImpl implements LinphoneFriend, Serializable {
+ protected final long nativePtr;
+ private native long newLinphoneFriend(String friendUri);
+ private native void setAddress(long nativePtr,long friend);
+ private native long getAddress(long nativePtr);
+ private native void setIncSubscribePolicy(long nativePtr,int enumValue);
+ private native int getIncSubscribePolicy(long nativePtr);
+ private native void enableSubscribes(long nativePtr,boolean value);
+ private native boolean isSubscribesEnabled(long nativePtr);
+ private native int getStatus(long nativePtr);
+ private native void edit(long nativePtr);
+ private native void done(long nativePtr);
+
+ private native void delete(long ptr);
+ boolean ownPtr = false;
+ protected LinphoneFriendImpl() {
+ nativePtr = newLinphoneFriend(null);
+ }
+ protected LinphoneFriendImpl(String friendUri) {
+ nativePtr = newLinphoneFriend(friendUri);
+ }
+ protected LinphoneFriendImpl(long aNativePtr) {
+ nativePtr = aNativePtr;
+ ownPtr=false;
+ }
+ protected void finalize() throws Throwable {
+ if (ownPtr) delete(nativePtr);
+ }
+ public void setAddress(LinphoneAddress anAddress) {
+ this.setAddress(nativePtr, ((LinphoneAddressImpl)anAddress).nativePtr);
+ }
+ public LinphoneAddress getAddress() {
+ return new LinphoneAddressImpl(getAddress(nativePtr));
+ }
+ public void setIncSubscribePolicy(SubscribePolicy policy) {
+ setIncSubscribePolicy(nativePtr,policy.mValue);
+ }
+ public SubscribePolicy getIncSubscribePolicy() {
+ return SubscribePolicy.fromInt(getIncSubscribePolicy(nativePtr)) ;
+ }
+ public void enableSubscribes(boolean enable) {
+ enableSubscribes(nativePtr, enable);
+ }
+ public boolean isSubscribesEnabled() {
+ return isSubscribesEnabled(nativePtr);
+ }
+ public OnlineStatus getStatus() {
+ return OnlineStatus.fromInt(getStatus(nativePtr));
+ }
+ public void edit() {
+ edit(nativePtr);
+ }
+ public void done() {
+ done(nativePtr);
+ }
+ public long getNativePtr() {
+ return nativePtr;
+ }
+}
--- /dev/null
+/*
+LinphoneProxyConfigImpl.java
+Copyright (C) 2010 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+package org.linphone.core;
+
+import org.linphone.core.LinphoneCore.RegistrationState;
+
+
+
+
+
+class LinphoneProxyConfigImpl implements LinphoneProxyConfig {
+
+ protected final long nativePtr;
+
+ private native int getState(long nativePtr);
+ private native void setExpires(long nativePtr, int delay);
+
+ boolean ownPtr = false;
+ protected LinphoneProxyConfigImpl(String identity,String proxy,String route, boolean enableRegister) throws LinphoneCoreException {
+ nativePtr = newLinphoneProxyConfig();
+ setIdentity(identity);
+ setProxy(proxy);
+ enableRegister(enableRegister);
+ ownPtr=true;
+ }
+ protected LinphoneProxyConfigImpl(long aNativePtr) {
+ nativePtr = aNativePtr;
+ ownPtr=false;
+ }
+ protected void finalize() throws Throwable {
+ //Log.e(LinphoneService.TAG,"fixme, should release underlying proxy config");
+ if (ownPtr) delete(nativePtr);
+ }
+ private native long newLinphoneProxyConfig();
+ private native void delete(long ptr);
+
+ private native void edit(long ptr);
+ private native void done(long ptr);
+
+ private native void setIdentity(long ptr,String identity);
+ private native String getIdentity(long ptr);
+ private native int setProxy(long ptr,String proxy);
+ private native String getProxy(long ptr);
+
+
+ private native void enableRegister(long ptr,boolean value);
+ private native boolean isRegisterEnabled(long ptr);
+
+ private native boolean isRegistered(long ptr);
+ private native void setDialPrefix(long ptr, String prefix);
+
+ private native String normalizePhoneNumber(long ptr,String number);
+
+ private native String getDomain(long ptr);
+
+ private native void setDialEscapePlus(long ptr, boolean value);
+
+ private native String getRoute(long ptr);
+ private native int setRoute(long ptr,String uri);
+ private native void enablePublish(long ptr,boolean enable);
+ private native boolean publishEnabled(long ptr);
+ private native void setContactParameters(long ptr, String params);
+
+ private native int lookupCCCFromIso(long nativePtr, String iso);
+
+ public void enableRegister(boolean value) {
+ enableRegister(nativePtr,value);
+ }
+
+ public void done() {
+ done(nativePtr);
+ }
+
+ public void edit() {
+ edit(nativePtr);
+ }
+
+ public void setIdentity(String identity) throws LinphoneCoreException {
+ setIdentity(nativePtr,identity);
+ }
+
+ public void setProxy(String proxyUri) throws LinphoneCoreException {
+ if (setProxy(nativePtr,proxyUri)!=0) {
+ throw new LinphoneCoreException("Bad proxy address ["+proxyUri+"]");
+ }
+ }
+ public String normalizePhoneNumber(String number) {
+ return normalizePhoneNumber(nativePtr,number);
+ }
+ public void setDialPrefix(String prefix) {
+ setDialPrefix(nativePtr, prefix);
+ }
+ public String getDomain() {
+ return getDomain(nativePtr);
+ }
+ public void setDialEscapePlus(boolean value) {
+ setDialEscapePlus(nativePtr,value);
+ }
+ public String getIdentity() {
+ return getIdentity(nativePtr);
+ }
+ public String getProxy() {
+ return getProxy(nativePtr);
+ }
+ public boolean isRegistered() {
+ return isRegistered(nativePtr);
+ }
+ public boolean registerEnabled() {
+ return isRegisterEnabled(nativePtr);
+ }
+ public String getRoute() {
+ return getRoute(nativePtr);
+ }
+ public void setRoute(String routeUri) throws LinphoneCoreException {
+ if (setRoute(nativePtr, routeUri) != 0) {
+ throw new LinphoneCoreException("cannot set route ["+routeUri+"]");
+ }
+ }
+ public void enablePublish(boolean enable) {
+ enablePublish(nativePtr,enable);
+ }
+ public RegistrationState getState() {
+ return RegistrationState.fromInt(getState(nativePtr));
+ }
+
+ public void setExpires(int delay) {
+ setExpires(nativePtr, delay);
+ }
+ public boolean publishEnabled() {
+ return publishEnabled(nativePtr);
+ }
+ @Override
+ public void setContactParameters(String params) {
+ setContactParameters(nativePtr, params);
+ }
+ @Override
+ public int lookupCCCFromIso(String iso) {
+ return lookupCCCFromIso(nativePtr, iso);
+ }
+}
--- /dev/null
+/*
+Log.java
+Copyright (C) 2011 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+package org.linphone.core;
+
+import static android.util.Log.DEBUG;
+import static android.util.Log.ERROR;
+import static android.util.Log.INFO;
+import static android.util.Log.WARN;
+
+/**
+ * Convenient wrapper for Android logs.
+ *
+ * @author Guillaume Beraudo
+ */
+public final class Log {
+
+ public static final String TAG = "Linphone";
+ private static final boolean useIsLoggable = false;
+
+ @SuppressWarnings(value="all")
+ private static boolean isLoggable(int level) {
+ return !useIsLoggable || android.util.Log.isLoggable(TAG, level);
+ }
+
+ public static void i(Object...objects) {
+ if (isLoggable(INFO)) {
+ android.util.Log.i(TAG, toString(objects));
+ }
+ }
+ public static void i(Throwable t, Object...objects) {
+ if (isLoggable(INFO)) {
+ android.util.Log.i(TAG, toString(objects), t);
+ }
+ }
+
+
+ public static void d(Object...objects) {
+ if (isLoggable(DEBUG)) {
+ android.util.Log.d(TAG, toString(objects));
+ }
+ }
+ public static void d(Throwable t, Object...objects) {
+ if (isLoggable(DEBUG)) {
+ android.util.Log.d(TAG, toString(objects), t);
+ }
+ }
+
+ public static void w(Object...objects) {
+ if (isLoggable(WARN)) {
+ android.util.Log.w(TAG, toString(objects));
+ }
+ }
+ public static void w(Throwable t, Object...objects) {
+ if (isLoggable(WARN)) {
+ android.util.Log.w(TAG, toString(objects), t);
+ }
+ }
+
+ public static void e(Object...objects) {
+ if (isLoggable(ERROR)) {
+ android.util.Log.e(TAG, toString(objects));
+ }
+ }
+ public static void e(Throwable t, Object...objects) {
+ if (isLoggable(ERROR)) {
+ android.util.Log.e(TAG, toString(objects), t);
+ }
+ }
+
+ /**
+ * @throws RuntimeException always throw after logging the error message.
+ */
+ public static void f(Object...objects) {
+ if (isLoggable(ERROR)) {
+ android.util.Log.e(TAG, toString(objects));
+ throw new RuntimeException("Fatal error : " + toString(objects));
+ }
+ }
+ /**
+ * @throws RuntimeException always throw after logging the error message.
+ */
+ public static void f(Throwable t, Object...objects) {
+ if (isLoggable(ERROR)) {
+ android.util.Log.e(TAG, toString(objects), t);
+ throw new RuntimeException("Fatal error : " + toString(objects), t);
+ }
+ }
+
+ private static String toString(Object...objects) {
+ StringBuilder sb = new StringBuilder();
+ for (Object o : objects) {
+ sb.append(o);
+ }
+ return sb.toString();
+ }
+}
--- /dev/null
+/*
+PayloadTypeImpl.java
+Copyright (C) 2010 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+package org.linphone.core;
+
+class PayloadTypeImpl implements PayloadType {
+
+ protected final long nativePtr;
+
+ private native String toString(long ptr);
+ private native String getMime(long ptr);
+ private native int getRate(long ptr);
+
+ protected PayloadTypeImpl(long aNativePtr) {
+ nativePtr = aNativePtr;
+ }
+
+ public int getRate() {
+ return getRate(nativePtr);
+ }
+
+ public String getMime() {
+ return getMime(nativePtr);
+ }
+
+ public String toString() {
+ return toString(nativePtr);
+ }
+}
--- /dev/null
+/*
+VideoUtil.java
+Copyright (C) 2011 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+package org.linphone.core.video;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.linphone.core.VideoSize;
+
+import android.hardware.Camera.Size;
+
+/**
+ * @author Guillaume Beraudo
+ */
+final class VideoUtil {
+
+ private VideoUtil() {}
+
+ public static List<VideoSize> createList(List<Size> supportedVideoSizes) {
+ List<VideoSize> converted = new ArrayList<VideoSize>(supportedVideoSizes.size());
+ for (Size s : supportedVideoSizes) {
+ converted.add(new VideoSize(s.width, s.height));
+ }
+ return converted;
+ }
+}
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*)
AC_CHECK_HEADERS(readline.h readline/readline.h, readline_h_found=yes)
AC_CHECK_HEADERS(history.h readline/history.h)
- AC_CHECK_LIB(readline, readline, [readline_libs_found=yes],[],[])
-
+ for termcap_lib in "" -ltermcap -lcurses -lncurses; do
+ unset ac_cv_lib_readline_readline
+ AC_CHECK_LIB(readline, readline, [readline_libs_found=yes],[],[$termcap_lib])
+ if test "x$readline_libs_found" = "xyes" ; then
+ READLINE_LIBS="$READLINE_LIBS -lreadline $termcap_lib"
+ break
+ fi
+ done
+
LIBS=$LIBS_save
CPPFLAGS=$CPPFLAGS_save
if test "$readline_libs_found$readline_h_found" != "yesyes" ; then
AC_MSG_WARN([Could not find libreadline headers or library, linphonec will have limited prompt features])
else
- READLINE_LIBS="$READLINE_LIBS -lreadline "
+ AC_DEFINE([HAVE_READLINE],1,[defined when compiling with readline support])
fi
-Subproject commit a457709df8daa72544fc36283c0053c4f09d0249
+Subproject commit 23c75b19523c172c97ba89c76cf7672fc804b14a
-Subproject commit cbe444a6098346311b412a5723190107e77d9c42
+Subproject commit ddc4f7d041967305483761fc9c643d3bb290a5f1
[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