diff --git a/console/commands.c b/console/commands.c index 27ea8dc5c..84639ada8 100644 --- a/console/commands.c +++ b/console/commands.c @@ -123,7 +123,7 @@ static int linphonec_friend_delete(LinphoneCore *lc, int num); static void linphonec_codec_list(int type, LinphoneCore *lc); static void linphonec_codec_enable(int type, LinphoneCore *lc, int index); static void linphonec_codec_disable(int type, LinphoneCore *lc, int index); - +static void lpc_display_call_states(LinphoneCore *lc); /* Command table management */ static LPC_COMMAND *lpc_find_command(const char *name); @@ -527,37 +527,6 @@ lpc_cmd_help(LinphoneCore *lc, char *arg) static char callee_name[256]={0}; static char caller_name[256]={0}; -static const char *get_call_status(LinphoneCall *call){ - switch(linphone_call_get_state(call)){ - case LinphoneCallPaused: - if (linphone_call_get_refer_to (call)!=NULL){ - return "Paused (transfered)"; - }else{ - return "Paused"; - } - break; - case LinphoneCallPausedByRemote: - return "Paused by remote"; - break; - case LinphoneCallIncomingReceived: - return "Pending"; - break; - case LinphoneCallOutgoingInit: - case LinphoneCallOutgoingProgress: - return "Dialing out"; - break; - case LinphoneCallOutgoingEarlyMedia: - case LinphoneCallOutgoingRinging: - return "Remote ringing"; - break; - default: - if (linphone_call_has_transfer_pending(call)){ - return "Running (transfer pending)"; - }else - return "Running"; - } - return ""; -} static int lpc_cmd_call(LinphoneCore *lc, char *args) @@ -603,19 +572,7 @@ lpc_cmd_calls(LinphoneCore *lc, char *args){ const MSList *calls = linphone_core_get_calls(lc); if(calls) { - const MSList *p_calls = calls; - linphonec_out("ID\t\tDestination\t\t\t\tStatus\n---------------------------------------------------------------------\n"); - while(p_calls != NULL) - { - LinphoneCall *call=(LinphoneCall*)p_calls->data; - char *tmp=linphone_call_get_remote_address_as_string(call); - linphonec_out("%li\t%s\t\t\t%s\r\n", - (long)linphone_call_get_user_pointer (call), - tmp, - get_call_status(call)); - p_calls = p_calls->next; - ms_free(tmp); - } + lpc_display_call_states(lc); }else { linphonec_out("No active call.\n"); @@ -1476,8 +1433,16 @@ static int lpc_cmd_conference(LinphoneCore *lc, char *args){ if (call==NULL) return 1; if (strcmp(subcommand,"add")==0){ linphone_core_add_to_conference(lc,call); + return 1; }else if (strcmp(subcommand,"rm")==0){ linphone_core_remove_from_conference(lc,call); + return 1; + }else if (strcmp(subcommand,"enter")==0){ + linphone_core_enter_conference(lc); + return 1; + }else if (strcmp(subcommand,"leave")==0){ + linphone_core_leave_conference(lc); + return 1; } } return 0; @@ -2425,19 +2390,21 @@ static void lpc_display_call_states(LinphoneCore *lc){ const MSList *elem; char *tmp; linphonec_out("Call states\n" - "Id | Destination | State\n" - "---------------------------------------------------------------\n"); + "Id | Destination | State | Flags |\n" + "------------------------------------------------------------------------\n"); elem=linphone_core_get_calls(lc); if (elem==NULL){ linphonec_out("(empty)\n"); }else{ for(;elem!=NULL;elem=elem->next){ + const char *flag; call=(LinphoneCall*)elem->data; bool_t in_conference=linphone_call_params_local_conference_mode(linphone_call_get_current_params(call)); tmp=linphone_call_get_remote_address_as_string (call); - linphonec_out("%-2i | %-35s | %s %s\n",(int)(long)linphone_call_get_user_pointer(call), - tmp,linphone_call_state_to_string(linphone_call_get_state(call)), - in_conference ? "(conferencing)" : ""); + flag=in_conference ? "conferencing" : ""; + flag=linphone_call_has_transfer_pending(call) ? "transfer pending" : flag; + linphonec_out("%-2i | %-35s | %-15s | %s\n",(int)(long)linphone_call_get_user_pointer(call), + tmp,linphone_call_state_to_string(linphone_call_get_state(call))+strlen("LinphoneCall"),flag); ms_free(tmp); } } diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index a101dbc8e..1f00b1995 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. static void register_failure(SalOp *op, SalError error, SalReason reason, const char *details); static bool_t media_parameters_changed(LinphoneCall *call, SalMediaDescription *oldmd, SalMediaDescription *newmd){ + if (call->params.in_conference!=call->current_params.in_conference) return TRUE; return !sal_media_description_equals(oldmd,newmd) || call->up_bw!=linphone_core_get_upload_bandwidth(call->core); } diff --git a/coreapi/conference.c b/coreapi/conference.c index e97f2588c..c1058233b 100644 --- a/coreapi/conference.c +++ b/coreapi/conference.c @@ -32,9 +32,20 @@ static void conference_check_init(LinphoneConference *ctx){ } } +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; + } +} + static void conference_check_uninit(LinphoneConference *ctx){ if (ctx->conf){ if (ctx->conf->nmembers==0){ + remove_local_endpoint(ctx); ms_audio_conference_destroy(ctx->conf); ctx->conf=NULL; } @@ -61,8 +72,36 @@ void linphone_call_remove_from_conf(LinphoneCall *call){ conference_check_uninit(conf); } +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,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; + + audio_stream_start_full(st, &av_profile, + "127.0.0.1", + 65000, + 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); +} + int linphone_core_add_to_conference(LinphoneCore *lc, LinphoneCall *call){ LinphoneCallParams params; + LinphoneConference *conf=&lc->conf_ctx; + if (call->current_params.in_conference){ ms_error("Already in conference"); return -1; @@ -75,7 +114,10 @@ int linphone_core_add_to_conference(LinphoneCore *lc, LinphoneCall *call){ linphone_core_resume_call(lc,call); else if (call->state==LinphoneCallStreamsRunning){ /*this will trigger a reINVITE that will later redraw the streams */ + if (call->audiostream || call->videostream) + linphone_call_stop_media_streams (call); /*free the audio & video local resources*/ linphone_core_update_call(lc,call,¶ms); + 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; @@ -97,12 +139,21 @@ int linphone_core_remove_from_conference(LinphoneCore *lc, LinphoneCall *call){ return linphone_core_pause_call(lc,call); } -int linphone_core_pause_conference(LinphoneCore *lc){ +bool_t linphone_core_is_in_conference(const LinphoneCore *lc){ + return lc->conf_ctx.local_participant!=NULL; +} + +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; } -int linphone_core_resume_conference(LinphoneCore *lc){ +int linphone_core_enter_conference(LinphoneCore *lc){ + LinphoneConference *conf=&lc->conf_ctx; + if (conf->local_participant==NULL) add_local_endpoint(conf,lc); return 0; } diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index a568b8ba9..085cde973 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -841,7 +841,7 @@ static void parametrize_equalizer(LinphoneCore *lc, AudioStream *st){ } } -static void _post_configure_audio_stream(AudioStream *st, LinphoneCore *lc, bool_t muted){ +void _post_configure_audio_stream(AudioStream *st, LinphoneCore *lc, bool_t muted){ float mic_gain=lp_config_get_float(lc->config,"sound","mic_gain",1); float thres = 0; float recv_gain; diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 1d985f544..b042a1398 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -2095,7 +2095,7 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const if (linphone_core_in_call(lc)){ if (lc->vtable.display_warning) - lc->vtable.display_warning(lc,_("Sorry, you have to pause or stop the current call first !")); + lc->vtable.display_warning(lc,_("Sorry, you have to pause or stop the current call or conference first !")); return NULL; } if(!linphone_core_can_we_add_call(lc)){ @@ -2454,7 +2454,7 @@ const MSList *linphone_core_get_calls(LinphoneCore *lc) * @ingroup call_control **/ bool_t linphone_core_in_call(const LinphoneCore *lc){ - return linphone_core_get_current_call((LinphoneCore *)lc)!=NULL; + return linphone_core_get_current_call((LinphoneCore *)lc)!=NULL || linphone_core_is_in_conference(lc); } /** diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index e0f3145ff..dbf698fad 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -1026,8 +1026,9 @@ bool_t linphone_call_get_authentication_token_verified(LinphoneCall *call); int linphone_core_add_to_conference(LinphoneCore *lc, LinphoneCall *call); int linphone_core_remove_from_conference(LinphoneCore *lc, LinphoneCall *call); -int linphone_core_pause_conference(LinphoneCore *lc); -int linphone_core_resume_conference(LinphoneCore *lc); +bool_t linphone_core_is_in_conference(const LinphoneCore *lc); +int linphone_core_enter_conference(LinphoneCore *lc); +int linphone_core_leave_conference(LinphoneCore *lc); #ifdef __cplusplus diff --git a/coreapi/private.h b/coreapi/private.h index e5ce1fd0d..bb1fb883b 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -506,6 +506,7 @@ void ec_calibrator_destroy(EcCalibrator *ecc); void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapsed); /*conferencing subsystem*/ +void _post_configure_audio_stream(AudioStream *st, LinphoneCore *lc, bool_t muted); void linphone_call_add_to_conf(LinphoneCall *call); void linphone_call_remove_from_conf(LinphoneCall *call);