to=sal_op_get_to(h);
call=linphone_call_new_incoming(lc,linphone_address_new(from),linphone_address_new(to),h);
- if(linphone_core_add_call(lc,call)!= 0)
- {
- ms_warning("we cannot have more calls\n");
- sal_call_decline(h,SalReasonMedia,NULL);
- linphone_call_unref(call);
- return;
- }
+
if(linphone_core_get_current_call(lc)!=NULL) //we are already in call just inform that an incoming call is going on
{
char temp[256];
- snprintf(temp,sizeof(temp),"A new incoming call from %s during call",from);
+ snprintf(temp,sizeof(temp)-1,"A new incoming call from %s during call",from);
lc->vtable.display_status(lc,temp);
}
sal_call_set_local_media_description(h,call->localdesc);
linphone_call_unref(call);
return;
}
+ /* the call is acceptable so we can now add it to our list */
+ linphone_core_add_call(lc,call);
from_parsed=linphone_address_new(sal_op_get_from(h));
linphone_address_clean(from_parsed);
lc->vtable.show(lc);
if (lc->vtable.display_status!=NULL)
lc->vtable.display_status(lc,_("Call terminated."));
- linphone_call_set_terminated(call);
+ call->state=LinphoneCallTerminated;
gstate_new_state(lc, GSTATE_CALL_END, NULL);
if (lc->vtable.bye_recv!=NULL){
LinphoneAddress *addr=linphone_address_new(from);
char *tmp;
linphone_address_clean(addr);
tmp=linphone_address_as_string(addr);
- lc->vtable.bye_recv(lc,call);
+ if (lc->vtable.bye_recv!=NULL)
+ lc->vtable.bye_recv(lc,call);
ms_free(tmp);
linphone_address_destroy(addr);
}
- linphone_call_unref(call);
+ linphone_call_set_terminated(call);
}
static void call_failure(SalOp *op, SalError error, SalReason sr, const char *details, int code){
if(call == linphone_core_get_current_call(lc))
linphone_core_stop_media_streams(lc,call);
if (call!=NULL) {
- linphone_call_set_terminated(call);
- linphone_call_unref(call);//TODO not an unref here ???//AUREL
if (sr!=SalReasonDeclined) gstate_new_state(lc, GSTATE_CALL_ERROR, msg);
else gstate_new_state(lc, GSTATE_CALL_END, NULL);
+ linphone_call_set_terminated(call);
}
}
return call;
}
+/* this function is called internally to get rid of a call.
+ It performs the following tasks:
+ - remove the call from the internal list of calls
+ - unref the LinphoneCall object
+ - update the call logs accordingly
+*/
+
void linphone_call_set_terminated(LinphoneCall *call){
LinphoneCallStatus status=LinphoneCallAborted;
+ LinphoneCore *lc=call->core;
+
+ if (ms_list_size(lc->calls)==0)
+ linphone_core_notify_all_friends(lc,lc->prev_mode);
+
+ linphone_core_update_allocated_audio_bandwidth(lc);
if (call->state==LinphoneCallAVRunning){
status=LinphoneCallSuccess;
+
}
linphone_call_log_completed(call->log,call, status);
call->state=LinphoneCallTerminated;
+ if (linphone_core_del_call(lc,call) != 0){
+ ms_error("could not remove the call from the list !!!");
+ }
+ if (call == linphone_core_get_current_call(lc)){
+ ms_message("destroying the current call\n");
+ linphone_core_unset_the_current_call(lc);
+ }
+ if (call->op!=NULL) {
+ /* so that we cannot have anymore upcalls for SAL
+ concerning this call*/
+ sal_op_release(call->op);
+ call->op=NULL;
+ }
+ linphone_call_unref(call);
}
static void linphone_call_destroy(LinphoneCall *obj)
{
- linphone_core_notify_all_friends(obj->core,obj->core->prev_mode);
-
- linphone_core_update_allocated_audio_bandwidth(obj->core);
if (obj->op!=NULL) {
sal_op_release(obj->op);
obj->op=NULL;
if (obj->ping_op) {
sal_op_release(obj->ping_op);
}
- if(linphone_core_del_call(obj->core,obj) != 0)
- {
- ms_error("could not remove the call from the list !!!");
- }
- if(obj == linphone_core_get_current_call(obj->core))
- {
- ms_message("destroying the current call\n");
- linphone_core_unset_the_current_call(obj->core);
- }
ms_free(obj);
}
+/**
+ * @addtogroup calls
+ * @{
+**/
+
+/**
+ * Increments the call 's reference count.
+ * An application that wishes to retain a pointer to call object
+ * must use this function to unsure the pointer remains
+ * valid. Once the application no more needs this pointer,
+ * it must call linphone_call_unref().
+**/
void linphone_call_ref(LinphoneCall *obj){
obj->refcnt++;
}
+/**
+ * Decrements the call object reference count.
+ * See linphone_call_ref().
+**/
void linphone_call_unref(LinphoneCall *obj){
obj->refcnt--;
if (obj->refcnt==0)
linphone_call_destroy(obj);
}
+/**
+ * Returns true if the call is paused.
+**/
bool_t linphone_call_paused(LinphoneCall *call){
return call->state==LinphoneCallPaused;
}
+/**
+ * Returns the remote address associated to this call
+ *
+**/
const LinphoneAddress * linphone_call_get_remote_address(const LinphoneCall *call){
return call->dir==LinphoneCallIncoming ? call->log->from : call->log->to;
}
+/**
+ * Returns the remote address associated to this call as a string.
+ *
+ * The result string must be freed by user using ms_free().
+**/
char *linphone_call_get_remote_address_as_string(const LinphoneCall *call){
return linphone_address_as_string(linphone_call_get_remote_address(call));
}
+/**
+ * Retrieves the call's current state.
+**/
LinphoneCallState linphone_call_get_state(const LinphoneCall *call){
return call->state;
}
{
call->user_pointer = user_pointer;
}
+
+/**
+ * @}
+**/
+
* serialized with a mutex.
**/
void linphone_core_iterate(LinphoneCore *lc){
- MSList *the_call;
+ MSList *calls;
LinphoneCall *call;
int disconnect_timeout = linphone_core_get_nortp_timeout(lc);
time_t curtime=time(NULL);
proxy_update(lc);
//we have to iterate for each call
- the_call = lc->calls;
- while(the_call != NULL)
- {
- call = (LinphoneCall *)the_call->data;
+ calls= lc->calls;
+ while(calls!= NULL){
+ call = (LinphoneCall *)calls->data;
+ /* get immediately a reference to next one in case the one
+ we are going to examine is destroy and removed during
+ linphone_core_start_invite() */
+ calls=calls->next;
if (call->state==LinphoneCallPreEstablishing && (curtime-call->start_time>=2)){
/*start the call even if the OPTIONS reply did not arrive*/
linphone_core_start_invite(lc,call,NULL);
linphone_core_terminate_call(lc,call);
}
}
-
- the_call = the_call->next;
- }//end while
- //and consider the current call
+ }
call = linphone_core_get_current_call(lc);
if(call)
{
lc->vtable.display_status(lc,_("could not call"));
if(call == linphone_core_get_current_call(lc))
linphone_core_stop_media_streams(lc,call);
- linphone_call_unref(call);
+ linphone_call_set_terminated (call);
}else gstate_new_state(lc, GSTATE_CALL_OUT_INVITE, real_url);
ms_free(real_url);
ms_free(from);
lc->vtable.display_status(lc,_("Call ended") );
gstate_new_state(lc, GSTATE_CALL_END, NULL);
linphone_call_set_terminated(call);
- linphone_call_unref(call);
return 0;
}
{
if(linphone_core_get_calls_nb(lc) < NB_MAX_CALLS)
return TRUE;
+ ms_error("Maximum amount of simultaneous calls reached !");
return FALSE;
}
if(linphone_core_can_we_add_call(lc))
{
MSList *the_calls = lc->calls;
- the_calls = ms_list_append(the_calls,(void *)call);
+ the_calls = ms_list_append(the_calls,call);
lc->calls = the_calls;
return 0;
}