Commit 44e18649 authored by Sylvain Berfini's avatar Sylvain Berfini 🎩
Browse files

Merge branch 'master' into dev_vcard

Conflicts:
	build/android/Android.mk
	coreapi/CMakeLists.txt
	coreapi/Makefile.am
	coreapi/friend.c
	coreapi/linphonecore.c
	coreapi/linphonecore.h
parents 4561b0ce dab5cc72
......@@ -47,7 +47,7 @@ LOCAL_SRC_FILES := \
call_params.c \
chat.c \
chat_file_transfer.c \
conference.c \
conference.cc \
content.c \
ec-calibrator.c \
enum.c \
......@@ -78,6 +78,7 @@ LOCAL_SRC_FILES := \
xml.c \
xmlrpc.c \
vtables.c \
ringtoneplayer.c
ifndef LIBLINPHONE_VERSION
LIBLINPHONE_VERSION = "Devel"
......
......@@ -2452,7 +2452,7 @@ static void lpc_display_call_states(LinphoneCore *lc){
const char *flag;
bool_t in_conference;
call=(LinphoneCall*)elem->data;
in_conference=linphone_call_params_get_local_conference_mode(linphone_call_get_current_params(call));
in_conference=(linphone_call_get_conference(call) != NULL);
tmp=linphone_call_get_remote_address_as_string (call);
flag=in_conference ? "conferencing" : "";
flag=linphone_call_has_transfer_pending(call) ? "transfer pending" : flag;
......
......@@ -46,6 +46,7 @@ set(LINPHONE_HEADER_FILES
linphone_tunnel.h
lpc2xml.h
lpconfig.h
ringtoneplayer.h
sipsetup.h
xml2lpc.h
xmlrpc.h
......@@ -75,7 +76,6 @@ set(LINPHONE_SOURCE_FILES_C
call_params.c
chat.c
chat_file_transfer.c
conference.c
contactprovider.c
content.c
dict.c
......@@ -106,6 +106,7 @@ set(LINPHONE_SOURCE_FILES_C
proxy.c
quality_reporting.c
remote_provisioning.c
ringtoneplayer.c
sal.c
siplogin.c
sipsetup.c
......@@ -114,7 +115,13 @@ set(LINPHONE_SOURCE_FILES_C
xmlrpc.c
vtables.c
)
set(LINPHONE_SOURCE_FILES_CXX )
set(LINPHONE_SOURCE_FILES_CXX conference.cc)
set(LINPHONE_SOURCE_FILES_OBJC)
if (IOS)
list(APPEND LINPHONE_SOURCE_FILES_OBJC ringtoneplayer_ios.m ringtoneplayer_ios.h)
endif()
if(ENABLE_TUNNEL)
list(APPEND LINPHONE_SOURCE_FILES_CXX
......@@ -137,6 +144,10 @@ add_definitions(
-DLIBLINPHONE_EXPORTS
)
apply_compile_flags(LINPHONE_SOURCE_FILES_C "CPP" "C")
apply_compile_flags(LINPHONE_SOURCE_FILES_CXX "CPP" "CXX")
apply_compile_flags(LINPHONE_SOURCE_FILES_OBJC "CPP" "OBJC")
set(LIBS
${BELLESIP_LIBRARIES}
${MEDIASTREAMER2_LIBRARIES}
......@@ -175,10 +186,10 @@ apply_compile_flags(LINPHONE_SOURCE_FILES_C "CPP" "C")
apply_compile_flags(LINPHONE_SOURCE_FILES_CXX "CPP" "CXX")
if(ENABLE_STATIC)
add_library(linphone STATIC ${LINPHONE_HEADER_FILES} ${LINPHONE_SOURCE_FILES_C} ${LINPHONE_SOURCE_FILES_CXX})
add_library(linphone STATIC ${LINPHONE_HEADER_FILES} ${LINPHONE_SOURCE_FILES_C} ${LINPHONE_SOURCE_FILES_CXX} ${LINPHONE_SOURCE_FILES_OBJC})
target_link_libraries(linphone ${LIBS})
else()
add_library(linphone SHARED ${LINPHONE_HEADER_FILES} ${LINPHONE_SOURCE_FILES_C} ${LINPHONE_SOURCE_FILES_CXX})
add_library(linphone SHARED ${LINPHONE_HEADER_FILES} ${LINPHONE_SOURCE_FILES_C} ${LINPHONE_SOURCE_FILES_CXX} ${LINPHONE_SOURCE_FILES_OBJC})
set_target_properties(linphone PROPERTIES VERSION ${LINPHONE_SO_VERSION} LINKER_LANGUAGE CXX)
target_link_libraries(linphone ${LIBS})
if(MSVC)
......@@ -190,6 +201,9 @@ else()
endif()
endif()
endif()
if(IOS)
target_link_libraries(linphone "-framework Foundation" "-framework AVFoundation")
endif()
add_dependencies(linphone liblinphone-git-version)
if(WIN32 AND CMAKE_SYSTEM_NAME STREQUAL "WindowsPhone")
set_target_properties(linphone PROPERTIES PREFIX "lib")
......
......@@ -57,7 +57,7 @@ liblinphone_la_SOURCES=\
call_params.c \
chat.c \
chat_file_transfer.c \
conference.c \
conference.cc conference.h \
contactprovider.c contactprovider.h contact_providers_priv.h \
content.c \
dict.c \
......@@ -92,6 +92,7 @@ liblinphone_la_SOURCES=\
xmlrpc.c \
vtables.c \
carddav.c \
ringtoneplayer.c ringtoneplayer.h\
$(GITVERSION_FILE)
if BUILD_UPNP
......@@ -125,7 +126,7 @@ else
liblinphone_la_SOURCES+=vcard_stubs.c vcard.h
endif
liblinphone_la_LDFLAGS= -version-info $(LIBLINPHONE_SO_VERSION) -no-undefined
liblinphone_la_LDFLAGS=-lstdc++ -version-info $(LIBLINPHONE_SO_VERSION) -no-undefined
if HAVE_LD_OUTPUT_DEF
liblinphone_la_LDFLAGS += -Wl,--output-def,liblinphone-$(LIBLINPHONE_SO_CURRENT).def
......
......@@ -129,6 +129,20 @@ LinphoneTransportType linphone_address_get_transport(const LinphoneAddress *uri)
return (LinphoneTransportType)sal_address_get_transport(uri);
}
/**
* Set the value of the method parameter
**/
void linphone_address_set_method_param(LinphoneAddress *addr, const char *method) {
sal_address_set_method_param(addr, method);
}
/**
* Get the value of the method parameter
**/
const char *linphone_address_get_method_param(const LinphoneAddress *addr) {
return sal_address_get_method_param(addr);
}
/**
* Removes address's tags and uri headers so that it is displayable to the user.
**/
......
......@@ -114,6 +114,15 @@ const char* sal_address_get_transport_name(const SalAddress* addr){
return NULL;
}
const char *sal_address_get_method_param(const SalAddress *addr) {
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);
if (uri) {
return belle_sip_uri_get_method_param(uri);
}
return NULL;
}
void sal_address_set_display_name(SalAddress *addr, const char *display_name){
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
belle_sip_header_address_set_displayname(header_addr,display_name);
......@@ -213,6 +222,10 @@ void sal_address_set_transport_name(SalAddress* addr,const char *transport){
SAL_ADDRESS_SET(addr,transport_param,transport);
}
void sal_address_set_method_param(SalAddress *addr, const char *method) {
SAL_ADDRESS_SET(addr, method_param, method);
}
SalAddress *sal_address_ref(SalAddress *addr){
return (SalAddress*)belle_sip_object_ref(BELLE_SIP_HEADER_ADDRESS(addr));
}
......
......@@ -40,7 +40,7 @@ static void sal_op_set_referred_by(SalOp* op,belle_sip_header_referred_by_t* ref
int sal_call_refer_to(SalOp *op, belle_sip_header_refer_to_t* refer_to, belle_sip_header_referred_by_t* referred_by){
char* tmp;
belle_sip_request_t* req=op->dialog?belle_sip_dialog_create_request(op->dialog,"REFER"):NULL; /*cannot create request if dialog not set yet*/
belle_sip_request_t* req=op->dialog?belle_sip_dialog_create_request(op->dialog,"REFER"):sal_op_build_request(op, "REFER");
if (!req) {
tmp=belle_sip_uri_to_string(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(refer_to)));
ms_error("Cannot refer to [%s] for op [%p]",tmp,op);
......
......@@ -117,7 +117,8 @@ void sal_process_incoming_message(SalOp *op,const belle_sip_request_event_t *eve
if ((cipher_xml=is_cipher_xml(content_type))) {
/* access the zrtp cache to get keys needed to decipher the message */
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
FILE *CACHEFD = fopen(lc->zrtp_secrets_cache, "rb+");
FILE *CACHEFD = NULL;
if (lc->zrtp_secrets_cache != NULL) CACHEFD = fopen(lc->zrtp_secrets_cache, "rb+");
if (CACHEFD == NULL) {
ms_warning("Unable to access ZRTP ZID cache to decrypt message");
goto error;
......
......@@ -125,6 +125,10 @@ LINPHONE_PUBLIC const char *linphone_call_params_get_custom_header(const Linphon
/**
* Tell whether the call is part of the locally managed conference.
* @warning If a conference server is used to manage conferences,
* that function does not return TRUE even if the conference is running.<br/>
* If you want to test whether the conference is running, you should test
* whether linphone_core_get_conference() return a non-null pointer.
* @param[in] cp LinphoneCallParams object
* @return A boolean value telling whether the call is part of the locally managed conference.
**/
......
......@@ -187,7 +187,7 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
ms_message("Media ip type has changed, destroying sessions context on call [%p]",call);
ms_media_stream_sessions_uninit(&call->sessions[call->main_audio_stream_index]);
ms_media_stream_sessions_uninit(&call->sessions[call->main_video_stream_index]);
if (call->params->realtimetext_enabled) ms_media_stream_sessions_uninit(&call->sessions[call->main_text_stream_index]);
ms_media_stream_sessions_uninit(&call->sessions[call->main_text_stream_index]);
}
linphone_call_init_media_streams (call);
}
......@@ -791,7 +791,7 @@ static void call_terminated(SalOp *op, const char *from){
linphone_core_start_refered_call(lc,call,NULL);
}
//we stop the call only if we have this current call or if we are in call
if (lc->ringstream!=NULL && ( (ms_list_size(lc->calls) == 1) || linphone_core_in_call(lc) )) {
if ((ms_list_size(lc->calls) == 1) || linphone_core_in_call(lc)) {
linphone_core_stop_ringing(lc);
}
linphone_call_stop_media_streams(call);
......@@ -1065,7 +1065,15 @@ static void dtmf_received(SalOp *op, char dtmf){
static void refer_received(Sal *sal, SalOp *op, const char *referto){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal);
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
if (call){
LinphoneAddress *refer_to_addr = linphone_address_new(referto);
char method[20] = "";
if(refer_to_addr) {
const char *tmp = linphone_address_get_method_param(refer_to_addr);
if(tmp) strncpy(method, tmp, sizeof(method));
linphone_address_destroy(refer_to_addr);
}
if (call && (strlen(method) == 0 || strcmp(method, "INVITE") == 0)) {
if (call->refer_to!=NULL){
ms_free(call->refer_to);
}
......
......@@ -158,6 +158,7 @@ static int find_matching_vcard(LinphoneCardDavResponse *response, LinphoneFriend
LinphoneVCard *lvc2 = linphone_friend_get_vcard(lf);
const char *uid1 = linphone_vcard_get_uid(lvc1);
const char *uid2 = linphone_vcard_get_uid(lvc2);
linphone_vcard_free(lvc1);
if (!uid1 || !uid2) {
return 1;
}
......
/***************************************************************************
* conference.c
*
* Mon Sep 12, 2011
* Copyright 2011 Belledonne Communications
* Author: Simon Morlat
* Email simon dot morlat at linphone dot org
****************************************************************************/
/*
* 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 "private.h"
#include "lpconfig.h"
#include "mediastreamer2/msvolume.h"
/**
* @addtogroup conferencing
* @{
**/
static int convert_conference_to_call(LinphoneCore *lc);
static void conference_check_init(LinphoneConference *ctx, int samplerate){
if (ctx->conf==NULL){
MSAudioConferenceParams params;
params.samplerate=samplerate;
ctx->conf=ms_audio_conference_new(&params);
ctx->terminated=FALSE;
}
}
static void remove_local_endpoint(LinphoneConference *ctx){
if (ctx->local_endpoint){
ms_audio_conference_remove_member(ctx->conf,ctx->local_endpoint);
ms_audio_endpoint_release_from_stream(ctx->local_endpoint);
ctx->local_endpoint=NULL;
audio_stream_stop(ctx->local_participant);
ctx->local_participant=NULL;
rtp_profile_destroy(ctx->local_dummy_profile);
}
}
static int linphone_conference_get_size(LinphoneConference *conf){
if (conf->conf == NULL) {
return 0;
}
return ms_audio_conference_get_size(conf->conf) - (conf->record_endpoint ? 1 : 0);
}
static int remote_participants_count(LinphoneConference *ctx) {
int count=linphone_conference_get_size(ctx);
if (count==0) return 0;
if (!ctx->local_participant) return count;
return count -1;
}
void linphone_core_conference_check_uninit(LinphoneCore *lc){
LinphoneConference *ctx=&lc->conf_ctx;
if (ctx->conf){
int remote_count=remote_participants_count(ctx);
ms_message("conference_check_uninit(): size=%i",linphone_conference_get_size(ctx));
if (remote_count==1 && !ctx->terminated){
convert_conference_to_call(lc);
}
if (remote_count==0){
if (ctx->local_participant!=NULL)
remove_local_endpoint(ctx);
if (ctx->record_endpoint){
ms_audio_conference_remove_member(ctx->conf,ctx->record_endpoint);
ms_audio_endpoint_destroy(ctx->record_endpoint);
ctx->record_endpoint=NULL;
}
}
if (ms_audio_conference_get_size(ctx->conf)==0){
ms_audio_conference_destroy(ctx->conf);
ctx->conf=NULL;
}
}
}
void linphone_call_add_to_conf(LinphoneCall *call, bool_t muted){
LinphoneCore *lc=call->core;
LinphoneConference *conf=&lc->conf_ctx;
MSAudioEndpoint *ep;
call->params->has_video = FALSE;
call->camera_enabled = FALSE;
ep=ms_audio_endpoint_get_from_stream(call->audiostream,TRUE);
ms_audio_conference_add_member(conf->conf,ep);
ms_audio_conference_mute_member(conf->conf,ep,muted);
call->endpoint=ep;
}
void linphone_call_remove_from_conf(LinphoneCall *call){
LinphoneCore *lc=call->core;
LinphoneConference *conf=&lc->conf_ctx;
ms_audio_conference_remove_member(conf->conf,call->endpoint);
ms_audio_endpoint_release_from_stream(call->endpoint);
call->endpoint=NULL;
}
static RtpProfile *make_dummy_profile(int samplerate){
RtpProfile *prof=rtp_profile_new("dummy");
PayloadType *pt=payload_type_clone(&payload_type_l16_mono);
pt->clock_rate=samplerate;
rtp_profile_set_payload(prof,0,pt);
return prof;
}
static void add_local_endpoint(LinphoneConference *conf,LinphoneCore *lc){
/*create a dummy audiostream in order to extract the local part of it */
/* network address and ports have no meaning and are not used here. */
AudioStream *st=audio_stream_new(65000,65001,FALSE);
MSSndCard *playcard=lc->sound_conf.lsd_card ?
lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard;
MSSndCard *captcard=lc->sound_conf.capt_sndcard;
const MSAudioConferenceParams *params=ms_audio_conference_get_params(conf->conf);
conf->local_dummy_profile=make_dummy_profile(params->samplerate);
audio_stream_start_full(st, conf->local_dummy_profile,
"127.0.0.1",
65000,
"127.0.0.1",
65001,
0,
40,
NULL,
NULL,
playcard,
captcard,
linphone_core_echo_cancellation_enabled(lc)
);
_post_configure_audio_stream(st,lc,FALSE);
conf->local_participant=st;
conf->local_endpoint=ms_audio_endpoint_get_from_stream(st,FALSE);
ms_audio_conference_add_member(conf->conf,conf->local_endpoint);
}
/**
* Returns the sound volume (mic input) of the local participant of the conference.
* @param lc the linphone core
* @return the measured input volume expressed in dbm0.
**/
float linphone_core_get_conference_local_input_volume(LinphoneCore *lc){
LinphoneConference *conf=&lc->conf_ctx;
AudioStream *st=conf->local_participant;
if (st && st->volsend && !conf->local_muted){
float vol=0;
ms_filter_call_method(st->volsend,MS_VOLUME_GET,&vol);
return vol;
}
return LINPHONE_VOLUME_DB_LOWEST;
}
/**
* Merge a call into a conference.
* @param lc the linphone core
* @param call an established call, either in LinphoneCallStreamsRunning or LinphoneCallPaused state.
*
* If this is the first call that enters the conference, the virtual conference will be created automatically.
* If the local user was actively part of the call (ie not in paused state), then the local user is automatically entered into the conference.
* If the call was in paused state, then it is automatically resumed when entering into the conference.
*
* @return 0 if successful, -1 otherwise.
**/
int linphone_core_add_to_conference(LinphoneCore *lc, LinphoneCall *call){
LinphoneConference *conf=&lc->conf_ctx;
if (call->current_params->in_conference){
ms_error("Already in conference");
return -1;
}
conference_check_init(&lc->conf_ctx, lp_config_get_int(lc->config, "sound","conference_rate",16000));
if (call->state==LinphoneCallPaused){
call->params->in_conference=TRUE;
call->params->has_video=FALSE;
linphone_core_resume_call(lc,call);
}else if (call->state==LinphoneCallStreamsRunning){
LinphoneCallParams *params=linphone_call_params_copy(linphone_call_get_current_params(call));
params->in_conference=TRUE;
params->has_video=FALSE;
if (call->audiostream || call->videostream){
linphone_call_stop_media_streams(call); /*free the audio & video local resources*/
linphone_call_init_media_streams(call);
}
if (call==lc->current_call){
lc->current_call=NULL;
}
/*this will trigger a reINVITE that will later redraw the streams */
/*FIXME probably a bit too much to just redraw streams !*/
linphone_core_update_call(lc,call,params);
linphone_call_params_destroy(params);
add_local_endpoint(conf,lc);
}else{
ms_error("Call is in state %s, it cannot be added to the conference.",linphone_call_state_to_string(call->state));
return -1;
}
return 0;
}
static int remove_from_conference(LinphoneCore *lc, LinphoneCall *call, bool_t active){
int err=0;
char *str;
if (!call->current_params->in_conference){
if (call->params->in_conference){
ms_warning("Not (yet) in conference, be patient");
return -1;
}else{
ms_error("Not in a conference.");
return -1;
}
}
call->params->in_conference=FALSE;
str=linphone_call_get_remote_address_as_string(call);
ms_message("%s will be removed from conference", str);
ms_free(str);
if (active){
LinphoneCallParams *params=linphone_call_params_copy(linphone_call_get_current_params(call));
params->in_conference=FALSE;
// reconnect local audio with this call
if (linphone_core_is_in_conference(lc)){
ms_message("Leaving conference for reconnecting with unique call.");
linphone_core_leave_conference(lc);
}
ms_message("Updating call to actually remove from conference");
err=linphone_core_update_call(lc,call,params);
linphone_call_params_destroy(params);
} else{
ms_message("Pausing call to actually remove from conference");
err=_linphone_core_pause_call(lc,call);
}
return err;
}
static int convert_conference_to_call(LinphoneCore *lc){
int err=0;
MSList *calls=lc->calls;
if (remote_participants_count(&lc->conf_ctx)!=1){
ms_error("No unique call remaining in conference.");
return -1;
}
while (calls) {
LinphoneCall *rc=(LinphoneCall*)calls->data;
calls=calls->next;
if (rc->params->in_conference) { // not using current_param
bool_t active_after_removed=linphone_core_is_in_conference(lc);
err=remove_from_conference(lc, rc, active_after_removed);
break;
}
}
return err;
}
int linphone_core_remove_from_conference(LinphoneCore *lc, LinphoneCall *call){
int err;
char * str=linphone_call_get_remote_address_as_string(call);
ms_message("Removing call %s from the conference", str);
ms_free(str);
err=remove_from_conference(lc,call, FALSE);
if (err){
ms_error("Error removing participant from conference.");
return err;
}
if (remote_participants_count(&lc->conf_ctx)==1){
ms_message("conference size is 1: need to be converted to plain call");
err=convert_conference_to_call(lc);
} else {
ms_message("the conference need not to be converted as size is %i", remote_participants_count(&lc->conf_ctx));
}
return err;
}
bool_t linphone_core_is_in_conference(const LinphoneCore *lc){
return lc->conf_ctx.local_participant!=NULL;
}
/**
* Moves the local participant out of the conference.
* @param lc the linphone core
* When the local participant is out of the conference, the remote participants can continue to talk normally.
* @return 0 if successful, -1 otherwise.
**/
int linphone_core_leave_conference(LinphoneCore *lc){
LinphoneConference *conf=&lc->conf_ctx;
if (linphone_core_is_in_conference(lc))
remove_local_endpoint(conf);
return 0;
}
/**
* Moves the local participant inside the conference.
* @param lc the linphone core
*
* Makes the local participant to join the conference.
* Typically, the local participant is by default always part of the conference when joining an active call into a conference.
* However, by calling linphone_core_leave_conference() and linphone_core_enter_conference() the application can decide to temporarily
* move out and in the local participant from the conference.
*
* @return 0 if successful, -1 otherwise
**/
int linphone_core_enter_conference(LinphoneCore *lc){
LinphoneConference *conf;
if (linphone_core_sound_resources_locked(lc)) {
return -1;
}
if (lc->current_call != NULL) {
_linphone_core_pause_call(lc, lc->current_call);
}
conf=&lc->conf_ctx;
if (conf->local_participant==NULL) add_local_endpoint(conf,lc);
return 0;
}
/**
* Add all calls into a conference.
* @param lc the linphone core
*
* Merge all established calls (either in LinphoneCallStreamsRunning or LinphoneCallPaused) into a conference.
*
* @return 0 if successful, -1 otherwise
**/
int linphone_core_add_all_to_conference(LinphoneCore *lc) {
MSList *calls=lc->calls;
while (calls) {