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);
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)
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");
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;
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);
}
}
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);
}
}
}
+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;
}
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;
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;
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;
}
}
}
-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;
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)){
* @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);
}
/**
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
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);