Merge with linphone master

This commit is contained in:
Guillaume BIENKOWSKI 2014-10-06 11:16:23 +02:00
commit 3843205323
46 changed files with 1042 additions and 342 deletions

View file

@ -61,6 +61,13 @@ endif()
find_package(BelleSIP REQUIRED)
find_package(MS2 REQUIRED)
find_package(XML2 REQUIRED)
if(ENABLE_TUNNEL)
find_package(Tunnel)
if(NOT TUNNEL_FOUND)
message(WARNING "Could not find the tunnel library!")
set(ENABLE_TUNNEL OFF CACHE BOOL "Enable tunnel support" FORCE)
endif()
endif()
include_directories(
@ -72,6 +79,9 @@ include_directories(
${MS2_INCLUDE_DIRS}
${XML2_INCLUDE_DIRS}
)
if(ENABLE_TUNNEL)
include_directories(${TUNNEL_INCLUDE_DIRS})
endif()
if(MSVC)
include_directories(${CMAKE_PREFIX_PATH}/include/MSVC)
@ -94,6 +104,9 @@ add_definitions(-DHAVE_CONFIG_H)
add_subdirectory(coreapi)
add_subdirectory(share)
if(ENABLE_TOOLS)
add_subdirectory(tools)
endif()
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/FindLinphone.cmake

View file

@ -60,6 +60,8 @@ General rules for compilation
- all other commands (configure, autogen.sh, make) must be done within the mingw shell (msys).
In both msys and msys-git windows, change into the directory you created for sources:
cd /c/sources
- make sure pkg-config works by adding this env variable to your terminal:
export PKG_CONFIG_PATH=/usr/lib/pkgconfig
Building belle-sip
******************

View file

@ -898,8 +898,8 @@ dnl ##################################################
dnl # Check for doxygen
dnl ##################################################
AC_PATH_PROG(DOXYGEN,doxygen,false)
AM_CONDITIONAL(HAVE_DOXYGEN, test $DOXYGEN != false)
AC_CHECK_PROG(DOXYGEN,doxygen,doxygen,false)
AM_CONDITIONAL(HAVE_DOXYGEN, test "$DOXYGEN" != "false")
AC_CONFIG_FILES([

View file

@ -1601,7 +1601,7 @@ linphonec_proxy_add(LinphoneCore *lc)
*/
if ( enable_register==TRUE )
{
long int expires=0;
int expires=0;
while (1)
{
char *input=linphonec_readline("Specify register expiration time"
@ -1613,13 +1613,8 @@ linphonec_proxy_add(LinphoneCore *lc)
return;
}
expires=strtol(input, (char **)NULL, 10);
if ( expires == LONG_MIN || expires == LONG_MAX )
{
linphonec_out("Invalid value: %s\n", strerror(errno));
free(input);
continue;
}
expires=atoi(input);
if (expires==0) expires=600;
linphone_proxy_config_set_expires(cfg, expires);
linphonec_out("Expiration: %d seconds\n", linphone_proxy_config_get_expires (cfg));

View file

@ -500,7 +500,6 @@ static void *pipe_thread(void*p){
}
static void start_pipe_reader(void){
ms_mutex_init(&prompt_mutex,NULL);
pipe_reader_run=TRUE;
ortp_thread_create(&pipe_reader_th,NULL,pipe_thread,NULL);
}
@ -805,6 +804,7 @@ linphonec_finish(int exit_status)
if (mylogfile != NULL && mylogfile != stdout)
{
fclose (mylogfile);
mylogfile=stdout;
}
printf("\n");
exit(exit_status);

View file

@ -53,7 +53,6 @@ set(SOURCE_FILES
info.c
linphonecall.c
linphonecore.c
linphone_tunnel_stubs.c
linphone_tunnel_config.c
lpconfig.c
lsd.c
@ -89,6 +88,8 @@ if(ENABLE_TUNNEL)
TunnelManager.cc
)
add_definitions(-DTUNNEL_ENABLED)
else()
list(APPEND SOURCE_FILES linphone_tunnel_stubs.c)
endif()
set(GENERATED_SOURCE_FILES
@ -116,6 +117,9 @@ set(LIBS
${MS2_LIBRARIES}
${XML2_LIBRARIES}
)
if(ENABLE_TUNNEL)
list(APPEND LIBS ${TUNNEL_LIBRARIES})
endif()
if(WIN32)
list(APPEND LIBS shlwapi)
endif()

View file

@ -63,6 +63,7 @@ liblinphone_la_SOURCES=\
call_log.c \
call_params.c \
player.c \
fileplayer.c \
$(GITVERSION_FILE)
if BUILD_UPNP

View file

@ -96,6 +96,7 @@ RtpTransport *TunnelManager::createRtpTransport(int port){
}
void TunnelManager::startClient() {
ms_message("TunnelManager: Starting tunnel client");
if (mTunnelClient == NULL) {
mTunnelClient = new TunnelClient();
mTunnelClient->setCallback((TunnelClientController::StateCallback)tunnelCallback,this);
@ -111,9 +112,11 @@ void TunnelManager::startClient() {
if(mTunnelizeSipPackets) {
sal_enable_tunnel(mCore->sal, mTunnelClient);
}
mConnecting = true;
}
void TunnelManager::stopClient(){
ms_message("TunnelManager: Stopping tunnel client");
linphone_core_set_rtp_transport_factories(mCore,NULL);
sal_disable_tunnel(mCore->sal);
if (mTunnelClient){
@ -148,11 +151,12 @@ TunnelManager::TunnelManager(LinphoneCore* lc) :
mExosipTransport(NULL),
#endif
mMode(LinphoneTunnelModeDisable),
mTunnelClient(NULL),
mIsConnected(false),
mHttpProxyPort(0),
mPreviousRegistrationEnabled(false),
mAutoDetecting(false),
mConnecting(false),
mScheduledRegistration(false),
mTunnelizeSipPackets(true),
mTunnelClient(NULL),
mHttpProxyPort(0),
mVTable(NULL)
{
linphone_core_add_iterate_hook(mCore,(LinphoneCoreIterateHook)sOnIterate,this);
@ -170,84 +174,61 @@ TunnelManager::TunnelManager(LinphoneCore* lc) :
}
TunnelManager::~TunnelManager(){
for(UdpMirrorClientList::iterator udpMirror = mUdpMirrorClients.begin(); udpMirror != mUdpMirrorClients.end(); udpMirror++) {
udpMirror->stop();
}
stopClient();
linphone_core_remove_listener(mCore, mVTable);
linphone_vtable_destroy(mVTable);
}
void TunnelManager::registration(){
// registration occurs always after an unregistation has been made. First we
// need to reset the previous registration mode
LinphoneProxyConfig* lProxy;
linphone_core_get_default_proxy(mCore, &lProxy);
if (lProxy) {
linphone_proxy_config_edit(lProxy);
linphone_proxy_config_enable_register(lProxy,mPreviousRegistrationEnabled);
linphone_proxy_config_done(lProxy);
void TunnelManager::doRegistration(){
if(mTunnelizeSipPackets) {
LinphoneProxyConfig* lProxy;
linphone_core_get_default_proxy(mCore, &lProxy);
if (lProxy) {
ms_message("TunnelManager: need to register");
if(linphone_proxy_config_get_state(lProxy) != LinphoneRegistrationProgress) {
linphone_proxy_config_refresh_register(lProxy);
mScheduledRegistration = false;
} else {
ms_warning("TunnelManager: register difered. There is already a registration in progress");
mScheduledRegistration = true;
}
} else {
mScheduledRegistration = false;
}
}
}
void TunnelManager::processTunnelEvent(const Event &ev){
if (ev.mData.mConnected){
ms_message("Tunnel is up, registering now");
registration();
ms_message("Tunnel is connected");
doRegistration();
} else {
ms_error("Tunnel has been disconnected");
}
mConnecting = false;
}
void TunnelManager::waitUnRegistration() {
LinphoneProxyConfig* lProxy;
linphone_core_get_default_proxy(mCore, &lProxy);
if (lProxy){
mPreviousRegistrationEnabled=linphone_proxy_config_register_enabled(lProxy);
if (linphone_proxy_config_is_registered(lProxy)) {
int i=0;
linphone_proxy_config_edit(lProxy);
linphone_proxy_config_enable_register(lProxy,FALSE);
linphone_proxy_config_done(lProxy);
sal_unregister(lProxy->op);
//make sure unregister is sent and authenticated
do{
linphone_core_iterate(mCore);
ms_usleep(20000);
if (i>100){
ms_message("tunnel: timeout for unregistration expired, giving up");
break;
}
i++;
}while(linphone_proxy_config_is_registered(lProxy));
ms_message("Unregistration %s", linphone_proxy_config_is_registered(lProxy)?"failed":"succeeded");
}else{
ms_message("No registration pending");
}
}
}
/*Each time tunnel is enabled/disabled, we need to unregister previous session and re-register. Since tunnel initialization
is asynchronous, we temporary disable auto register while tunnel sets up, and reenable it when re-registering. */
void TunnelManager::setMode(LinphoneTunnelMode mode) {
if(mMode != mode) {
waitUnRegistration();
ms_message("TunnelManager: Switching mode from %s to %s",
tunnel_mode_to_string(mMode),
tunnel_mode_to_string(mode));
switch(mode) {
case LinphoneTunnelModeEnable:
mMode = mode;
startClient();
/* registration is done by proccessTunnelEvent() when the tunnel
the tunnel succeed to connect */
break;
case LinphoneTunnelModeDisable:
mMode = mode;
stopClient();
registration();
doRegistration();
break;
case LinphoneTunnelModeAuto:
mMode = mode;
autoDetect();
/* Registration is not needed because processUdpMirrorEvent() will
call either connect() or disconnect(). Should disconnect() is called,
processUdpMirrorEvent() care to call registratin() */
break;
default:
ms_error("TunnelManager::setMode(): invalid mode (%d)", mode);
@ -263,6 +244,10 @@ void TunnelManager::tunnelCallback(bool connected, TunnelManager *zis){
}
void TunnelManager::onIterate(){
if(mScheduledRegistration) {
ms_message("Apply difered registration");
doRegistration();
}
mMutex.lock();
while(!mEvq.empty()){
Event ev=mEvq.front();
@ -329,20 +314,21 @@ LinphoneTunnelMode TunnelManager::getMode() const {
void TunnelManager::processUdpMirrorEvent(const Event &ev){
if (ev.mData.mHaveUdp) {
LOGI("Tunnel is not required, disabling");
ms_message("TunnelManager: auto detection test succeed");
stopClient();
registration();
doRegistration();
mAutoDetecting = false;
} else {
ms_message("TunnelManager: auto detection test failed");
mCurrentUdpMirrorClient++;
if (mCurrentUdpMirrorClient !=mUdpMirrorClients.end()) {
// enable tunnel but also try backup server
LOGI("Tunnel is required, enabling; Trying backup udp mirror");
ms_message("TunnelManager: trying another udp mirror");
UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient;
lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this);
} else {
LOGI("Tunnel is required, enabling; no backup udp mirror available");
ms_message("TunnelManager: all auto detection failed. Need ti enable tunnel");
startClient();
mAutoDetecting = false;
}
}
}
@ -369,14 +355,18 @@ void TunnelManager::networkReachableCb(LinphoneCore *lc, bool_t reachable) {
}
void TunnelManager::autoDetect() {
// first check if udp mirrors was provisionned
if(mAutoDetecting) {
ms_error("TunnelManager: Cannot start auto detection. One auto detection is going on");
return;
}
if (mUdpMirrorClients.empty()) {
LOGE("No UDP mirror server configured aborting auto detection");
ms_error("TunnelManager: No UDP mirror server configured aborting auto detection");
return;
}
mCurrentUdpMirrorClient = mUdpMirrorClients.begin();
UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient;
lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this);
mAutoDetecting = true;
}
void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd) {
@ -386,15 +376,7 @@ void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd
}
void TunnelManager::tunnelizeSipPackets(bool enable){
if(enable != mTunnelizeSipPackets) {
mTunnelizeSipPackets = enable;
if(isConnected()) {
waitUnRegistration();
if(mTunnelizeSipPackets) sal_enable_tunnel(mCore->sal, mTunnelClient);
else sal_disable_tunnel(mCore->sal);
registration();
}
}
}
bool TunnelManager::tunnelizeSipPacketsEnabled() const {

View file

@ -167,37 +167,37 @@ namespace belledonnecomm {
private:
void onIterate();
void registration();
void waitUnRegistration();
void processTunnelEvent(const Event &ev);
void processUdpMirrorEvent(const Event &ev);
void postEvent(const Event &ev);
void doRegistration();
void startClient();
void stopClient();
void autoDetect();
void processTunnelEvent(const Event &ev);
void processUdpMirrorEvent(const Event &ev);
void postEvent(const Event &ev);
private:
LinphoneCore* mCore;
#ifndef USE_BELLESIP
TunnelSocket *mSipSocket;
eXosip_transport_hooks_t mExosipTransport;
#endif
LinphoneTunnelMode mMode;
std::queue<Event> mEvq;
std::list <ServerAddr> mServerAddrs;
UdpMirrorClientList mUdpMirrorClients;
UdpMirrorClientList::iterator mCurrentUdpMirrorClient;
bool mAutoDetecting;
bool mConnecting;
bool mScheduledRegistration;
bool mTunnelizeSipPackets;
TunnelClient* mTunnelClient;
Mutex mMutex;
bool mIsConnected;
LinphoneRtpTransportFactories mTransportFactories;
std::string mHttpUserName;
std::string mHttpPasswd;
std::string mHttpProxyHost;
int mHttpProxyPort;
bool mPreviousRegistrationEnabled;
bool mTunnelizeSipPackets;
LinphoneCoreVTable *mVTable;
std::list <ServerAddr> mServerAddrs;
UdpMirrorClientList mUdpMirrorClients;
UdpMirrorClientList::iterator mCurrentUdpMirrorClient;
LinphoneRtpTransportFactories mTransportFactories;
Mutex mMutex;
std::queue<Event> mEvq;
#ifndef USE_BELLESIP
TunnelSocket *mSipSocket;
eXosip_transport_hooks_t mExosipTransport;
#endif
};
/**

View file

@ -318,6 +318,8 @@ static void call_process_transaction_terminated(void *user_ctx, const belle_sip_
belle_sip_server_transaction_t *server_transaction=belle_sip_transaction_terminated_event_get_server_transaction(event);
belle_sip_request_t* req;
belle_sip_response_t* resp;
bool_t release_call=FALSE;
if (client_transaction) {
req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
resp=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(client_transaction));
@ -328,9 +330,21 @@ static void call_process_transaction_terminated(void *user_ctx, const belle_sip_
if (op->state ==SalOpStateTerminating
&& strcmp("BYE",belle_sip_request_get_method(req))==0
&& (!resp || (belle_sip_response_get_status_code(resp) !=401
&& belle_sip_response_get_status_code(resp) !=407))) {
if (op->dialog==NULL) call_set_released(op);
&& belle_sip_response_get_status_code(resp) !=407))
&& op->dialog==NULL) {
release_call=TRUE;
}
if (server_transaction){
if (op->pending_server_trans==server_transaction){
belle_sip_object_unref(op->pending_server_trans);
op->pending_server_trans=NULL;
}
if (op->pending_update_server_trans==server_transaction){
belle_sip_object_unref(op->pending_update_server_trans);
op->pending_update_server_trans=NULL;
}
}
if (release_call) call_set_released(op);
}
static void call_terminated(SalOp* op,belle_sip_server_transaction_t* server_transaction, belle_sip_request_t* request,int status_code) {
@ -777,6 +791,7 @@ int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*opti
belle_sip_response_t* response;
belle_sip_header_contact_t* contact=NULL;
int status=sal_reason_to_sip_code(reason);
belle_sip_transaction_t *trans;
if (reason==SalReasonRedirect){
if (redirection!=NULL) {
@ -788,9 +803,15 @@ int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*opti
ms_error("Cannot redirect to null");
}
}
response = sal_op_create_response_from_request(op,belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)),status);
trans=(belle_sip_transaction_t*)op->pending_server_trans;
if (!trans) trans=(belle_sip_transaction_t*)op->pending_update_server_trans;
if (!trans){
ms_error("sal_call_decline(): no pending transaction to decline.");
return -1;
}
response = sal_op_create_response_from_request(op,belle_sip_transaction_get_request(trans),status);
if (contact) belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact));
belle_sip_server_transaction_send_response(op->pending_server_trans,response);
belle_sip_server_transaction_send_response(BELLE_SIP_SERVER_TRANSACTION(trans),response);
return 0;
}

View file

@ -152,7 +152,7 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
ms_message("Network parameters have changed, update them.");
linphone_core_update_streams_destinations(lc, call, oldmd, new_md);
}
if (md_changed & SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED) {
if (md_changed & SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED) {
ms_message("Crypto parameters have changed, update them.");
linphone_call_update_crypto_parameters(call, oldmd, new_md);
}
@ -535,7 +535,7 @@ static void call_updated_by_remote(LinphoneCore *lc, LinphoneCall *call, bool_t
}
if (is_update && prev_result_desc && md){
int diff=sal_media_description_equals(prev_result_desc,md);
if (diff & (SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED|SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED)){
if (diff & (SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED|SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED)){
ms_warning("Cannot accept this update, it is changing parameters that require user approval");
sal_call_decline(call->op,SalReasonNotAcceptable,NULL); /*FIXME should send 504 Cannot change the session parameters without prompting the user"*/
return;
@ -655,7 +655,6 @@ static void call_terminated(SalOp *op, const char *from){
}
static int resume_call_after_failed_transfer(LinphoneCall *call){
ms_message("!!!!!!!!!!resume_call_after_failed_transfer");
if (call->was_automatically_paused && call->state==LinphoneCallPausing)
return BELLE_SIP_CONTINUE; /*was still in pausing state*/
@ -663,7 +662,7 @@ static int resume_call_after_failed_transfer(LinphoneCall *call){
if (sal_op_is_idle(call->op)){
linphone_core_resume_call(call->core,call);
}else {
ms_message("!!!!!!!!!!resume_call_after_failed_transfer, salop was busy");
ms_message("resume_call_after_failed_transfer(), salop was busy");
return BELLE_SIP_CONTINUE;
}
}

View file

@ -424,7 +424,7 @@ LinphoneChatRoom * linphone_core_get_chat_room_from_uri(LinphoneCore *lc, const
static void linphone_chat_room_delete_composing_idle_timer(LinphoneChatRoom *cr) {
if (cr->composing_idle_timer) {
if(cr->lc->sal)
if(cr-> lc && cr->lc->sal)
sal_cancel_timer(cr->lc->sal, cr->composing_idle_timer);
belle_sip_object_unref(cr->composing_idle_timer);
cr->composing_idle_timer = NULL;
@ -433,7 +433,7 @@ static void linphone_chat_room_delete_composing_idle_timer(LinphoneChatRoom *cr)
static void linphone_chat_room_delete_composing_refresh_timer(LinphoneChatRoom *cr) {
if (cr->composing_refresh_timer) {
if(cr->lc->sal)
if(cr->lc && cr->lc->sal)
sal_cancel_timer(cr->lc->sal, cr->composing_refresh_timer);
belle_sip_object_unref(cr->composing_refresh_timer);
cr->composing_refresh_timer = NULL;
@ -442,7 +442,7 @@ static void linphone_chat_room_delete_composing_refresh_timer(LinphoneChatRoom *
static void linphone_chat_room_delete_remote_composing_refresh_timer(LinphoneChatRoom *cr) {
if (cr->remote_composing_refresh_timer) {
if(cr->lc->sal)
if(cr->lc && cr->lc->sal)
sal_cancel_timer(cr->lc->sal, cr->remote_composing_refresh_timer);
belle_sip_object_unref(cr->remote_composing_refresh_timer);
cr->remote_composing_refresh_timer = NULL;

65
coreapi/fileplayer.c Normal file
View file

@ -0,0 +1,65 @@
#include "private.h"
#include <mediastreamer2/fileplayer.h>
#include <mediastreamer2/mssndcard.h>
static int file_player_open(LinphonePlayer *obj, const char *filename);
static int file_player_start(LinphonePlayer *obj);
static int file_player_pause(LinphonePlayer *obj);
static int file_player_seek(LinphonePlayer *obj, int time_ms);
static MSPlayerState file_player_get_state(LinphonePlayer *obj);
static void file_player_close(LinphonePlayer *obj);
static void file_player_eof_callback(void *user_data);
LinphonePlayer *linphone_core_create_file_player(LinphoneCore *lc, MSSndCard *snd_card, const char *video_out) {
LinphonePlayer *obj = ms_new0(LinphonePlayer, 1);
if(snd_card == NULL) snd_card = lc->sound_conf.play_sndcard;
if(video_out == NULL) video_out = linphone_core_get_video_display_filter(lc);
obj->impl = ms_file_player_new(snd_card, video_out);
obj->open = file_player_open;
obj->start = file_player_start;
obj->pause = file_player_pause;
obj->seek = file_player_seek;
obj->get_state = file_player_get_state;
obj->close = file_player_close;
ms_file_player_set_eof_callback((MSFilePlayer *)obj->impl, file_player_eof_callback, obj);
return obj;
}
void linphone_file_player_destroy(LinphonePlayer *obj) {
ms_file_player_free((MSFilePlayer *)obj->impl);
ms_free(obj);
}
bool_t linphone_file_player_matroska_supported(void) {
return ms_file_player_matroska_supported();
}
static int file_player_open(LinphonePlayer *obj, const char *filename) {
return ms_file_player_open((MSFilePlayer *)obj->impl, filename) ? 0 : -1;
}
static int file_player_start(LinphonePlayer *obj) {
return ms_file_player_start((MSFilePlayer *)obj->impl) ? 0 : -1;
}
static int file_player_pause(LinphonePlayer *obj) {
ms_file_player_pause((MSFilePlayer *)obj->impl);
return 0;
}
static int file_player_seek(LinphonePlayer *obj, int time_ms) {
return ms_file_player_seek((MSFilePlayer *)obj->impl, time_ms) ? 0 : -1;
}
static MSPlayerState file_player_get_state(LinphonePlayer *obj) {
return ms_file_player_get_state((MSFilePlayer *)obj->impl);
}
static void file_player_close(LinphonePlayer *obj) {
ms_file_player_close((MSFilePlayer *)obj->impl);
}
static void file_player_eof_callback(void *user_data) {
LinphonePlayer *obj = (LinphonePlayer *)user_data;
obj->cb(obj, obj->user_data);
}

View file

@ -31,9 +31,6 @@
static const char *_tunnel_mode_str[3] = { "disable", "enable", "auto" };
static LinphoneTunnelMode _string_to_tunnel_mode(const char *string);
static const char *_tunnel_mode_to_string(LinphoneTunnelMode mode);
LinphoneTunnel* linphone_core_get_tunnel(const LinphoneCore *lc){
return lc->tunnel;
}
@ -237,7 +234,7 @@ void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel){
}
void linphone_tunnel_set_mode(LinphoneTunnel *tunnel, LinphoneTunnelMode mode){
lp_config_set_string(config(tunnel),"tunnel","mode", _tunnel_mode_to_string(mode));
lp_config_set_string(config(tunnel),"tunnel","mode", tunnel_mode_to_string(mode));
bcTunnel(tunnel)->setMode(mode);
}
@ -335,7 +332,7 @@ static void my_ortp_logv(OrtpLogLevel level, const char *fmt, va_list args){
ortp_logv(level,fmt,args);
}
static LinphoneTunnelMode _string_to_tunnel_mode(const char *string) {
LinphoneTunnelMode string_to_tunnel_mode(const char *string) {
if(string != NULL) {
int i;
for(i=0; i<3 && strcmp(string, _tunnel_mode_str[i]) != 0; i++);
@ -350,7 +347,7 @@ static LinphoneTunnelMode _string_to_tunnel_mode(const char *string) {
}
}
static const char *_tunnel_mode_to_string(LinphoneTunnelMode mode) {
const char *tunnel_mode_to_string(LinphoneTunnelMode mode) {
return _tunnel_mode_str[mode];
}
@ -359,7 +356,7 @@ static const char *_tunnel_mode_to_string(LinphoneTunnelMode mode) {
* Called internally from linphonecore at startup.
*/
void linphone_tunnel_configure(LinphoneTunnel *tunnel){
LinphoneTunnelMode mode = _string_to_tunnel_mode(lp_config_get_string(config(tunnel), "tunnel", "mode", NULL));
LinphoneTunnelMode mode = string_to_tunnel_mode(lp_config_get_string(config(tunnel), "tunnel", "mode", NULL));
bool_t tunnelizeSIPPackets = (bool_t)lp_config_get_int(config(tunnel), "tunnel", "sip", TRUE);
linphone_tunnel_enable_logs_with_handler(tunnel,TRUE,my_ortp_logv);
linphone_tunnel_load_config(tunnel);

View file

@ -50,12 +50,30 @@ extern "C"
typedef struct _LinphoneTunnelConfig LinphoneTunnelConfig;
/**
* Enum describing the tunnel modes.
**/
typedef enum _LinphoneTunnelMode {
LinphoneTunnelModeDisable,
LinphoneTunnelModeEnable,
LinphoneTunnelModeAuto
LinphoneTunnelModeDisable, /**< The tunnel is disabled. */
LinphoneTunnelModeEnable, /**< The tunnel is enabled. */
LinphoneTunnelModeAuto /**< The tunnel is enabled automatically if it is required. */
} LinphoneTunnelMode;
/**
* @brief Convert a string into LinphoneTunnelMode enum
* @param string String to convert
* @return An LinphoneTunnelMode enum. If the passed string is NULL or
* does not match with any mode, the LinphoneTunnelModeDisable is returned.
*/
LINPHONE_PUBLIC LinphoneTunnelMode string_to_tunnel_mode(const char *string);
/**
* @brief Convert a tunnel mode enum into string
* @param mode Enum to convert
* @return "disable", "enable" or "auto"
*/
LINPHONE_PUBLIC const char *tunnel_mode_to_string(LinphoneTunnelMode mode);
/**
* Create a new tunnel configuration
*/
@ -268,7 +286,6 @@ LINPHONE_PUBLIC void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel);
*/
LINPHONE_PUBLIC bool_t linphone_tunnel_auto_detect_enabled(LinphoneTunnel *tunnel);
/**
* @}
**/

View file

@ -1662,6 +1662,19 @@ static void parametrize_equalizer(LinphoneCore *lc, AudioStream *st){
}
}
void set_mic_gain_db(AudioStream *st, float gain){
if (st->volsend){
ms_filter_call_method(st->volsend,MS_VOLUME_SET_DB_GAIN,&gain);
}else ms_warning("Could not apply mic gain: gain control wasn't activated.");
}
void set_playback_gain_db(AudioStream *st, float gain){
if (st->volrecv){
ms_filter_call_method(st->volrecv,MS_VOLUME_SET_DB_GAIN,&gain);
}else ms_warning("Could not apply playback gain: gain control wasn't activated.");
}
/*This function is not static because used internally in linphone-daemon project*/
void _post_configure_audio_stream(AudioStream *st, LinphoneCore *lc, bool_t muted){
float mic_gain=lc->sound_conf.soft_mic_lev;
float thres = 0;
@ -1678,13 +1691,13 @@ void _post_configure_audio_stream(AudioStream *st, LinphoneCore *lc, bool_t mute
int spk_agc;
if (!muted)
linphone_core_set_mic_gain_db (lc, mic_gain);
set_mic_gain_db(st,mic_gain);
else
audio_stream_set_mic_gain(st,0);
recv_gain = lc->sound_conf.soft_play_lev;
if (recv_gain != 0) {
linphone_core_set_playback_gain_db (lc,recv_gain);
set_playback_gain_db(st,recv_gain);
}
if (st->volsend){
@ -1720,10 +1733,10 @@ void _post_configure_audio_stream(AudioStream *st, LinphoneCore *lc, bool_t mute
parametrize_equalizer(lc,st);
}
static void post_configure_audio_streams(LinphoneCall*call){
static void post_configure_audio_streams(LinphoneCall *call, bool_t muted){
AudioStream *st=call->audiostream;
LinphoneCore *lc=call->core;
_post_configure_audio_stream(st,lc,call->audio_muted);
_post_configure_audio_stream(st,lc,muted);
if (linphone_core_dtmf_received_has_listener(lc)){
audio_stream_play_received_dtmfs(call->audiostream,FALSE);
}
@ -1996,10 +2009,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
captcard,
use_ec
);
post_configure_audio_streams(call);
if (muted && !send_ringbacktone){
audio_stream_set_mic_gain(call->audiostream,0);
}
post_configure_audio_streams(call, muted && !send_ringbacktone);
if (stream->dir==SalStreamSendOnly && playfile!=NULL){
int pause_time=500;
ms_filter_call_method(call->audiostream->soundread,MS_FILE_PLAYER_LOOP,&pause_time);
@ -2220,7 +2230,7 @@ void linphone_call_stop_media_streams_for_ice_gathering(LinphoneCall *call){
static bool_t update_stream_crypto_params(LinphoneCall *call, const SalStreamDescription *local_st_desc, SalStreamDescription *old_stream, SalStreamDescription *new_stream, MediaStream *ms){
int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, new_stream->crypto_local_tag);
if (crypto_idx >= 0) {
if (call->localdesc_changed & SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED)
if (call->localdesc_changed & SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED)
media_stream_set_srtp_send_key(ms,new_stream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key);
if (strcmp(old_stream->crypto[0].master_key,new_stream->crypto[0].master_key)!=0){
media_stream_set_srtp_recv_key(ms,new_stream->crypto[0].algo,new_stream->crypto[0].master_key);
@ -2634,10 +2644,10 @@ uint64_t linphone_call_stats_get_late_packets_cumulative_number(const LinphoneCa
if (!stats || !call)
return 0;
memset(&rtp_stats, 0, sizeof(rtp_stats));
if (stats->type == LINPHONE_CALL_STATS_AUDIO)
if (stats->type == LINPHONE_CALL_STATS_AUDIO && call->audiostream != NULL)
audio_stream_get_local_rtp_stats(call->audiostream, &rtp_stats);
#ifdef VIDEO_ENABLED
else
else if (call->videostream != NULL)
video_stream_get_local_rtp_stats(call->videostream, &rtp_stats);
#endif
return rtp_stats.outoftime;

View file

@ -1630,8 +1630,7 @@ void linphone_core_set_use_rfc2833_for_dtmf(LinphoneCore *lc,bool_t use_rfc2833)
* Deprecated: use linphone_core_get_sip_transports() instead.
* @ingroup network_parameters
**/
int linphone_core_get_sip_port(LinphoneCore *lc)
{
int linphone_core_get_sip_port(LinphoneCore *lc){
LCSipTransports tr;
linphone_core_get_sip_transports_used(lc,&tr);
return tr.udp_port>0 ? tr.udp_port : (tr.tcp_port > 0 ? tr.tcp_port : tr.tls_port);
@ -2857,6 +2856,7 @@ int linphone_core_accept_early_media(LinphoneCore* lc, LinphoneCall* call){
int linphone_core_start_update_call(LinphoneCore *lc, LinphoneCall *call){
const char *subject;
int err;
bool_t no_user_consent=call->params->no_user_consent;
if (!no_user_consent) linphone_call_make_local_media_description(lc,call);
@ -2873,12 +2873,22 @@ int linphone_core_start_update_call(LinphoneCore *lc, LinphoneCall *call){
subject="Refreshing";
}
linphone_core_notify_display_status(lc,_("Modifying call parameters..."));
sal_call_set_local_media_description (call->op,call->localdesc);
if (!lc->sip_conf.sdp_200_ack){
sal_call_set_local_media_description (call->op,call->localdesc);
} else {
sal_call_set_local_media_description (call->op,NULL);
}
if (call->dest_proxy && call->dest_proxy->op){
/*give a chance to update the contact address if connectivity has changed*/
sal_op_set_contact_address(call->op,sal_op_get_contact_address(call->dest_proxy->op));
}else sal_op_set_contact_address(call->op,NULL);
return sal_call_update(call->op,subject,no_user_consent);
err= sal_call_update(call->op,subject,no_user_consent);
if (lc->sip_conf.sdp_200_ack){
/*we are NOT offering, set local media description after sending the call so that we are ready to
process the remote offer when it will arrive*/
sal_call_set_local_media_description(call->op,call->localdesc);
}
return err;
}
/**
@ -3789,9 +3799,7 @@ void linphone_core_set_mic_gain_db (LinphoneCore *lc, float gaindb){
ms_message("linphone_core_set_mic_gain_db(): no active call.");
return;
}
if (st->volsend){
ms_filter_call_method(st->volsend,MS_VOLUME_SET_DB_GAIN,&gain);
}else ms_warning("Could not apply gain: gain control wasn't activated.");
set_mic_gain_db(st,gain);
}
/**
@ -3822,9 +3830,7 @@ void linphone_core_set_playback_gain_db (LinphoneCore *lc, float gaindb){
ms_message("linphone_core_set_playback_gain_db(): no active call.");
return;
}
if (st->volrecv){
ms_filter_call_method(st->volrecv,MS_VOLUME_SET_DB_GAIN,&gain);
}else ms_warning("Could not apply gain: gain control wasn't activated.");
set_playback_gain_db(st,gain);
}
/**
@ -4467,11 +4473,11 @@ void linphone_core_set_firewall_policy(LinphoneCore *lc, LinphoneFirewallPolicy
lp_config_set_string(lc->config,"net","firewall_policy",policy);
}
inline LinphoneFirewallPolicy linphone_core_get_firewall_policy(const LinphoneCore *lc) {
ORTP_INLINE LinphoneFirewallPolicy linphone_core_get_firewall_policy(const LinphoneCore *lc) {
return _linphone_core_get_firewall_policy_with_lie(lc, FALSE);
}
inline LinphoneFirewallPolicy _linphone_core_get_firewall_policy(const LinphoneCore *lc) {
ORTP_INLINE LinphoneFirewallPolicy _linphone_core_get_firewall_policy(const LinphoneCore *lc) {
return _linphone_core_get_firewall_policy_with_lie(lc, TRUE);
}
@ -5003,15 +5009,15 @@ int linphone_core_get_camera_sensor_rotation(LinphoneCore *lc) {
}
static MSVideoSizeDef supported_resolutions[]={
#if !ANDROID & !TARGET_OS_IPHONE
#if !ANDROID && !TARGET_OS_IPHONE
{ { MS_VIDEO_SIZE_1080P_W, MS_VIDEO_SIZE_1080P_H } , "1080p" },
#endif
#if !ANDROID & !TARGET_OS_MAC /*limite to most common size because mac card cannot list supported resolutions*/
#if !ANDROID && !TARGET_OS_MAC /*limit to most common sizes because mac video API cannot list supported resolutions*/
{ { MS_VIDEO_SIZE_UXGA_W, MS_VIDEO_SIZE_UXGA_H } , "uxga" },
{ { MS_VIDEO_SIZE_SXGA_MINUS_W, MS_VIDEO_SIZE_SXGA_MINUS_H } , "sxga-" },
#endif
{ { MS_VIDEO_SIZE_720P_W, MS_VIDEO_SIZE_720P_H } , "720p" },
#if !ANDROID & !TARGET_OS_MAC
#if !ANDROID && !TARGET_OS_MAC
{ { MS_VIDEO_SIZE_XGA_W, MS_VIDEO_SIZE_XGA_H } , "xga" },
#endif
#if !ANDROID && !TARGET_OS_IPHONE
@ -5043,23 +5049,33 @@ const MSVideoSizeDef *linphone_core_get_supported_video_sizes(LinphoneCore *lc){
static MSVideoSize video_size_get_by_name(const char *name){
MSVideoSizeDef *pdef=supported_resolutions;
MSVideoSize null_vsize={0,0};
MSVideoSize parsed;
if (!name) return null_vsize;
for(;pdef->name!=NULL;pdef++){
if (strcasecmp(name,pdef->name)==0){
return pdef->vsize;
}
}
if (sscanf(name,"%ix%i",&parsed.width,&parsed.height)==2){
return parsed;
}
ms_warning("Video resolution %s is not supported in linphone.",name);
return null_vsize;
}
/* warning: function not reentrant*/
static const char *video_size_get_name(MSVideoSize vsize){
MSVideoSizeDef *pdef=supported_resolutions;
static char customsize[64]={0};
for(;pdef->name!=NULL;pdef++){
if (pdef->vsize.width==vsize.width && pdef->vsize.height==vsize.height){
return pdef->name;
}
}
if (vsize.width && vsize.height){
snprintf(customsize,sizeof(customsize)-1,"%ix%i",vsize.width,vsize.height);
return customsize;
}
return NULL;
}
@ -5108,6 +5124,7 @@ void linphone_core_set_preferred_video_size(LinphoneCore *lc, MSVideoSize vsize)
* @param vsize the video resolution choosed for capuring and previewing. It can be (0,0) to not request any specific preview size and let the core optimize the processing.
**/
void linphone_core_set_preview_video_size(LinphoneCore *lc, MSVideoSize vsize){
MSVideoSize oldvsize;
if (vsize.width==0 && vsize.height==0){
/*special case to reset the forced preview size mode*/
lc->video_conf.preview_vsize=vsize;
@ -5115,16 +5132,25 @@ void linphone_core_set_preview_video_size(LinphoneCore *lc, MSVideoSize vsize){
lp_config_set_string(lc->config,"video","preview_size",NULL);
return;
}
if (video_size_supported(vsize)){
MSVideoSize oldvsize=lc->video_conf.preview_vsize;
lc->video_conf.preview_vsize=vsize;
if (!ms_video_size_equal(oldvsize,vsize) && lc->previewstream!=NULL){
toggle_video_preview(lc,FALSE);
toggle_video_preview(lc,TRUE);
}
if (linphone_core_ready(lc))
lp_config_set_string(lc->config,"video","preview_size",video_size_get_name(vsize));
oldvsize=lc->video_conf.preview_vsize;
lc->video_conf.preview_vsize=vsize;
if (!ms_video_size_equal(oldvsize,vsize) && lc->previewstream!=NULL){
toggle_video_preview(lc,FALSE);
toggle_video_preview(lc,TRUE);
}
if (linphone_core_ready(lc))
lp_config_set_string(lc->config,"video","preview_size",video_size_get_name(vsize));
}
/**
* Returns video size for the captured video if it was previously set by linphone_core_set_preview_video_size(), otherwise returns a 0,0 size.
* @see linphone_core_set_preview_video_size()
* @ingroup media_parameters
* @param lc the core
* @return a MSVideoSize
**/
MSVideoSize linphone_core_get_preview_video_size(const LinphoneCore *lc){
return lc->video_conf.preview_vsize;
}
/**

View file

@ -596,6 +596,28 @@ int linphone_player_seek(LinphonePlayer *obj, int time_ms);
MSPlayerState linphone_player_get_state(LinphonePlayer *obj);
void linphone_player_close(LinphonePlayer *obj);
/**
* @brief Create an independent media file player.
* This player support WAVE and MATROSKA formats.
* @param lc A LinphoneCore
* @param snd_card Playback sound card. If NULL, the sound card set in LinphoneCore will be used
* @param video_out Video display. If NULL, the video display set in LinphoneCore will be used
* @return A pointer on the new instance. NULL if faild.
*/
LINPHONE_PUBLIC LinphonePlayer *linphone_core_create_file_player(LinphoneCore *lc, MSSndCard *snd_card, const char *video_out);
/**
* @brief Destroy a file player
* @param obj File player to destroy
*/
LINPHONE_PUBLIC void linphone_file_player_destroy(LinphonePlayer *obj);
/**
* @brief Check whether Matroksa format is supported by the player
* @return TRUE if it is supported
*/
LINPHONE_PUBLIC bool_t linphone_file_player_matroska_supported(void);
/**
* LinphoneCallState enum represents the different state a call can reach into.
* The application is notified of state changes through the LinphoneCoreVTable::call_state_changed callback.
@ -2536,6 +2558,7 @@ LINPHONE_PUBLIC const MSVideoSizeDef *linphone_core_get_supported_video_sizes(Li
LINPHONE_PUBLIC void linphone_core_set_preferred_video_size(LinphoneCore *lc, MSVideoSize vsize);
LINPHONE_PUBLIC void linphone_core_set_preview_video_size(LinphoneCore *lc, MSVideoSize vsize);
LINPHONE_PUBLIC void linphone_core_set_preview_video_size_by_name(LinphoneCore *lc, const char *name);
LINPHONE_PUBLIC MSVideoSize linphone_core_get_preview_video_size(const LinphoneCore *lc);
LINPHONE_PUBLIC MSVideoSize linphone_core_get_preferred_video_size(LinphoneCore *lc);
LINPHONE_PUBLIC void linphone_core_set_preferred_video_size_by_name(LinphoneCore *lc, const char *name);
LINPHONE_PUBLIC void linphone_core_set_preferred_framerate(LinphoneCore *lc, float fps);

View file

@ -40,7 +40,11 @@
#endif /*_WIN32_WCE*/
#ifdef _MSC_VER
#ifdef WINAPI_FAMILY_PHONE_APP
#include <stdlib.h>
#else
#include <Shlwapi.h>
#endif
#else
#include <libgen.h>
#endif
@ -666,9 +670,18 @@ const char* lp_config_get_default_string(const LpConfig *lpconfig, const char *s
static char *_lp_config_dirname(char *path) {
#ifdef _MSC_VER
#ifdef WINAPI_FAMILY_PHONE_APP
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
_splitpath(path, drive, dir, fname, ext);
return ms_strdup_printf("%s%s", drive, dir);
#else
char *dir = ms_strdup(path);
PathRemoveFileSpec(dir);
return dir;
#endif
#else
char *tmp = ms_strdup(path);
char *dir = ms_strdup(dirname(tmp));

View file

@ -937,7 +937,7 @@ void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call,
bool_t linphone_core_media_description_contains_video_stream(const SalMediaDescription *md){
int i;
for (i = 0; i < md->nb_streams; i++) {
for (i = 0; md && i < md->nb_streams; i++) {
if (md->streams[i].type == SalVideo && md->streams[i].rtp_port!=0)
return TRUE;
}

View file

@ -31,7 +31,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
int linphone_player_open(LinphonePlayer *obj, const char *filename, LinphonePlayerEofCallback cb, void *user_data){
obj->user_data=user_data;
obj->cb=cb;
return obj->open(obj->impl,filename);
return obj->open(obj,filename);
}
/**
@ -40,7 +40,7 @@ int linphone_player_open(LinphonePlayer *obj, const char *filename, LinphonePlay
* @return 0 if successful, -1 otherwise
**/
int linphone_player_start(LinphonePlayer *obj){
return obj->start(obj->impl);
return obj->start(obj);
}
/**
@ -49,7 +49,7 @@ int linphone_player_start(LinphonePlayer *obj){
* @return 0 if successful, -1 otherwise
**/
int linphone_player_pause(LinphonePlayer *obj){
return obj->pause(obj->impl);
return obj->pause(obj);
}
/**
@ -59,7 +59,7 @@ int linphone_player_pause(LinphonePlayer *obj){
* @return 0 if successful, -1 otherwise
**/
int linphone_player_seek(LinphonePlayer *obj, int time_ms){
return obj->seek(obj->impl,time_ms);
return obj->seek(obj,time_ms);
}
/**
@ -68,7 +68,7 @@ int linphone_player_seek(LinphonePlayer *obj, int time_ms){
* @return the state of the player within MSPlayerClosed, MSPlayerStarted, MSPlayerPaused.
**/
MSPlayerState linphone_player_get_state(LinphonePlayer *obj){
return obj->get_state(obj->impl);
return obj->get_state(obj);
}
/**
@ -76,7 +76,7 @@ MSPlayerState linphone_player_get_state(LinphonePlayer *obj){
* @param obj the player.
**/
void linphone_player_close(LinphonePlayer *obj){
return obj->close(obj->impl);
return obj->close(obj);
}
@ -104,7 +104,7 @@ static bool_t call_player_check_state(LinphonePlayer *player, bool_t check_playe
static void on_eof(void *user_data, MSFilter *f, unsigned int event_id, void *arg){
LinphonePlayer *player=(LinphonePlayer *)user_data;
if (player->cb) player->cb(player,user_data);
if (player->cb) player->cb(player,player->user_data);
}
static int call_player_open(LinphonePlayer* player, const char *filename){
@ -146,7 +146,7 @@ static int call_player_seek(LinphonePlayer *player, int time_ms){
static void call_player_close(LinphonePlayer *player){
LinphoneCall *call=(LinphoneCall*)player->impl;
if (!call_player_check_state(player,TRUE)) return;
ms_filter_call_method_noarg(call->audiostream->av_player.player,MS_PLAYER_CLOSE);
audio_stream_close_remote_play(call->audiostream);
}

View file

@ -1021,7 +1021,8 @@ void linphone_core_notify_notify_received(LinphoneCore *lc, LinphoneEvent *lev,
void linphone_core_notify_subscription_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state);
void linphone_core_notify_publish_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphonePublishState state);
void set_mic_gain_db(AudioStream *st, float gain);
void set_playback_gain_db(AudioStream *st, float gain);
#ifdef __cplusplus
}

View file

@ -1408,12 +1408,7 @@ static bool_t can_register(LinphoneProxyConfig *cfg){
}
#endif //BUILD_UPNP
if (lc->sip_conf.register_only_when_network_is_up){
LinphoneTunnel *tunnel=linphone_core_get_tunnel(lc);
if (tunnel && linphone_tunnel_get_mode(tunnel)){
return linphone_tunnel_connected(tunnel);
}else{
return lc->network_reachable;
}
return lc->network_reachable;
}
return TRUE;
}

View file

@ -280,9 +280,11 @@ int sal_stream_description_equals(const SalStreamDescription *sd1, const SalStre
if (sd1->proto != sd2->proto) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
for (i = 0; i < SAL_CRYPTO_ALGO_MAX; i++) {
if ((sd1->crypto[i].tag != sd2->crypto[i].tag)
|| (sd1->crypto[i].algo != sd2->crypto[i].algo)
|| (strncmp(sd1->crypto[i].master_key, sd2->crypto[i].master_key, sizeof(sd1->crypto[i].master_key) - 1))) {
result |= SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED;
|| (sd1->crypto[i].algo != sd2->crypto[i].algo)){
result|=SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED;
}
if ((strncmp(sd1->crypto[i].master_key, sd2->crypto[i].master_key, sizeof(sd1->crypto[i].master_key) - 1))) {
result |= SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED;
}
}

View file

@ -54,6 +54,7 @@ linphone_SOURCES= \
conference.c \
config-fetching.c \
audio_assistant.c \
videowindow.c \
linphone.h
if BUILD_WIZARD
linphone_SOURCES+= \

View file

@ -403,7 +403,7 @@ void linphone_gtk_create_in_call_view(LinphoneCall *call){
gtk_widget_hide(conf);
button=linphone_gtk_get_widget(call_view,"terminate_call");
image=create_pixmap("stopcall-small.png");
image=create_pixmap (linphone_gtk_get_ui_config("stop_call_icon","stopcall-small.png"));
gtk_button_set_label(GTK_BUTTON(button),_("Hang up"));
gtk_button_set_image(GTK_BUTTON(button),image);
gtk_widget_show(image);
@ -687,6 +687,14 @@ void linphone_gtk_in_call_view_show_encryption(LinphoneCall *call){
}
}
char *linphone_gtk_address(const LinphoneAddress *addr){
const char *displayname=linphone_address_get_display_name(addr);
if (!displayname) return linphone_address_as_string_uri_only(addr);
return ms_strdup(displayname);
}
void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call){
GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
GtkWidget *status=linphone_gtk_get_widget(callview,"in_call_status");
@ -696,6 +704,8 @@ void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call){
gboolean in_conf=linphone_call_params_get_local_conference_mode(linphone_call_get_current_params(call));
GtkWidget *call_stats=(GtkWidget*)g_object_get_data(G_OBJECT(callview),"call_stats");
linphone_gtk_in_call_show_video(call);
display_peer_name_in_label(callee,linphone_call_get_remote_address (call));
gtk_widget_hide(linphone_gtk_get_widget(callview,"answer_decline_panel"));
@ -736,7 +746,7 @@ void linphone_gtk_in_call_view_set_paused(LinphoneCall *call){
GtkWidget *status=linphone_gtk_get_widget(callview,"in_call_status");
gtk_widget_hide(linphone_gtk_get_widget(callview,"answer_decline_panel"));
gtk_label_set_markup(GTK_LABEL(status),_("<b>Paused call</b>"));
linphone_gtk_in_call_show_video(call);
linphone_gtk_in_call_set_animation_image(callview,GTK_STOCK_MEDIA_PAUSE,TRUE);
}
@ -760,13 +770,15 @@ static gboolean in_call_view_terminated(LinphoneCall *call){
void linphone_gtk_in_call_view_terminate(LinphoneCall *call, const char *error_msg){
GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
GtkWidget *status;
GtkWidget *video_window;
gboolean in_conf;
guint taskid;
if(callview==NULL) return;
video_window=(GtkWidget*)g_object_get_data(G_OBJECT(callview),"video_window");
status=linphone_gtk_get_widget(callview,"in_call_status");
taskid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(callview),"taskid"));
in_conf=linphone_call_params_get_local_conference_mode(linphone_call_get_current_params(call));
if (video_window) gtk_widget_destroy(video_window);
if (status==NULL) return;
if (error_msg==NULL)
gtk_label_set_markup(GTK_LABEL(status),_("<b>Call ended.</b>"));

View file

@ -48,6 +48,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define LINPHONE_VERSION LINPHONE_VERSION_DATE
#endif
#define LINPHONE_ICON "linphone.png"
enum {
COMPLETION_HISTORY,
COMPLETION_LDAP
@ -195,4 +197,6 @@ void linphone_gtk_set_configuration_uri(void);
GtkWidget * linphone_gtk_show_config_fetching(void);
void linphone_gtk_close_config_fetching(GtkWidget *w, LinphoneConfiguringState state);
const char *linphone_gtk_get_sound_path(const char *file);
void linphone_gtk_in_call_show_video(LinphoneCall *call);
char *linphone_gtk_address(const LinphoneAddress *addr);/*return human readable identifier for a LinphoneAddress */

View file

@ -48,7 +48,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifdef ENABLE_NLS
#include <locale.h>
#endif
#define LINPHONE_ICON "linphone.png"
const char *this_program_ident_string="linphone_ident_string=" LINPHONE_VERSION;
@ -318,6 +318,7 @@ static void linphone_gtk_init_liblinphone(const char *config_file,
g_free(secrets_file);
linphone_core_enable_video_capture(the_core, TRUE);
linphone_core_enable_video_display(the_core, TRUE);
linphone_core_set_native_video_window_id(the_core,-1);/*don't create the window*/
if (no_video) {
_linphone_gtk_enable_video(FALSE);
linphone_gtk_set_ui_config_int("videoselfview",0);
@ -566,102 +567,6 @@ void linphone_gtk_show_about(){
gtk_widget_show(about);
}
static void set_video_window_decorations(GdkWindow *w){
const char *title=linphone_gtk_get_ui_config("title","Linphone");
const char *icon_path=linphone_gtk_get_ui_config("icon",LINPHONE_ICON);
char video_title[256];
GdkPixbuf *pbuf=create_pixbuf(icon_path);
if (!linphone_core_in_call(linphone_gtk_get_core())){
snprintf(video_title,sizeof(video_title),"%s video",title);
/* When not in call, treat the video as a normal window */
gdk_window_set_keep_above(w, FALSE);
}else{
LinphoneAddress *uri =
linphone_address_clone(linphone_core_get_current_call_remote_address(linphone_gtk_get_core()));
char *display_name;
linphone_address_clean(uri);
if (linphone_address_get_display_name(uri)!=NULL){
display_name=ms_strdup(linphone_address_get_display_name(uri));
}else{
display_name=linphone_address_as_string(uri);
}
snprintf(video_title,sizeof(video_title),_("Call with %s"),display_name);
linphone_address_destroy(uri);
ms_free(display_name);
/* During calls, bring up the video window, arrange so that
it is above all the other windows */
gdk_window_deiconify(w);
gdk_window_set_keep_above(w,TRUE);
/* Maybe we should have the following, but then we want to
have a timer that turns it off after a little while. */
/* gdk_window_set_urgency_hint(w,TRUE); */
}
gdk_window_set_title(w,video_title);
/* Refrain the video window to be closed at all times. */
gdk_window_set_functions(w,
GDK_FUNC_RESIZE|GDK_FUNC_MOVE|
GDK_FUNC_MINIMIZE|GDK_FUNC_MAXIMIZE);
if (pbuf){
GList *l=NULL;
l=g_list_append(l,pbuf);
gdk_window_set_icon_list(w,l);
g_list_free(l);
g_object_unref(G_OBJECT(pbuf));
}
}
static gboolean video_needs_update=FALSE;
static void update_video_title(){
video_needs_update=TRUE;
}
static void update_video_titles(LinphoneCore *lc){
unsigned long id;
static unsigned long previd=0;
static unsigned long preview_previd=0;
id=linphone_core_get_native_video_window_id(lc);
if (id!=previd || video_needs_update){
GdkWindow *w;
previd=id;
if (id!=0){
ms_message("Updating window decorations");
#ifndef WIN32
w=gdk_window_foreign_new((GdkNativeWindow)id);
#else
w=gdk_window_foreign_new((HANDLE)id);
#endif
if (w) {
set_video_window_decorations(w);
g_object_unref(G_OBJECT(w));
}
else ms_error("gdk_window_foreign_new() failed");
if (video_needs_update) video_needs_update=FALSE;
}
}
id=linphone_core_get_native_preview_window_id (lc);
if (id!=preview_previd ){
GdkWindow *w;
preview_previd=id;
if (id!=0){
ms_message("Updating window decorations for preview");
#ifndef WIN32
w=gdk_window_foreign_new((GdkNativeWindow)id);
#else
w=gdk_window_foreign_new((HANDLE)id);
#endif
if (w) {
set_video_window_decorations(w);
g_object_unref(G_OBJECT(w));
}
else ms_error("gdk_window_foreign_new() failed");
if (video_needs_update) video_needs_update=FALSE;
}
}
}
static gboolean linphone_gtk_iterate(LinphoneCore *lc){
static gboolean first_time=TRUE;
@ -677,7 +582,6 @@ static gboolean linphone_gtk_iterate(LinphoneCore *lc){
first_time=FALSE;
}
update_video_titles(lc);
if (addr_to_call!=NULL){
/*make sure we are not showing the login screen*/
GtkWidget *mw=linphone_gtk_get_main_window();
@ -928,7 +832,6 @@ void linphone_gtk_call_terminated(LinphoneCall *call, const char *error){
}
if (linphone_gtk_use_in_call_view() && call)
linphone_gtk_in_call_view_terminate(call,error);
update_video_title();
}
static void linphone_gtk_update_call_buttons(LinphoneCall *call){
@ -971,7 +874,6 @@ static void linphone_gtk_update_call_buttons(LinphoneCall *call){
linphone_gtk_enable_transfer_button(lc,FALSE);
linphone_gtk_enable_conference_button(lc,FALSE);
}
update_video_title();
if (call) {
linphone_gtk_update_video_button(call);
}

310
gtk/videowindow.c Normal file
View file

@ -0,0 +1,310 @@
/*
linphone, gtk interface.
Copyright (C) 2014 Belledonne Communications SARL
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.
*/
#include "linphone.h"
#ifdef __linux
#include <gdk/gdkx.h>
#elif defined(WIN32)
#include <gdk/gdkwin32.h>
#elif defined(__APPLE__)
extern void *gdk_quartz_window_get_nswindow(GdkWindow *window);
extern void *gdk_quartz_window_get_nsview(GdkWindow *window);
#endif
#include <gdk/gdkkeysyms.h>
enum {
TARGET_STRING,
TARGET_TEXT,
TARGET_URILIST
};
static GtkTargetEntry targets[] = {
{ "text/uri-list", GTK_TARGET_OTHER_APP, TARGET_URILIST },
};
static void set_video_controls_position(GtkWidget *video_window);
static void on_end_of_play(LinphonePlayer *player, void *user_data){
linphone_player_close(player);
}
static void drag_data_received(GtkWidget *widget, GdkDragContext *context, gint x, gint y,
GtkSelectionData *selection_data, guint target_type, guint time, gpointer user_data){
int datalen=gtk_selection_data_get_length(selection_data) >= 0;
const void *data=gtk_selection_data_get_data(selection_data);
LinphoneCall *call=g_object_get_data(G_OBJECT(widget),"call");
ms_message("target_type=%i, datalen=%i, data=%p",target_type,datalen,data);
if (target_type==TARGET_URILIST && data){
LinphonePlayer *player=linphone_call_get_player(call);
const char *path=(const char*)data;
if (player){
if (strstr(path,"file://")==path) path+=strlen("file://");
if (linphone_player_open(player,path,on_end_of_play,NULL)==0){
linphone_player_start(player);
}else{
GtkWidget *warn=gtk_message_dialog_new(GTK_WINDOW(widget),GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,GTK_BUTTONS_CLOSE,
_("Cannot play %s."),path);
g_signal_connect(warn,"response",(GCallback)gtk_widget_destroy,NULL);
gtk_widget_show(warn);
}
}
}
gtk_drag_finish (context, TRUE, FALSE, time);
}
static gboolean drag_drop(GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, guint time, gpointer user_data){
#if GTK_CHECK_VERSION(2,20,0)
GList *l=gdk_drag_context_list_targets(drag_context);
GList *elem;
if (l){
ms_message("drag_drop");
/* Choose the best target type */
for(elem=l;elem!=NULL;elem=g_list_next(elem)){
char *name=gdk_atom_name(GDK_POINTER_TO_ATOM(elem->data));
ms_message("target: %s",name);
g_free(name);
}
}else{
ms_warning("drag_drop no targets");
return FALSE;
}
#endif
return TRUE;
}
unsigned long get_native_handle(GdkWindow *gdkw){
#ifdef __linux
return (unsigned long)GDK_WINDOW_XID(gdkw);
#elif defined(WIN32)
return (unsigned long)GDK_WINDOW_HWND(gdkw);
#elif defined(__APPLE__)
return (unsigned long)gdk_quartz_window_get_nsview(gdkw);
#endif
g_warning("No way to get the native handle from gdk window");
return 0;
}
static gint resize_video_window(LinphoneCall *call){
const LinphoneCallParams *params=linphone_call_get_current_params(call);
if (params){
MSVideoSize vsize=linphone_call_params_get_received_video_size(params);
if (vsize.width>0 && vsize.height>0){
GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
GtkWidget *video_window=(GtkWidget*)g_object_get_data(G_OBJECT(callview),"video_window");
if (video_window){
MSVideoSize cur;
gtk_window_get_size(GTK_WINDOW(video_window),&cur.width,&cur.height);
if (vsize.width*vsize.height > cur.width*cur.height ||
ms_video_size_get_orientation(vsize)!=ms_video_size_get_orientation(cur) ){
g_message("Resized to %ix%i",vsize.width,vsize.height);
gtk_window_resize(GTK_WINDOW(video_window),vsize.width,vsize.height);
}
}
}
}
return TRUE;
}
static void on_video_window_destroy(GtkWidget *w, guint timeout){
g_source_remove(timeout);
linphone_core_set_native_video_window_id(linphone_gtk_get_core(),(unsigned long)-1);
}
static void video_window_set_fullscreen(GtkWidget *w, gboolean val){
if (val){
g_object_set_data(G_OBJECT(w),"fullscreen",GINT_TO_POINTER(1));
gtk_window_fullscreen(GTK_WINDOW(w));
}else{
g_object_set_data(G_OBJECT(w),"fullscreen",GINT_TO_POINTER(0));
gtk_window_unfullscreen(GTK_WINDOW(w));
}
}
/*old names in old version of gdk*/
#ifndef GDK_KEY_Escape
#define GDK_KEY_Escape GDK_Escape
#define GDK_KEY_F GDK_F
#define GDK_KEY_f GDK_f
#endif
static void on_video_window_key_press(GtkWidget *w, GdkEvent *ev, gpointer up){
g_message("Key press event");
switch(ev->key.keyval){
case GDK_KEY_f:
case GDK_KEY_F:
video_window_set_fullscreen(w,TRUE);
break;
case GDK_KEY_Escape:
video_window_set_fullscreen(w,FALSE);
break;
}
}
static void on_controls_response(GtkWidget *dialog, int response_id, GtkWidget *video_window){
gtk_widget_destroy(dialog);
switch(response_id){
case GTK_RESPONSE_YES:
video_window_set_fullscreen(video_window,TRUE);
break;
case GTK_RESPONSE_NO:
video_window_set_fullscreen(video_window,FALSE);
break;
case GTK_RESPONSE_REJECT:
{
LinphoneCall *call=(LinphoneCall*)g_object_get_data(G_OBJECT(video_window),"call");
linphone_core_terminate_call(linphone_gtk_get_core(),call);
}
break;
}
}
static void on_controls_destroy(GtkWidget *w){
GtkWidget *video_window=(GtkWidget*)g_object_get_data(G_OBJECT(w),"video_window");
gint timeout=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"timeout"));
if (timeout!=0){
g_source_remove(timeout);
g_object_set_data(G_OBJECT(w),"timeout",GINT_TO_POINTER(0));
}
g_object_set_data(G_OBJECT(video_window),"controls",NULL);
}
static gboolean _set_video_controls_position(GtkWidget *video_window){
GtkWidget *w=(GtkWidget*)g_object_get_data(G_OBJECT(video_window),"controls");
if (w){
gint vw,vh;
gint cw,ch;
gint x,y;
gtk_window_get_size(GTK_WINDOW(video_window),&vw,&vh);
gtk_window_get_position(GTK_WINDOW(video_window),&x,&y);
gtk_window_get_size(GTK_WINDOW(w),&cw,&ch);
gtk_window_move(GTK_WINDOW(w),x+vw/2 - cw/2, y + vh - ch);
}
return FALSE;
}
static void set_video_controls_position(GtkWidget *video_window){
/*do it a first time*/
_set_video_controls_position(video_window);
/*and schedule to do it a second time in order to workaround a bug in fullscreen mode, where poistion is not taken into account the first time*/
g_timeout_add(0,(GSourceFunc)_set_video_controls_position,video_window);
}
static gboolean video_window_moved(GtkWidget *widget, GdkEvent *event, gpointer user_data){
set_video_controls_position(widget);
return FALSE;
}
static GtkWidget *show_video_controls(GtkWidget *video_window){
GtkWidget *w;
w=(GtkWidget*)g_object_get_data(G_OBJECT(video_window),"controls");
if (!w){
gboolean isfullscreen=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(video_window),"fullscreen"));
const char *stock_button=isfullscreen ? GTK_STOCK_LEAVE_FULLSCREEN : GTK_STOCK_FULLSCREEN;
gint response_id=isfullscreen ? GTK_RESPONSE_NO : GTK_RESPONSE_YES ;
gint timeout;
GtkWidget *button;
w=gtk_dialog_new_with_buttons("",GTK_WINDOW(video_window),GTK_DIALOG_DESTROY_WITH_PARENT,stock_button,response_id,NULL);
gtk_window_set_opacity(GTK_WINDOW(w),0.5);
gtk_window_set_decorated(GTK_WINDOW(w),FALSE);
button=gtk_button_new_with_label(_("Hang up"));
gtk_button_set_image(GTK_BUTTON(button),create_pixmap (linphone_gtk_get_ui_config("stop_call_icon","stopcall-small.png")));
gtk_widget_show(button);
gtk_dialog_add_action_widget(GTK_DIALOG(w),button,GTK_RESPONSE_REJECT);
g_signal_connect(w,"response",(GCallback)on_controls_response,video_window);
timeout=g_timeout_add(3000,(GSourceFunc)gtk_widget_destroy,w);
g_object_set_data(G_OBJECT(w),"timeout",GINT_TO_POINTER(timeout));
g_signal_connect(w,"destroy",(GCallback)on_controls_destroy,NULL);
g_object_set_data(G_OBJECT(w),"video_window",video_window);
g_object_set_data(G_OBJECT(video_window),"controls",w);
set_video_controls_position(video_window);
gtk_widget_show(w);
}else{
gint timeout=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"timeout"));
g_source_remove(timeout);
timeout=g_timeout_add(3000,(GSourceFunc)gtk_widget_destroy,w);
g_object_set_data(G_OBJECT(w),"timeout",GINT_TO_POINTER(timeout));
}
return w;
}
static GtkWidget *create_video_window(LinphoneCall *call){
char *remote,*title;
GtkWidget *video_window;
const LinphoneAddress *addr;
const char *icon_path=linphone_gtk_get_ui_config("icon",LINPHONE_ICON);
GdkPixbuf *pbuf=create_pixbuf(icon_path);
guint timeout;
MSVideoSize vsize=MS_VIDEO_SIZE_CIF;
GdkColor color;
addr=linphone_call_get_remote_address(call);
remote=linphone_gtk_address(addr);
video_window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
title=g_strdup_printf("%s - Video call with %s",linphone_gtk_get_ui_config("title","Linphone"),remote);
ms_free(remote);
gtk_window_set_title(GTK_WINDOW(video_window),title);
g_free(title);
if (pbuf){
gtk_window_set_icon(GTK_WINDOW(video_window),pbuf);
}
gtk_window_resize(GTK_WINDOW(video_window),vsize.width,vsize.height);
gdk_color_parse("black",&color);
gtk_widget_modify_bg(video_window,GTK_STATE_NORMAL,&color);
gtk_drag_dest_set(video_window, GTK_DEST_DEFAULT_ALL, targets, sizeof(targets)/sizeof(GtkTargetEntry), GDK_ACTION_COPY);
gtk_widget_show(video_window);
gdk_window_set_events(gtk_widget_get_window(video_window),
gdk_window_get_events(gtk_widget_get_window(video_window)) | GDK_POINTER_MOTION_MASK);
timeout=g_timeout_add(500,(GSourceFunc)resize_video_window,call);
g_signal_connect(video_window,"destroy",(GCallback)on_video_window_destroy,GINT_TO_POINTER(timeout));
g_signal_connect(video_window,"key-press-event",(GCallback)on_video_window_key_press,NULL);
g_signal_connect_swapped(video_window,"motion-notify-event",(GCallback)show_video_controls,video_window);
g_signal_connect(video_window,"configure-event",(GCallback)video_window_moved,NULL);
g_signal_connect(video_window, "drag-data-received",(GCallback)drag_data_received, NULL);
g_signal_connect(video_window, "drag-drop",(GCallback)drag_drop, NULL);
g_object_set_data(G_OBJECT(video_window),"call",call);
return video_window;
}
void linphone_gtk_in_call_show_video(LinphoneCall *call){
GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
GtkWidget *video_window=(GtkWidget*)g_object_get_data(G_OBJECT(callview),"video_window");
const LinphoneCallParams *params=linphone_call_get_current_params(call);
LinphoneCore *lc=linphone_gtk_get_core();
if (linphone_call_get_state(call)!=LinphoneCallPaused && params && linphone_call_params_video_enabled(params)){
if (video_window==NULL){
video_window=create_video_window(call);
g_object_set_data(G_OBJECT(callview),"video_window",video_window);
}
linphone_core_set_native_video_window_id(lc,get_native_handle(gtk_widget_get_window(video_window)));
}else{
if (video_window){
gtk_widget_destroy(video_window);
g_object_set_data(G_OBJECT(callview),"video_window",NULL);
}
}
}

View file

@ -68,13 +68,15 @@ typedef enum {
SalTransportDTLS /*DTLS*/
}SalTransport;
#define SAL_MEDIA_DESCRIPTION_UNCHANGED 0x00
#define SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED 0x01
#define SAL_MEDIA_DESCRIPTION_CODEC_CHANGED 0x02
#define SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED 0x04
#define SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED 0x08
#define SAL_MEDIA_DESCRIPTION_UNCHANGED 0x00
#define SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED (1)
#define SAL_MEDIA_DESCRIPTION_CODEC_CHANGED (1<<1)
#define SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED (1<<2)
#define SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED (1<<3)
#define SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED (1<<4)
#define SAL_MEDIA_DESCRIPTION_CHANGED (SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED | SAL_MEDIA_DESCRIPTION_CODEC_CHANGED |\
SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED |SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED)
SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED |SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED | SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED)
const char* sal_transport_to_string(SalTransport transport);
SalTransport sal_transport_parse(const char*);

@ -1 +1 @@
Subproject commit 21e35e89ffa8920bb0b5865d365b84471ecfa321
Subproject commit 91f2782073c776b2d5ce3ab0a12561aea7610068

2
oRTP

@ -1 +1 @@
Subproject commit 45da3ab75d39587189ea95829ee1cb92d61827be
Subproject commit 540ee49bd3f65139f7e5938cc6bc1f8a4353c3f7

View file

@ -22,7 +22,8 @@ liblinphonetester_la_SOURCES = tester.c \
stun_tester.c \
remote_provisioning_tester.c \
quality_reporting_tester.c \
transport_tester.c
transport_tester.c \
player_tester.c
liblinphonetester_la_LDFLAGS= -no-undefined
liblinphonetester_la_LIBADD= ../coreapi/liblinphone.la $(CUNIT_LIBS)

View file

@ -25,10 +25,16 @@
#include "lpconfig.h"
#include "private.h"
#include "liblinphone_tester.h"
#include "mediastreamer2/dsptools.h"
#ifdef WIN32
#define unlink _unlink
#endif
static void srtp_call(void);
static void call_base(LinphoneMediaEncryption mode, bool_t enable_video,bool_t enable_relay,LinphoneFirewallPolicy policy);
static void disable_all_audio_codecs_except_one(LinphoneCore *lc, const char *mime, int rate);
static char *create_filepath(const char *dir, const char *filename, const char *ext);
// prototype definition for call_recording()
#ifdef ANDROID
@ -775,6 +781,7 @@ static void call_with_no_sdp(void) {
linphone_core_manager_destroy(pauline);
}
static bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee, LinphoneIceState state) {
LinphoneCall *c1,*c2;
bool_t audio_success=FALSE;
@ -1878,6 +1885,114 @@ static void call_with_declined_srtp(void) {
linphone_core_manager_destroy(pauline);
}
static void on_eof(LinphonePlayer *player, void *user_data){
LinphoneCoreManager *marie=(LinphoneCoreManager*)user_data;
marie->stat.number_of_player_eof++;
}
static void call_with_file_player(void) {
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
LinphonePlayer *player;
char hellopath[256];
char *recordpath = create_filepath(liblinphone_tester_writable_dir_prefix, "record", "wav");
double similar;
/*make sure the record file doesn't already exists, otherwise this test will append new samples to it*/
unlink(recordpath);
snprintf(hellopath,sizeof(hellopath), "%s/sounds/hello8000.wav", liblinphone_tester_file_prefix);
/*caller uses soundcard*/
/*callee is recording and plays file*/
linphone_core_use_files(pauline->lc,TRUE);
linphone_core_set_play_file(pauline->lc,hellopath);
linphone_core_set_record_file(pauline->lc,recordpath);
CU_ASSERT_TRUE(call(marie,pauline));
player=linphone_call_get_player(linphone_core_get_current_call(marie->lc));
CU_ASSERT_PTR_NOT_NULL(player);
if (player){
CU_ASSERT_TRUE(linphone_player_open(player,hellopath,on_eof,marie)==0);
CU_ASSERT_TRUE(linphone_player_start(player)==0);
}
CU_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_player_eof,1,12000));
/*just to sleep*/
linphone_core_terminate_all_calls(marie->lc);
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1));
CU_ASSERT_TRUE(ms_audio_diff(hellopath,recordpath,&similar,NULL,NULL)==0);
CU_ASSERT_TRUE(similar>0.9);
CU_ASSERT_TRUE(similar<=1.0);
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
ms_free(recordpath);
}
static bool_t is_format_supported(LinphoneCore *lc, const char *fmt){
const char **formats=linphone_core_get_supported_file_formats(lc);
for(;*formats!=NULL;++formats){
if (strcasecmp(*formats,fmt)==0) return TRUE;
}
return FALSE;
}
static void call_with_mkv_file_player(void) {
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
LinphonePlayer *player;
char hellomkv[256];
char hellowav[256];
char *recordpath;
double similar;
if (!is_format_supported(marie->lc,"mkv")){
ms_warning("Test skipped, no mkv support.");
goto end;
}
recordpath = create_filepath(liblinphone_tester_writable_dir_prefix, "record", "wav");
/*make sure the record file doesn't already exists, otherwise this test will append new samples to it*/
unlink(recordpath);
snprintf(hellowav,sizeof(hellowav), "%s/sounds/hello8000.wav", liblinphone_tester_file_prefix);
snprintf(hellomkv,sizeof(hellomkv), "%s/sounds/hello8000.mkv", liblinphone_tester_file_prefix);
/*caller uses soundcard*/
/*callee is recording and plays file*/
linphone_core_use_files(pauline->lc,TRUE);
linphone_core_set_play_file(pauline->lc,hellowav); /*just to send something but we are not testing what is sent by pauline*/
linphone_core_set_record_file(pauline->lc,recordpath);
CU_ASSERT_TRUE(call(marie,pauline));
player=linphone_call_get_player(linphone_core_get_current_call(marie->lc));
CU_ASSERT_PTR_NOT_NULL(player);
if (player){
CU_ASSERT_TRUE(linphone_player_open(player,hellomkv,on_eof,marie)==0);
CU_ASSERT_TRUE(linphone_player_start(player)==0);
}
CU_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_player_eof,1,12000));
/*just to sleep*/
linphone_core_terminate_all_calls(marie->lc);
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1));
CU_ASSERT_TRUE(ms_audio_diff(hellowav,recordpath,&similar,NULL,NULL)==0);
CU_ASSERT_TRUE(similar>0.9);
CU_ASSERT_TRUE(similar<=1.0);
ms_free(recordpath);
end:
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
static void call_base(LinphoneMediaEncryption mode, bool_t enable_video,bool_t enable_relay,LinphoneFirewallPolicy policy) {
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
@ -2808,13 +2923,7 @@ static void savpf_to_savpf_call(void) {
}
static char *create_filepath(const char *dir, const char *filename, const char *ext) {
char *filepath = ms_new0(char, strlen(dir) + strlen(filename) + strlen(ext) + 3);
strcpy(filepath, dir);
strcat(filepath, "/");
strcat(filepath, filename);
strcat(filepath, ".");
strcat(filepath, ext);
return filepath;
return ms_strdup_printf("%s/%s.%s",dir,filename,ext);
}
static void record_call(const char *filename, bool_t enableVideo) {
@ -2867,7 +2976,6 @@ static void record_call(const char *filename, bool_t enableVideo) {
linphone_call_stop_recording(callInst);
end_call(marie, pauline);
CU_ASSERT_EQUAL(access(filepath, F_OK), 0);
remove(filepath);
}
ms_free(filepath);
}
@ -2949,7 +3057,57 @@ static void call_with_in_dialog_update(void) {
belle_sip_object_dump_active_objects();
}
}
static void call_with_in_dialog_codec_change_base(bool_t no_sdp) {
int begin;
int leaked_objects;
int dummy=0;
LinphoneCoreManager* marie;
LinphoneCoreManager* pauline;
LinphoneCallParams *params;
belle_sip_object_enable_leak_detector(TRUE);
begin=belle_sip_object_get_object_count();
marie = linphone_core_manager_new( "marie_rc");
pauline = linphone_core_manager_new( "pauline_rc");
CU_ASSERT_TRUE(call(pauline,marie));
liblinphone_tester_check_rtcp(marie,pauline);
params=linphone_core_create_call_params(marie->lc,linphone_core_get_current_call(marie->lc));
linphone_core_enable_payload_type(pauline->lc,linphone_core_find_payload_type(pauline->lc,"PCMU",8000,1),FALSE); /*disable PCMU*/
linphone_core_enable_payload_type(marie->lc,linphone_core_find_payload_type(marie->lc,"PCMU",8000,1),FALSE); /*disable PCMU*/
linphone_core_enable_payload_type(pauline->lc,linphone_core_find_payload_type(pauline->lc,"PCMA",8000,1),TRUE); /*enable PCMA*/
linphone_core_enable_payload_type(marie->lc,linphone_core_find_payload_type(marie->lc,"PCMA",8000,1),TRUE); /*enable PCMA*/
if (no_sdp) {
linphone_core_enable_sdp_200_ack(marie->lc,TRUE);
}
linphone_core_update_call(marie->lc,linphone_core_get_current_call(marie->lc),params);
linphone_call_params_destroy(params);
CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallUpdating,1));
CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,2));
CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallUpdatedByRemote,1));
CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,2));
CU_ASSERT_STRING_EQUAL("PCMA",linphone_payload_type_get_mime_type(linphone_call_params_get_used_audio_codec(linphone_call_get_current_params(linphone_core_get_current_call(marie->lc)))));
wait_for_until(marie->lc, pauline->lc, &dummy, 1, 3000);
CU_ASSERT_TRUE(linphone_call_get_audio_stats(linphone_core_get_current_call(marie->lc))->download_bandwidth>70);
CU_ASSERT_TRUE(linphone_call_get_audio_stats(linphone_core_get_current_call(pauline->lc))->download_bandwidth>70);
end_call(marie,pauline);
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
leaked_objects=belle_sip_object_get_object_count()-begin;
CU_ASSERT_TRUE(leaked_objects==0);
if (leaked_objects>0){
belle_sip_object_dump_active_objects();
}
}
static void call_with_in_dialog_codec_change(void) {
call_with_in_dialog_codec_change_base(FALSE);
}
static void call_with_in_dialog_codec_change_no_sdp(void) {
call_with_in_dialog_codec_change_base(TRUE);
}
static void call_with_custom_supported_tags(void) {
int begin;
int leaked_objects;
@ -3015,6 +3173,8 @@ test_t call_tests[] = {
{ "ZRTP call",zrtp_call},
{ "ZRTP video call",zrtp_video_call},
{ "SRTP call with declined srtp", call_with_declined_srtp },
{ "Call with file player", call_with_file_player},
{ "Call with mkv file player", call_with_mkv_file_player},
#ifdef VIDEO_ENABLED
{ "Simple video call",video_call},
{ "Simple video call using policy",video_call_using_policy},
@ -3079,6 +3239,8 @@ test_t call_tests[] = {
{ "SAVPF to SAVP call", savpf_to_savp_call },
{ "SAVPF to SAVPF call", savpf_to_savpf_call },
{ "Call with in-dialog UPDATE request", call_with_in_dialog_update },
{ "Call with in-dialog codec change", call_with_in_dialog_codec_change },
{ "Call with in-dialog codec change no sdp", call_with_in_dialog_codec_change_no_sdp },
{ "Call with custom supported tags", call_with_custom_supported_tags }
};

View file

@ -13,17 +13,16 @@ RPIGEkQ2wzG9AJq7iJ2Yy8+2kTvULajvhI0JrSqVbgS9Z9fUKgCN6oIZfvQsrxus
UcIc3KjqaP1mLw7aIpUCQH5S0B+GOwKa8+RbuRcgBvksqkRwRZn6jawoNJJSBCDn
gQJ5B9PvJXppTsbnulSD2srhUqCR1pzGfnl8bYV8b8Q=
-----END RSA PRIVATE KEY-----
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 5 (0x5)
Serial Number: 9 (0x9)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=FR, ST=Some-State, L=Grenoble, O=Belledonne Communications, OU=LAB, CN=Jehan Monnier/emailAddress=jehan.monnier@belledonne-communications.com
Validity
Not Before: Sep 23 15:58:58 2013 GMT
Not After : Sep 23 15:58:58 2014 GMT
Subject: C=FR, ST=France, L=Grenoble, O=Belledonne Communications, OU=LAB, CN=See altname for DNS name/emailAddress=jehan.monnier@belledonne-communications.com
Not Before: Sep 25 16:12:35 2014 GMT
Not After : Sep 22 16:12:35 2024 GMT
Subject: C=FR, ST=France, L=Grenoble, O=Belledonne Communications, OU=LAB, CN=Jehan Monnier/emailAddress=jehan.monnier@belledonne-communications.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (1024 bit)
@ -46,31 +45,31 @@ Certificate:
X509v3 Subject Alternative Name:
DNS:altname.linphone.org, DNS:*.wildcard2.linphone.org
Signature Algorithm: sha1WithRSAEncryption
21:05:d3:36:82:5d:f4:f4:70:71:17:ac:06:12:49:0c:d6:c3:
21:07:9c:2f:79:c8:14:da:e5:3a:92:04:22:5b:74:cf:53:3c:
95:33:51:93:66:04:59:c6:3d:dd:22:cf:3f:f8:0e:24:93:6b:
2a:02:f7:bf:ba:89:1b:72:9a:d4:1b:bf:22:3d:08:51:13:a4:
bf:43:d2:89:a1:c5:f2:e3:04:24:1e:d4:33:64:06:83:2d:b6:
66:34:16:a9:f4:8d:6f:3f:71:86:ab:73:19:36:ae:43:29:7e:
9d:6c:35:3a:75:f4:22:8b:c5:e3:1e:ee:c1:0d:d7:63:cc:95:
4a:6a
56:f5:23:64:4c:8d:85:6e:05:d6:42:a3:41:b2:6a:ab:a1:cd:
be:ae:4a:38:c5:23:4c:62:2c:06:4d:49:b7:fc:ad:86:1d:9b:
c0:7e:33:80:fa:7d:31:8b:ca:9c:28:44:b2:1c:f1:ed:73:5b:
d3:80:72:b0:6c:0b:20:2b:e5:2b:02:c6:be:14:ad:55:34:2f:
6f:8e:bb:7b:61:ce:9c:af:85:a7:b0:cd:d1:4e:1e:17:e9:7e:
61:ed:50:60:9a:de:d0:7a:6d:a5:ee:04:9a:5c:41:94:21:e5:
05:61:a8:17:ab:eb:b4:cc:7f:90:9b:3a:0e:ca:31:fb:65:40:
11:2d
-----BEGIN CERTIFICATE-----
MIIDSjCCArOgAwIBAgIBBTANBgkqhkiG9w0BAQUFADCBuzELMAkGA1UEBhMCRlIx
MIIDPzCCAqigAwIBAgIBCTANBgkqhkiG9w0BAQUFADCBuzELMAkGA1UEBhMCRlIx
EzARBgNVBAgMClNvbWUtU3RhdGUxETAPBgNVBAcMCEdyZW5vYmxlMSIwIAYDVQQK
DBlCZWxsZWRvbm5lIENvbW11bmljYXRpb25zMQwwCgYDVQQLDANMQUIxFjAUBgNV
BAMMDUplaGFuIE1vbm5pZXIxOjA4BgkqhkiG9w0BCQEWK2plaGFuLm1vbm5pZXJA
YmVsbGVkb25uZS1jb21tdW5pY2F0aW9ucy5jb20wHhcNMTMwOTIzMTU1ODU4WhcN
MTQwOTIzMTU1ODU4WjCBwjELMAkGA1UEBhMCRlIxDzANBgNVBAgMBkZyYW5jZTER
YmVsbGVkb25uZS1jb21tdW5pY2F0aW9ucy5jb20wHhcNMTQwOTI1MTYxMjM1WhcN
MjQwOTIyMTYxMjM1WjCBtzELMAkGA1UEBhMCRlIxDzANBgNVBAgMBkZyYW5jZTER
MA8GA1UEBwwIR3Jlbm9ibGUxIjAgBgNVBAoMGUJlbGxlZG9ubmUgQ29tbXVuaWNh
dGlvbnMxDDAKBgNVBAsMA0xBQjEhMB8GA1UEAwwYU2VlIGFsdG5hbWUgZm9yIERO
UyBuYW1lMTowOAYJKoZIhvcNAQkBFitqZWhhbi5tb25uaWVyQGJlbGxlZG9ubmUt
Y29tbXVuaWNhdGlvbnMuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDH
ZG78iwkkxJeq3ZPuQwY9DfdcNCvHXayW+5p5VUULV50ohJKtJJzhp5ysq4VH7q/d
mOnMnbYTACnqVSlph88zRdQJd/g0h6T4DyWa5Jxe+R1hwLWVfgeSXstCK8m9SwxK
qnqA5mPZxfARXg3r4XWkUK2A1lWIXCkZU3MMD4JJ4QIDAQABo1UwUzAJBgNVHRME
AjAAMAsGA1UdDwQEAwIF4DA5BgNVHREEMjAwghRhbHRuYW1lLmxpbnBob25lLm9y
Z4IYKi53aWxkY2FyZDIubGlucGhvbmUub3JnMA0GCSqGSIb3DQEBBQUAA4GBACEF
0zaCXfT0cHEXrAYSSQzWwyEHnC95yBTa5TqSBCJbdM9TPJUzUZNmBFnGPd0izz/4
DiSTayoC97+6iRtymtQbvyI9CFETpL9D0omhxfLjBCQe1DNkBoMttmY0Fqn0jW8/
cYarcxk2rkMpfp1sNTp19CKLxeMe7sEN12PMlUpq
dGlvbnMxDDAKBgNVBAsMA0xBQjEWMBQGA1UEAwwNSmVoYW4gTW9ubmllcjE6MDgG
CSqGSIb3DQEJARYramVoYW4ubW9ubmllckBiZWxsZWRvbm5lLWNvbW11bmljYXRp
b25zLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAx2Ru/IsJJMSXqt2T
7kMGPQ33XDQrx12slvuaeVVFC1edKISSrSSc4aecrKuFR+6v3ZjpzJ22EwAp6lUp
aYfPM0XUCXf4NIek+A8lmuScXvkdYcC1lX4Hkl7LQivJvUsMSqp6gOZj2cXwEV4N
6+F1pFCtgNZViFwpGVNzDA+CSeECAwEAAaNVMFMwCQYDVR0TBAIwADALBgNVHQ8E
BAMCBeAwOQYDVR0RBDIwMIIUYWx0bmFtZS5saW5waG9uZS5vcmeCGCoud2lsZGNh
cmQyLmxpbnBob25lLm9yZzANBgkqhkiG9w0BAQUFAAOBgQBW9SNkTI2FbgXWQqNB
smqroc2+rko4xSNMYiwGTUm3/K2GHZvAfjOA+n0xi8qcKESyHPHtc1vTgHKwbAsg
K+UrAsa+FK1VNC9vjrt7Yc6cr4WnsM3RTh4X6X5h7VBgmt7Qem2l7gSaXEGUIeUF
YagXq+u0zH+QmzoOyjH7ZUARLQ==
-----END CERTIFICATE-----

View file

@ -39,7 +39,7 @@ default_ca = CA_default # The default ca section
####################################################################
[ CA_default ]
dir = ./demoCA # Where everything is kept
dir = . # Where everything is kept
certs = $dir/certs # Where the issued certs are kept
crl_dir = $dir/crl # Where the issued crl are kept
database = $dir/index.txt # database index file.

View file

@ -39,7 +39,7 @@ default_ca = CA_default # The default ca section
####################################################################
[ CA_default ]
dir = ./demoCA # Where everything is kept
dir = . # Where everything is kept
certs = $dir/certs # Where the issued certs are kept
crl_dir = $dir/crl # Where the issued crl are kept
database = $dir/index.txt # database index file.

View file

@ -59,6 +59,7 @@ extern test_suite_t stun_test_suite;
extern test_suite_t remote_provisioning_test_suite;
extern test_suite_t quality_reporting_test_suite;
extern test_suite_t transport_test_suite;
extern test_suite_t player_test_suite;
extern int liblinphone_tester_nb_test_suites(void);
@ -195,6 +196,7 @@ typedef struct _stats {
int number_of_LinphoneCallEncryptedOff;
int number_of_NetworkReachableTrue;
int number_of_NetworkReachableFalse;
int number_of_player_eof;
LinphoneChatMessage* last_received_chat_message;
}stats;

View file

@ -281,7 +281,7 @@ static void text_message_with_privacy(void) {
/* make sure lime is not enabled */
linphone_core_set_lime(marie->lc, 0);
linphone_core_set_lime(pauline->lc, 0);
to = linphone_address_as_string(marie->identity);
chat_room = linphone_core_create_chat_room(pauline->lc,to);
ms_free(to);

64
tester/player_tester.c Normal file
View file

@ -0,0 +1,64 @@
#include "liblinphone_tester.h"
static bool_t wait_for_eof(bool_t *eof, int *time,int time_refresh, int timeout) {
while(*time < timeout && !*eof) {
usleep(time_refresh * 1000U);
*time += time_refresh;
}
return *time < timeout;
}
static void eof_callback(LinphonePlayer *player, void *user_data) {
bool_t *eof = (bool_t *)user_data;
*eof = TRUE;
}
static void play_file(const char *filename, bool_t unsupported_format) {
LinphoneCoreManager *lc_manager;
LinphonePlayer *player;
int res, time = 0;
bool_t eof = FALSE;
lc_manager = linphone_core_manager_new("marie_rc");
CU_ASSERT_PTR_NOT_NULL(lc_manager);
if(lc_manager == NULL) return;
player = linphone_core_create_file_player(lc_manager->lc, ms_snd_card_manager_get_default_card(ms_snd_card_manager_get()), video_stream_get_default_video_renderer());
CU_ASSERT_PTR_NOT_NULL(player);
if(player == NULL) goto fail;
res = linphone_player_open(player, filename, eof_callback, &eof);
if(unsupported_format) {
CU_ASSERT_EQUAL(res, -1);
} else {
CU_ASSERT_EQUAL(res, 0);
}
if(res == -1) goto fail;
CU_ASSERT_EQUAL((res = linphone_player_start(player)), 0);
if(res == -1) goto fail;
CU_ASSERT_TRUE(wait_for_eof(&eof, &time, 100, 13000));
linphone_player_close(player);
fail:
if(player) linphone_file_player_destroy(player);
if(lc_manager) linphone_core_manager_destroy(lc_manager);
}
static void playing_test(void) {
play_file("sounds/hello_opus_h264.mkv", !linphone_file_player_matroska_supported());
}
test_t player_tests[] = {
{ "Playing" , playing_test }
};
test_suite_t player_test_suite = {
"Player",
NULL,
NULL,
sizeof(player_tests) / sizeof(test_t),
player_tests
};

BIN
tester/sounds/hello8000.mkv Normal file

Binary file not shown.

Binary file not shown.

View file

@ -388,6 +388,7 @@ void liblinphone_tester_init(void) {
add_test_suite(&remote_provisioning_test_suite);
add_test_suite(&quality_reporting_test_suite);
add_test_suite(&transport_test_suite);
add_test_suite(&player_test_suite);
}
void liblinphone_tester_uninit(void) {

View file

@ -59,7 +59,7 @@ static char* get_public_contact_ip(LinphoneCore* lc) {
ms_free(contact);
return ms_strdup(contact_host_ip);
}
static void call_with_transport_base(bool_t use_tunnel, bool_t with_sip, LinphoneMediaEncryption encryption) {
static void call_with_transport_base(LinphoneTunnelMode tunnel_mode, bool_t with_sip, LinphoneMediaEncryption encryption) {
if (linphone_core_tunnel_available()){
char *tmp_char;
LinphoneCoreManager *pauline = linphone_core_manager_new( "pauline_rc");
@ -69,7 +69,7 @@ static void call_with_transport_base(bool_t use_tunnel, bool_t with_sip, Linphon
LinphoneAddress *server_addr = linphone_address_new(linphone_proxy_config_get_server_addr(proxy));
LinphoneAddress *route = linphone_address_new(linphone_proxy_config_get_route(proxy));
const char * tunnel_ip = get_ip_from_hostname("tunnel.linphone.org");
char *public_ip;
char *public_ip, *public_ip2=NULL;
CU_ASSERT_TRUE(wait_for(pauline->lc,NULL,&pauline->stat.number_of_LinphoneRegistrationOk,1));
public_ip = get_public_contact_ip(pauline->lc);
@ -77,7 +77,7 @@ static void call_with_transport_base(bool_t use_tunnel, bool_t with_sip, Linphon
linphone_core_set_media_encryption(pauline->lc, encryption);
if (use_tunnel){
if (tunnel_mode != LinphoneTunnelModeDisable){
LinphoneTunnel *tunnel = linphone_core_get_tunnel(pauline->lc);
LinphoneTunnelConfig *config = linphone_tunnel_config_new();
@ -91,24 +91,30 @@ static void call_with_transport_base(bool_t use_tunnel, bool_t with_sip, Linphon
tmp_char = linphone_address_as_string(route);
linphone_proxy_config_set_route(proxy, tmp_char);
ms_free(tmp_char);
linphone_tunnel_set_mode(tunnel, LinphoneTunnelModeEnable);
if(with_sip) linphone_tunnel_enable_sip(tunnel, with_sip);
linphone_tunnel_config_set_host(config, "tunnel.linphone.org");
linphone_tunnel_config_set_port(config, 443);
linphone_tunnel_config_set_remote_udp_mirror_port(config, 12345);
linphone_tunnel_add_server(tunnel, config);
linphone_tunnel_set_mode(tunnel, tunnel_mode);
linphone_tunnel_enable_sip(tunnel, with_sip);
linphone_proxy_config_done(proxy);
/*enabling the tunnel cause another REGISTER to be made*/
CU_ASSERT_TRUE(wait_for(pauline->lc,NULL,&pauline->stat.number_of_LinphoneRegistrationOk,2));
/* Ensure that we did use the tunnel. If so, we should see contact changed from:
Contact: <sip:pauline@192.168.0.201>;.[...]
To:
Contact: <sip:pauline@91.121.209.194:43867>;[....] (91.121.209.194 must be tunnel.liphone.org)
*/
ms_free(public_ip);
public_ip = get_public_contact_ip(pauline->lc);
CU_ASSERT_STRING_EQUAL(public_ip, tunnel_ip);
if(tunnel_mode == LinphoneTunnelModeEnable) {
/* Ensure that we did use the tunnel. If so, we should see contact changed from:
Contact: <sip:pauline@192.168.0.201>;.[...]
To:
Contact: <sip:pauline@91.121.209.194:43867>;[....] (91.121.209.194 must be tunnel.liphone.org)
*/
ms_free(public_ip);
public_ip = get_public_contact_ip(pauline->lc);
CU_ASSERT_STRING_EQUAL(public_ip, tunnel_ip);
} else {
public_ip2 = get_public_contact_ip(pauline->lc);
CU_ASSERT_STRING_EQUAL(public_ip, public_ip2);
}
}
CU_ASSERT_TRUE(call(pauline,marie));
@ -121,6 +127,7 @@ static void call_with_transport_base(bool_t use_tunnel, bool_t with_sip, Linphon
end_call(pauline,marie);
ms_free(public_ip);
if(public_ip2 != NULL) ms_free(public_ip2);
linphone_address_destroy(server_addr);
linphone_address_destroy(route);
linphone_core_manager_destroy(pauline);
@ -131,21 +138,31 @@ static void call_with_transport_base(bool_t use_tunnel, bool_t with_sip, Linphon
}
static void call_with_tunnel(void) {
call_with_transport_base(TRUE, TRUE, LinphoneMediaEncryptionNone);
call_with_transport_base(LinphoneTunnelModeEnable, TRUE, LinphoneMediaEncryptionNone);
}
static void call_with_tunnel_srtp(void) {
call_with_transport_base(TRUE, TRUE, LinphoneMediaEncryptionSRTP);
call_with_transport_base(LinphoneTunnelModeEnable, TRUE, LinphoneMediaEncryptionSRTP);
}
static void call_with_tunnel_without_sip(void) {
call_with_transport_base(TRUE, FALSE, LinphoneMediaEncryptionNone);
call_with_transport_base(LinphoneTunnelModeEnable, FALSE, LinphoneMediaEncryptionNone);
}
static void call_with_tunnel_auto(void) {
call_with_transport_base(LinphoneTunnelModeAuto, TRUE, LinphoneMediaEncryptionNone);
}
static void call_with_tunnel_auto_without_sip_with_srtp(void) {
call_with_transport_base(LinphoneTunnelModeAuto, FALSE, LinphoneMediaEncryptionSRTP);
}
test_t transport_tests[] = {
{ "Tunnel only", call_with_tunnel },
{ "Tunnel with SRTP", call_with_tunnel_srtp },
{ "Tunnel without SIP", call_with_tunnel_without_sip }
{ "Tunnel without SIP", call_with_tunnel_without_sip },
{ "Tunnel in automatic mode", call_with_tunnel_auto },
{ "Tunnel in automatic mode with SRTP without SIP", call_with_tunnel_auto_without_sip_with_srtp },
};
test_suite_t transport_test_suite = {

55
tools/CMakeLists.txt Normal file
View file

@ -0,0 +1,55 @@
############################################################################
# CMakeLists.txt
# Copyright (C) 2014 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.
#
############################################################################
if(MSVC)
find_library(LIBGCC NAMES gcc)
find_library(LIBMINGWEX NAMES mingwex)
endif()
set(LP_GEN_WRAPPERS_SOURCE_FILES
generator.cc
generator.hh
genwrappers.cc
software-desc.cc
software-desc.hh
)
add_definitions(
-DIN_LINPHONE
)
set(LP_GEN_WRAPPERS_LIBS
${LIBGCC}
${LIBMINGWEX}
${XML2_LIBRARIES}
)
add_executable(lp-gen-wrappers ${LP_GEN_WRAPPERS_SOURCE_FILES})
target_link_libraries(lp-gen-wrappers ${LP_GEN_WRAPPERS_LIBS})
install(TARGETS lp-gen-wrappers
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
)

View file

@ -46,6 +46,7 @@ blacklisted_functions = [
'linphone_chat_message_start_file_download', # to be handwritten because of callback
'linphone_chat_message_state_to_string', # There is no use to wrap this function
'linphone_chat_room_create_file_transfer_message', # missing LinphoneContent
'linphone_core_add_listener',
'linphone_core_can_we_add_call', # private function
'linphone_core_get_audio_port_range', # to be handwritten because of result via arguments
'linphone_core_get_sip_transports', # missing LCSipTransports
@ -54,6 +55,7 @@ blacklisted_functions = [
'linphone_core_get_video_policy', # missing LinphoneVideoPolicy
'linphone_core_get_video_port_range', # to be handwritten because of result via arguments
'linphone_core_publish', # missing LinphoneContent
'linphone_core_remove_listener',
'linphone_core_serialize_logs', # There is no use to wrap this function
'linphone_core_set_log_file', # There is no use to wrap this function
'linphone_core_set_log_handler', # Hand-written but put directly in the linphone module