static int lpc_cmd_help(LinphoneCore *, char *);
static int lpc_cmd_proxy(LinphoneCore *, char *);
static int lpc_cmd_call(LinphoneCore *, char *);
+static int lpc_cmd_calls(LinphoneCore *, char *);
static int lpc_cmd_chat(LinphoneCore *, char *);
static int lpc_cmd_answer(LinphoneCore *, char *);
static int lpc_cmd_autoanswer(LinphoneCore *, char *);
static int lpc_cmd_terminate(LinphoneCore *, char *);
static int lpc_cmd_call_logs(LinphoneCore *, char *);
static int lpc_cmd_ipv6(LinphoneCore *, char *);
-static int lpc_cmd_refer(LinphoneCore *, char *);
+static int lpc_cmd_transfer(LinphoneCore *, char *);
static int lpc_cmd_quit(LinphoneCore *, char *);
static int lpc_cmd_nat(LinphoneCore *, char *);
static int lpc_cmd_stun(LinphoneCore *, char *);
{ "help", lpc_cmd_help, "Print commands help", NULL },
{ "call", lpc_cmd_call, "Call a SIP uri",
"'call <sip-url>' \t: initiate a call to the specified destination.\n"
- "'call show' \t: show all the current calls status.\n"
+ "'call show' \t: show all the current calls with their id and status.\n"
+ },
+ { "calls", lpc_cmd_calls, "Show all the current calls with their id and status.\n",
+ NULL
},
{ "chat", lpc_cmd_chat, "Chat with a SIP uri",
"'chat <sip-url> \"message\"' "
},
{ "terminate", lpc_cmd_terminate, "Terminate a call",
"'terminate' : Terminate the current call\n"
- "'terminate <sip:XXX@XXX.XXX.XXX.XXX>' : Terminate the call with remote address\n"
+ "'terminate <call id>' : Terminate the call with supplied id\n"
"'terminate <all>' : Terminate all the current calls\n"
},
{ "answer", lpc_cmd_answer, "Answer a call",
"'answer' : Answer the current incoming call\n"
- "'answer <sip:XXX@XXX.XXX.XXX.XXX>' : Answer the call with remote address\n"
+ "'answer <call id>' : Answer the call with given id\n"
},
{ "autoanswer", lpc_cmd_autoanswer, "Show/set auto-answer mode",
"'autoanswer' \t: show current autoanswer mode\n"
"'ipv6 enable' : enable the use of the ipv6 network.\n"
"'ipv6 disable' : do not use ipv6 network."
},
- { "refer", lpc_cmd_refer,
- "Refer the current call to the specified destination.",
- "'refer <sip-url>' or 'r <sip-url>' "
- ": refer the current call to the specified destination."
+ { "transfer", lpc_cmd_transfer,
+ "Transfer a call to a specified destination.",
+ "'transfer <sip-uri>' : transfers the current active call to the destination sip-uri"
+ "'transfer <call id> <sip-uri>': transfers the call with 'id' to the destination sip-uri"
},
{ "nat", lpc_cmd_nat, "Set nat address",
"'nat' : show nat settings.\n"
"'pause' : pause the current call\n"},
{ "resume", lpc_cmd_resume, "resume a call",
"'resume' : resume the unique call\n"
- "'resume <sip:XXX@XXX.XXX.XXX.XXX>' : hold off the call with cid <cid>\n"},
+ "'resume <call id>' : hold off the call with given id\n"},
{ "mute", lpc_cmd_mute_mic,
"Mute microphone and suspend voice transmission."},
{ "unmute", lpc_cmd_unmute_mic,
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 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)
{
{
return 0;
}
- if(!strcmp(args,"show"))
- {
- const MSList *calls = linphone_core_get_calls(lc);
- if(calls)
- {
- const MSList *p_calls = calls;
- linphonec_out("<remote>\t\t\t\t<status>\r\n");
- while(p_calls != NULL)
- {
- char *tmp=linphone_call_get_remote_address_as_string(p_calls->data);
- linphonec_out("%s\t\t\t%s\r\n",
- tmp,
- (((LinphoneCall *)p_calls->data)==linphone_core_get_current_call(lc))?"yes":"no");
- p_calls = p_calls->next;
- ms_free(tmp);
- }
- }
- else
- {
- linphonec_out("No active call.\n");
- }
- }
- else
{
+ LinphoneCall *call;
if ( linphone_core_in_call(lc) )
{
linphonec_out("Terminate or hold on the current call first.\n");
return 1;
}
- if ( NULL == linphone_core_invite(lc, args) )
+ if ( NULL == (call=linphone_core_invite(lc, args)) )
{
linphonec_out("Error from linphone_core_invite.\n");
}
return 1;
}
+static int
+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);
+ }
+ }else
+ {
+ linphonec_out("No active call.\n");
+ }
+ return 1;
+}
+
+
static int
lpc_cmd_chat(LinphoneCore *lc, char *args)
{
}
static int
-lpc_cmd_refer(LinphoneCore *lc, char *args)
+lpc_cmd_transfer(LinphoneCore *lc, char *args)
{
- if (args)
- linphone_core_refer(lc, linphone_core_get_current_call(lc), args);
- else{
- linphonec_out("refer needs an argument\n");
+ if (args){
+ LinphoneCall *call;
+ const char *refer_to=NULL;
+ char arg1[256]={0};
+ char arg2[266]={0};
+ int n=sscanf(args,"%s %s",arg1,arg2);
+ if (n==1 || isalpha(*arg1)){
+ call=linphone_core_get_current_call(lc);
+ if (call==NULL && linphone_core_get_calls_nb (lc)==1){
+ call=(LinphoneCall*)linphone_core_get_calls(lc)->data;
+ }
+ refer_to=args;
+ if (call==NULL){
+ linphonec_out("No active call, please specify a call id among the ones listed by 'calls' command.\n");
+ return 0;
+ }
+ }else{
+ long id=atoi(arg1);
+ refer_to=args+strlen(arg1)+1;
+ call=linphonec_get_call(id);
+ if (call==NULL) return 0;
+ }
+ linphone_core_transfer_call(lc, call, refer_to);
+ }else{
+ linphonec_out("Transfer command requires at least one argument\n");
+ return 0;
}
return 1;
}
static int
lpc_cmd_terminate(LinphoneCore *lc, char *args)
{
- char *arg1 = args;
- char *arg2 = NULL;
- char *ptr = args;
-
+ if (linphone_core_get_calls(lc)==NULL){
+ linphonec_out("No active calls");
+ return 1;
+ }
if (!args)
{
- if(linphone_core_in_call(lc))
- {
- if ( -1 == linphone_core_terminate_call(lc, linphone_core_get_current_call(lc)) )
- {
- linphonec_out("Could not stop the active call.\n");
- }
- }
- else
- {
- linphonec_out("No active call.\n");
+ if ( -1 == linphone_core_terminate_call(lc, NULL) ){
+ linphonec_out("Could not stop the active call.\n");
}
return 1;
}
- /* Isolate first and second arg */
- while(*ptr && !isspace(*ptr)) ++ptr;
- if ( *ptr )
- {
- *ptr='\0';
- arg2=ptr+1;
- while(*arg2 && isspace(*arg2)) ++arg2;
- }
- if (arg1 != 0)
- {
- if(strcmp(arg1,"all")==0)
- {
- linphonec_out("We are going to stop all the calls.\n");
- return (linphone_core_terminate_all_calls(lc)==0)?1:0;
- }
- else
- {
- char the_remote_address[255];
- int n = sscanf(arg1, "%s", the_remote_address);
- if (n == 1)
- {
- if ( -1 == linphone_core_terminate_call(lc,linphone_core_get_call_by_remote_address(lc,the_remote_address)))
- {
- linphonec_out("Cannot stop the call with %s.\n",the_remote_address);
- }
- return 1;
+ if(strcmp(args,"all")==0){
+ linphonec_out("We are going to stop all the calls.\n");
+ linphone_core_terminate_all_calls(lc);
+ return 1;
+ }else{
+ /*the argument is a linphonec call id */
+ long id=atoi(args);
+ LinphoneCall *call=linphonec_get_call(id);
+ if (call){
+ if (linphone_core_terminate_call(lc,call)==-1){
+ linphonec_out("Could not stop the call with id %li",id);
}
- }
+ }else return 0;
+ return 1;
}
return 0;
}
static int
-lpc_cmd_answer(LinphoneCore *lc, char *args)
-{
- char *arg1 = args;
- char *arg2 = NULL;
- char *ptr = args;
-
+lpc_cmd_answer(LinphoneCore *lc, char *args){
if (!args)
{
- //if just one call is present answer the only one in passing NULL to the linphone_core_accept_call ...
- if ( -1 == linphone_core_accept_call(lc, NULL) )
- {
- linphonec_out("No incoming call.\n");
- }
- return 1;
- }
-
- // Isolate first and second arg
- while(*ptr && !isspace(*ptr)) ++ptr;
- if ( *ptr )
- {
- *ptr='\0';
- arg2=ptr+1;
- while(*arg2 && isspace(*arg2)) ++arg2;
- }
- if (arg1 != 0)
- {
- char the_remote_address[256];
- int n = sscanf(arg1, "%s", the_remote_address);
- if (n == 1)
- {
- if ( -1 == linphone_core_accept_call(lc, linphone_core_get_call_by_remote_address(lc,the_remote_address)) )
+ int nb=ms_list_size(linphone_core_get_calls(lc));
+ if (nb==1){
+ //if just one call is present answer the only one in passing NULL to the linphone_core_accept_call ...
+ if ( -1 == linphone_core_accept_call(lc, NULL) )
{
- linphonec_out("Cannot answer the call from %s.\n",the_remote_address);
+ linphonec_out("Fail to accept incoming call\n");
}
- return 1;
+ }else if (nb==0){
+ linphonec_out("There are no calls to answer.\n");
+ }else{
+ linphonec_out("Multiple calls in progress, please specify call id.\n");
+ return 0;
}
+ return 1;
+ }else{
+ long id;
+ if (sscanf(args,"%li",&id)==1){
+ LinphoneCall *call=linphonec_get_call (id);
+ if (linphone_core_accept_call (lc,call)==-1){
+ linphonec_out("Fail to accept call %i\n",id);
+ }
+ }else return 0;
+ return 1;
}
return 0;
}
if(linphone_core_in_call(lc))
{
linphonec_out("There is already a call in process pause or stop it first");
+ return 1;
}
if (args)
{
- char the_remote_address[255];
- int n = sscanf(args, "%s", the_remote_address);
- if (n == 1)
- {
- if(linphone_core_resume_call(lc,linphone_core_get_call_by_remote_address(lc,the_remote_address)) < 0)
- {
- linphonec_out("There was a problem to resume the call check the remote address you gave %s\n",args);
- return 0;
- }
- else
+ long id;
+ int n = sscanf(args, "%li", &id);
+ if (n == 1){
+ LinphoneCall *call=linphonec_get_call (id);
+ if (call){
+ if(linphone_core_resume_call(lc,call)==-1)
+ {
+ linphonec_out("There was a problem to resume the call check the remote address you gave %s\n",args);
+ return 1;
+ }
+ }else
{
return 1;
}
- }
+ }else return 0;
}
else
{
- int returned = 0;
const MSList *calls = linphone_core_get_calls(lc);
- if(ms_list_size(calls) == 1)
+ int nbcalls=ms_list_size(calls);
+ if( nbcalls == 1)
{
if(linphone_core_resume_call(lc,calls->data) < 0)
{
- linphonec_out("There was a problem to resume the unique call \n");
- returned = 0;
- }
- else
- {
- returned = 1;
+ linphonec_out("There was a problem to resume the unique call.\n");
}
- return returned;
+ return 1;
+ }else if (nbcalls==0){
+ linphonec_out("There is no calls at this time.\n");
+ return 1;
+ }else{
+ linphonec_out("There are %i calls at this time, please specify call id as given with 'calls' command.\n");
}
}
return 0;
static void linphonec_display_something (LinphoneCore * lc, const char *something);
static void linphonec_display_url (LinphoneCore * lc, const char *something, const char *url);
static void linphonec_display_warning (LinphoneCore * lc, const char *something);
-static void linphonec_notify_received(LinphoneCore *lc,const char *from,const char *msg);
+static void linphonec_notify_received(LinphoneCore *lc, LinphoneCall *call, const char *from,const char *event);
static void linphonec_notify_presence_received(LinphoneCore *lc,LinphoneFriend *fid);
static void linphonec_new_unknown_subscriber(LinphoneCore *lc,
#endif /*_WIN32_WCE*/
+void linphonec_call_identify(LinphoneCall* call){
+ static long callid=1;
+ linphone_call_set_user_pointer (call,(void*)callid);
+ callid++;
+}
+
+LinphoneCall *linphonec_get_call(long id){
+ const MSList *elem=linphone_core_get_calls(linphonec);
+ for (;elem!=NULL;elem=elem->next){
+ LinphoneCall *call=(LinphoneCall*)elem->data;
+ if (linphone_call_get_user_pointer (call)==(void*)id){
+ return call;
+ }
+ }
+ linphonec_out("Sorry, no call with id %i exists at this time.",id);
+ return NULL;
+}
+
/***************************************************************************
*
* Linphone core callbacks
* Linphone core callback
*/
static void
-linphonec_notify_received(LinphoneCore *lc,const char *from,const char *msg)
+linphonec_notify_received(LinphoneCore *lc, LinphoneCall *call, const char *from,const char *event)
{
- printf("Notify type %s from %s\n", msg, from);
- if(!strcmp(msg,"refer"))
+ if(!strcmp(event,"refer"))
{
- printf("The distant SIP end point get the refer we can close the call\n");
- linphonec_parse_command_line(linphonec, "terminate");
+ linphonec_out("The distand endpoint %s of call %li has been transfered, you can safely close the call.\n",
+ from,(long)linphone_call_get_user_pointer (call));
}
}
static void linphonec_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState st, const char *msg){
char *from=linphone_call_get_remote_address_as_string(call);
+ long id=(long)linphone_call_get_user_pointer (call);
switch(st){
case LinphoneCallEnd:
- printf("Call with %s ended.\n", from);
+ linphonec_out("Call %i with %s ended.\n", id, from);
break;
case LinphoneCallResuming:
- printf("Resuming call with %s.\n", from);
+ linphonec_out("Resuming call %i with %s.\n", id, from);
break;
case LinphoneCallStreamsRunning:
- printf("Media streams established with %s.\n", from);
+ linphonec_out("Media streams established with %s for call %i.\n", from,id);
break;
case LinphoneCallPausing:
- printf("Pausing call with %s.\n", from);
+ linphonec_out("Pausing call %i with %s.\n", id, from);
break;
case LinphoneCallPaused:
- printf("Call with %s is now paused.\n", from);
+ linphonec_out("Call %i with %s is now paused.\n", id, from);
break;
case LinphoneCallIncomingReceived:
+ linphonec_call_identify(call);
+ id=(long)linphone_call_get_user_pointer (call);
linphonec_set_caller(from);
if ( auto_answer) {
answer_call=TRUE;
}
+ linphonec_out("Receiving new incoming call from %s, assigned id %i", from,id);
+ break;
+ case LinphoneCallOutgoingInit:
+ linphonec_call_identify(call);
break;
default:
break;
void
linphonec_finish(int exit_status)
{
- printf("Terminating...\n");
+ linphonec_out("Terminating...\n");
/* Terminate any pending call */
- linphonec_parse_command_line(linphonec, "terminate");
- linphonec_command_finished();
+ linphone_core_terminate_all_calls(linphonec);
#ifdef HAVE_READLINE
linphonec_finish_readline();
#endif
bool_t linphonec_get_autoanswer();
void linphonec_command_finished(void);
void linphonec_set_caller(const char *caller);
+LinphoneCall *linphonec_get_call(long id);
+void linphonec_call_identify(LinphoneCall* call);
#endif /* def LINPHONEC_H */
if (lc->vtable.display_status)
lc->vtable.display_status(lc,barmesg);
- /* play the ring */
- if (lc->sound_conf.ring_sndcard!=NULL && !linphone_core_in_call(lc)){
+ /* play the ring if this is the only call*/
+ if (lc->sound_conf.ring_sndcard!=NULL && ms_list_size(lc->calls)==1){
if(lc->ringstream==NULL){
MSSndCard *ringcard=lc->sound_conf.lsd_card ?lc->sound_conf.lsd_card : lc->sound_conf.ring_sndcard;
ms_message("Starting local ring...");
{
ms_message("the local ring is already started");
}
+ }else{
+ /*TODO : play a tone within the context of the current call */
}
sal_call_notify_ringing(h);
#if !(__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000)
ms_free(msg);
}
linphone_call_set_state(call,LinphoneCallPaused,"Call paused");
+ }else if (sal_media_description_has_dir(call->resultdesc,SalStreamRecvOnly)){
+ /*we are put on hold when the call is initially accepted */
+ if (lc->vtable.display_status){
+ char *tmp=linphone_call_get_remote_address_as_string (call);
+ char *msg=ms_strdup_printf(_("Call answered by %s - on hold."),tmp);
+ lc->vtable.display_status(lc,msg);
+ ms_free(tmp);
+ ms_free(msg);
+ }
+ linphone_call_set_state(call,LinphoneCallPaused,"Call paused");
}else{
linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)");
}
}
/* this callback is called when an incoming re-INVITE modifies the session*/
-static void call_updated(SalOp *op){
+static void call_updating(SalOp *op){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
if (call->resultdesc)
{
if (call->state==LinphoneCallPaused &&
sal_media_description_has_dir(call->resultdesc,SalStreamSendRecv) && strcmp(call->resultdesc->addr,"0.0.0.0")!=0){
+ /*make sure we can be resumed */
+ if (lc->current_call!=NULL && lc->current_call!=call){
+ ms_warning("Attempt to be resumed but already in call with somebody else!");
+ /*we are actively running another call, reject with a busy*/
+ sal_call_decline (op,SalReasonBusy,NULL);
+ return;
+ }
if(lc->vtable.display_status)
lc->vtable.display_status(lc,_("We have been resumed..."));
linphone_call_set_state (call,LinphoneCallStreamsRunning,"Connected (streams running)");
if(lc->vtable.display_status)
lc->vtable.display_status(lc,_("We are being paused..."));
linphone_call_set_state (call,LinphoneCallPaused,"Call paused");
+ if (lc->current_call!=call){
+ ms_error("Inconsitency detected: current call is %p but call %p is being paused !",lc->current_call,call);
+ }
+ lc->current_call=NULL;
}
-
+ /*accept the modification (sends a 200Ok)*/
+ sal_call_accept(op);
linphone_call_stop_media_streams (call);
linphone_call_init_media_streams (call);
linphone_call_start_media_streams (call);
}
+ if (lc->current_call==NULL) linphone_core_start_pending_refered_calls (lc);
}
static void call_terminated(SalOp *op, const char *from){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal);
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
if (call){
+ if (call->refer_to!=NULL){
+ ms_free(call->refer_to);
+ }
+ call->refer_to=ms_strdup(referto);
+ call->refer_pending=TRUE;
linphone_call_set_state(call,LinphoneCallRefered,"Refered");
if (lc->vtable.display_status){
char *msg=ms_strdup_printf(_("We are transferred to %s"),referto);
lc->vtable.display_status(lc,msg);
ms_free(msg);
}
+ if (lc->current_call==NULL) linphone_core_start_pending_refered_calls (lc);
sal_refer_accept(op);
}else if (lc->vtable.refer_received){
lc->vtable.refer_received(lc,referto);
static void notify(SalOp *op, const char *from, const char *msg){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
-
+ LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer (op);
ms_message("get a %s notify from %s",msg,from);
if(lc->vtable.notify_recv)
- lc->vtable.notify_recv(lc,from,msg);
+ lc->vtable.notify_recv(lc,call,from,msg);
}
static void notify_presence(SalOp *op, SalSubscribeState ss, SalPresenceStatus status, const char *msg){
call_ringing,
call_accepted,
call_ack,
- call_updated,
+ call_updating,
call_terminated,
call_failure,
auth_requested,
MSList *elem;
int audio_port;
bool_t already_used=FALSE;
- for(offset=0;offset<100;++offset){
+ for(offset=0;offset<100;offset+=2){
audio_port=linphone_core_get_audio_port (lc)+offset;
already_used=FALSE;
for(elem=lc->calls;elem!=NULL;elem=elem->next){
}
linphone_call_log_completed(call->log,call, status);
- if (linphone_core_del_call(lc,call) != 0){
- ms_error("Could not remove the call from the list !!!");
- }
+
if (call == lc->current_call){
ms_message("Resetting the current call");
lc->current_call=NULL;
+ linphone_core_start_pending_refered_calls(lc);
+ }
+
+ if (linphone_core_del_call(lc,call) != 0){
+ ms_error("Could not remove the call from the list !!!");
}
+
if (ms_list_size(lc->calls)==0)
linphone_core_notify_all_friends(lc,lc->presence_mode);
void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message){
LinphoneCore *lc=call->core;
if (call->state!=cstate){
- call->state=cstate;
+ if (cstate!=LinphoneCallRefered){
+ /*LinphoneCallRefered is rather an event, not a state.
+ Indeed it does not change the state of the call (still paused or running)*/
+ call->state=cstate;
+ }
if (lc->vtable.call_state_changed)
lc->vtable.call_state_changed(lc,call,cstate,message);
}
if (obj->ping_op) {
sal_op_release(obj->ping_op);
}
+ if (obj->refer_to){
+ ms_free(obj->refer_to);
+ }
ms_free(obj);
}
}
/**
- * Returns the refer-to uri (if the call received was transfered).
+ * Returns the refer-to uri (if the call was transfered).
**/
const char *linphone_call_get_refer_to(const LinphoneCall *call){
return call->refer_to;
return call->log->dir;
}
+/**
+ * Returns true if this calls has received a transfer that has not been
+ * executed yet.
+ * Pending transfers are executed when this call is being paused or closed,
+ * locally or by remote endpoint.
+ * If the call is already paused while receiving the transfer request, the
+ * transfer immediately occurs.
+**/
+bool_t linphone_call_has_transfer_pending(const LinphoneCall *call){
+ return call->refer_pending;
+}
+
/**
* @}
**/
call = linphone_core_get_current_call(lc);
if(call)
{
- if (call->state==LinphoneCallConnected)
+ if (one_second_elapsed)
{
- if (one_second_elapsed)
- {
- RtpSession *as=NULL,*vs=NULL;
- lc->prevtime=curtime;
- if (call->audiostream!=NULL)
- as=call->audiostream->session;
- if (call->videostream!=NULL)
- vs=call->videostream->session;
- display_bandwidth(as,vs);
- }
-#ifdef VIDEO_ENABLED
+ RtpSession *as=NULL,*vs=NULL;
+ lc->prevtime=curtime;
+ if (call->audiostream!=NULL)
+ as=call->audiostream->session;
if (call->videostream!=NULL)
- video_stream_iterate(call->videostream);
-#endif
- if (call->audiostream!=NULL && disconnect_timeout>0)
- disconnected=!audio_stream_alive(call->audiostream,disconnect_timeout);
+ vs=call->videostream->session;
+ display_bandwidth(as,vs);
}
+#ifdef VIDEO_ENABLED
+ if (call->videostream!=NULL)
+ video_stream_iterate(call->videostream);
+#endif
+ if (call->audiostream!=NULL && disconnect_timeout>0)
+ disconnected=!audio_stream_alive(call->audiostream,disconnect_timeout);
}
if (linphone_core_video_preview_enabled(lc)){
if (lc->previewstream==NULL && lc->calls==NULL)
return returned;
}
+void linphone_core_start_pending_refered_calls(LinphoneCore *lc){
+ MSList *elem;
+ for(elem=lc->calls;elem!=NULL;elem=elem->next){
+ LinphoneCall *call=(LinphoneCall*)elem->data;
+ if (call->refer_pending){
+ ms_message("Starting new call to refered address %s",call->refer_to);
+ call->refer_pending=FALSE;
+ linphone_core_invite(lc,call->refer_to);
+ break;
+ }
+ }
+}
+
LinphoneProxyConfig * linphone_core_lookup_known_proxy(LinphoneCore *lc, const LinphoneAddress *uri){
const MSList *elem;
LinphoneProxyConfig *found_cfg=NULL;
return call;
}
-int linphone_core_refer(LinphoneCore *lc, LinphoneCall *call, const char *url)
+/**
+ * Performs a simple call transfer to the specified destination.
+ *
+ * The remote endpoint is expected to issue a new call to the specified destination.
+ * The current call remains active and thus can be later paused or terminated.
+**/
+int linphone_core_transfer_call(LinphoneCore *lc, LinphoneCall *call, const char *url)
{
char *real_url=NULL;
LinphoneAddress *real_parsed_url=linphone_core_interpret_url(lc,url);
real_url=linphone_address_as_string (real_parsed_url);
sal_refer(call->op,real_url);
ms_free(real_url);
+ linphone_address_destroy(real_parsed_url);
return 0;
}
MSList *elem;
for(elem=lc->calls;elem!=NULL;elem=elem->next){
LinphoneCall *c=(LinphoneCall*)elem->data;
- if (c!=call && (c->state!=LinphoneCallPaused || c->state!=LinphoneCallPausing)){
+ if (c!=call && (c->state!=LinphoneCallPaused)){
ms_warning("Cannot accept this call as another one is running, pause it before.");
return -1;
}
LinphoneCall *call;
if (the_call == NULL){
call = linphone_core_get_current_call(lc);
- if(call == NULL){
- ms_warning("No currently active call to terminate !");
+ if (ms_list_size(lc->calls)==1){
+ call=(LinphoneCall*)lc->calls->data;
+ }else{
+ ms_warning("No unique call to terminate !");
return -1;
}
}
if (lc->vtable.display_status)
lc->vtable.display_status(lc,_("Pausing the current call..."));
lc->current_call=NULL;
+ linphone_core_start_pending_refered_calls(lc);
return 0;
}
void linphone_call_unref(LinphoneCall *call);
LinphoneCallLog *linphone_call_get_call_log(const LinphoneCall *call);
const char *linphone_call_get_refer_to(const LinphoneCall *call);
+bool_t linphone_call_has_transfer_pending(const LinphoneCall *call);
void *linphone_call_get_user_pointer(LinphoneCall *call);
void linphone_call_set_user_pointer(LinphoneCall *call, void *user_pointer);
/** Callback prototype */
typedef void (*LinphoneCoreCbFunc)(struct _LinphoneCore *lc,void * user_data);
/** Callback prototype */
-typedef void (*NotifyReceivedCb)(struct _LinphoneCore *lc, const char *from, const char *msg);
+typedef void (*NotifyReceivedCb)(struct _LinphoneCore *lc, LinphoneCall *call, const char *from, const char *event);
/** Callback prototype */
typedef void (*NotifyPresenceReceivedCb)(struct _LinphoneCore *lc, LinphoneFriend * fid);
/** Callback prototype */
LinphoneCall * linphone_core_invite_address(LinphoneCore *lc, const LinphoneAddress *addr);
-int linphone_core_refer(LinphoneCore *lc, LinphoneCall *call, const char *url);
+int linphone_core_transfer_call(LinphoneCore *lc, LinphoneCall *call, const char *refer_to);
bool_t linphone_core_inc_invite_pending(LinphoneCore*lc);
struct _AudioStream *audiostream; /**/
struct _VideoStream *videostream;
char *refer_to;
+ bool_t refer_pending;
bool_t media_pending;
bool_t audio_muted;
};
void linphone_core_stop_waiting(LinphoneCore *lc);
int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, LinphoneProxyConfig *dest_proxy);
-
+void linphone_core_start_pending_refered_calls(LinphoneCore *lc);
extern SalCallbacks linphone_sal_callbacks;
typedef void (*SalOnCallRinging)(SalOp *op);
typedef void (*SalOnCallAccepted)(SalOp *op);
typedef void (*SalOnCallAck)(SalOp *op);
-typedef void (*SalOnCallUpdated)(SalOp *op);
+typedef void (*SalOnCallUpdating)(SalOp *op);/*< Called when a reINVITE is received*/
typedef void (*SalOnCallTerminated)(SalOp *op, const char *from);
typedef void (*SalOnCallFailure)(SalOp *op, SalError error, SalReason reason, const char *details, int code);
typedef void (*SalOnAuthRequested)(SalOp *op, const char *realm, const char *username);
SalOnCallRinging call_ringing;
SalOnCallAccepted call_accepted;
SalOnCallAck call_ack;
- SalOnCallUpdated call_updated;
+ SalOnCallUpdating call_updating;
SalOnCallTerminated call_terminated;
SalOnCallFailure call_failure;
SalOnAuthRequested auth_requested;
int sal_call_set_local_media_description(SalOp *h, SalMediaDescription *desc);
int sal_call(SalOp *h, const char *from, const char *to);
int sal_call_notify_ringing(SalOp *h);
+/*accept an incoming call or, during a call accept a reINVITE*/
int sal_call_accept(SalOp*h);
int sal_call_decline(SalOp *h, SalReason reason, const char *redirection /*optional*/);
int sal_call_hold(SalOp *h, bool_t holdon);
ctx->callbacks.call_failure=(SalOnCallFailure)unimplemented_stub;
if (ctx->callbacks.call_terminated==NULL)
ctx->callbacks.call_terminated=(SalOnCallTerminated)unimplemented_stub;
- if (ctx->callbacks.call_updated==NULL)
- ctx->callbacks.call_updated=(SalOnCallUpdated)unimplemented_stub;
+ if (ctx->callbacks.call_updating==NULL)
+ ctx->callbacks.call_updating=(SalOnCallUpdating)unimplemented_stub;
if (ctx->callbacks.auth_requested==NULL)
ctx->callbacks.auth_requested=(SalOnAuthRequested)unimplemented_stub;
if (ctx->callbacks.auth_success==NULL)
sal_media_description_unref(op->base.remote_media);
op->base.remote_media=NULL;
}
- eXosip_lock();
- eXosip_call_build_answer(ev->tid,200,&msg);
- eXosip_unlock();
- if (msg==NULL) return;
- if (op->base.root->session_expires!=0){
- if (op->supports_session_timers) osip_message_set_supported(msg, "timer");
- }
- if (op->base.contact){
- _osip_list_set_empty(&msg->contacts,(void (*)(void*))osip_contact_free);
- osip_message_set_contact(msg,op->base.contact);
+ if (op->result){
+ sal_media_description_unref(op->result);
+ op->result=NULL;
}
if (sdp){
op->sdp_offering=FALSE;
op->base.remote_media=sal_media_description_new();
sdp_to_media_description(sdp,op->base.remote_media);
sdp_message_free(sdp);
- sdp_process(op);
- if (op->sdp_answer!=NULL){
- set_sdp(msg,op->sdp_answer);
- sdp_message_free(op->sdp_answer);
- op->sdp_answer=NULL;
- }
+ sal->callbacks.call_updating(op);
}else {
op->sdp_offering=TRUE;
- set_sdp_from_desc(msg,op->base.local_media);
+ eXosip_lock();
+ eXosip_call_build_answer(ev->tid,200,&msg);
+ if (msg!=NULL){
+ set_sdp_from_desc(msg,op->base.local_media);
+ eXosip_call_send_answer(ev->tid,200,msg);
+ }
+ eXosip_unlock();
}
- eXosip_lock();
- eXosip_call_send_answer(ev->tid,200,msg);
- eXosip_unlock();
+
}
static void handle_ack(Sal *sal, eXosip_event_t *ev){
sdp_message_free(sdp);
}
if (op->reinvite){
- sal->callbacks.call_updated(op);
+ if (sdp) sal->callbacks.call_updating(op);
op->reinvite=FALSE;
}else{
sal->callbacks.call_ack(op);
-Subproject commit 236222b3f08baf502742b6c75633f50e3a14917f
+Subproject commit 6cc9076b9cc4d6b88e7a0b93e6abdd1ad881e832
-Subproject commit a084620745b1b1c81ec93501ffbb3de373f7c8c9
+Subproject commit d2a8cb0890c7547703a092c839c55db10449ef92
mediastreamer2/src/chanadapt.c
mediastreamer2/src/itc.c
mediastreamer2/src/extdisplay.c
+mediastreamer2/src/msiounit.c
+