diff --git a/console/commands.c b/console/commands.c
index 3abe0fb68..816135687 100644
--- a/console/commands.c
+++ b/console/commands.c
@@ -413,6 +413,9 @@ static const char *get_call_status(LinphoneCall *call){
return "Paused";
}
break;
+ case LinphoneCallPausedByRemote:
+ return "Paused by remote";
+ break;
case LinphoneCallIncomingReceived:
return "Pending";
break;
diff --git a/console/linphonec.c b/console/linphonec.c
index df86abb8f..75121db61 100644
--- a/console/linphonec.c
+++ b/console/linphonec.c
@@ -325,6 +325,9 @@ static void linphonec_call_state_changed(LinphoneCore *lc, LinphoneCall *call, L
case LinphoneCallPaused:
linphonec_out("Call %i with %s is now paused.\n", id, from);
break;
+ case LinphoneCallPausedByRemote:
+ linphonec_out("Call %i has been paused by %s.\n",id,from);
+ break;
case LinphoneCallIncomingReceived:
linphonec_call_identify(call);
id=(long)linphone_call_get_user_pointer (call);
diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c
index 8cbccc7c3..c96207251 100644
--- a/coreapi/callbacks.c
+++ b/coreapi/callbacks.c
@@ -277,7 +277,7 @@ static void call_updating(SalOp *op){
if (call->resultdesc && !sal_media_description_empty(call->resultdesc))
{
- if (call->state==LinphoneCallPaused &&
+ if (call->state==LinphoneCallPausedByRemote &&
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){
@@ -294,7 +294,7 @@ static void call_updating(SalOp *op){
sal_media_description_has_dir(call->resultdesc,SalStreamRecvOnly) && !strcmp(call->resultdesc->addr,"0.0.0.0")){
if(lc->vtable.display_status)
lc->vtable.display_status(lc,_("We are being paused..."));
- linphone_call_set_state (call,LinphoneCallPaused,"Call paused");
+ linphone_call_set_state (call,LinphoneCallPausedByRemote,"Call paused by remote");
if (lc->current_call!=call){
ms_error("Inconsitency detected: current call is %p but call %p is being paused !",lc->current_call,call);
}
diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c
index 3244aac7e..00739ae95 100644
--- a/coreapi/linphonecall.c
+++ b/coreapi/linphonecall.c
@@ -293,8 +293,9 @@ void linphone_call_ref(LinphoneCall *obj){
**/
void linphone_call_unref(LinphoneCall *obj){
obj->refcnt--;
- if (obj->refcnt==0)
+ if (obj->refcnt==0){
linphone_call_destroy(obj);
+ }
}
/**
@@ -576,7 +577,6 @@ static RtpProfile *make_profile(LinphoneCore *lc, const SalMediaDescription *md,
number=payload_type_get_number(pt);
if (rtp_profile_get_payload(prof,number)!=NULL){
ms_warning("A payload type with number %i already exists in profile !",number);
- payload_type_destroy(pt);
}else
rtp_profile_set_payload(prof,number,pt);
}
@@ -603,7 +603,7 @@ void linphone_call_start_media_streams(LinphoneCall *call){
{
const SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc,
SalProtoRtpAvp,SalAudio);
- if (stream){
+ if (stream && stream->dir!=SalStreamInactive){
MSSndCard *playcard=lc->sound_conf.lsd_card ?
lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard;
MSSndCard *captcard=lc->sound_conf.capt_sndcard;
@@ -661,7 +661,7 @@ void linphone_call_start_media_streams(LinphoneCall *call){
video_preview_stop(lc->previewstream);
lc->previewstream=NULL;
}
- if (stream) {
+ if (stream && stream->dir!=SalStreamInactive) {
const char *addr=stream->addr[0]!='\0' ? stream->addr : call->resultdesc->addr;
call->video_profile=make_profile(lc,call->resultdesc,stream,&used_pt);
if (used_pt!=-1){
diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c
index 0bbfe8af1..89ad4382a 100644
--- a/coreapi/linphonecore.c
+++ b/coreapi/linphonecore.c
@@ -2283,11 +2283,6 @@ int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *the_call)
{
LinphoneCall *call = the_call;
- if(linphone_core_get_current_call(lc) != call)
- {
- ms_error("The call asked to be paused was not the current on");
- return -1;
- }
if (sal_call_hold(call->op,TRUE) != 0)
{
if (lc->vtable.display_warning)
@@ -2301,6 +2296,21 @@ int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *the_call)
return 0;
}
+/**
+ * Pause all currently running calls.
+**/
+int linphone_core_pause_all_calls(LinphoneCore *lc){
+ const MSList *elem;
+ for(elem=lc->calls;elem!=NULL;elem=elem->next){
+ LinphoneCall *call=(LinphoneCall *)elem->data;
+ LinphoneCallState cs=linphone_call_get_state(call);
+ if (cs==LinphoneCallStreamsRunning && cs==LinphoneCallPausedByRemote){
+ linphone_core_pause_call(lc,call);
+ }
+ }
+ return 0;
+}
+
/**
* Resumes the call.
*
@@ -2312,7 +2322,7 @@ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *the_call)
LinphoneCall *call = the_call;
if(call->state!=LinphoneCallPaused ){
- ms_warning("we cannot resume a call when the communication is not established");
+ ms_warning("we cannot resume a call that has not been established and paused before");
return -1;
}
if(linphone_core_get_current_call(lc) != NULL){
diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h
index c845e4596..707e4b40c 100644
--- a/coreapi/linphonecore.h
+++ b/coreapi/linphonecore.h
@@ -176,6 +176,7 @@ typedef enum _LinphoneCallState{
LinphoneCallRefered,
LinphoneCallError,
LinphoneCallEnd,
+ LinphoneCallPausedByRemote
} LinphoneCallState;
@@ -527,6 +528,8 @@ int linphone_core_terminate_all_calls(LinphoneCore *lc);
int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call);
+int linphone_core_pause_all_calls(LinphoneCore *lc);
+
int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *call);
LinphoneCall *linphone_core_get_call_by_remote_address(LinphoneCore *lc, const char *remote_address);
diff --git a/coreapi/offeranswer.c b/coreapi/offeranswer.c
index 172255716..ac5ea1d7a 100644
--- a/coreapi/offeranswer.c
+++ b/coreapi/offeranswer.c
@@ -98,6 +98,21 @@ static bool_t only_telephone_event(const MSList *l){
return TRUE;
}
+static SalStreamDir compute_dir(SalStreamDir local, SalStreamDir answered){
+ SalStreamDir res=local;
+ if (local==SalStreamSendRecv){
+ if (answered==SalStreamRecvOnly){
+ res=SalStreamSendOnly;
+ }else if (answered==SalStreamSendOnly){
+ res=SalStreamRecvOnly;
+ }
+ }
+ if (answered==SalStreamInactive){
+ res=SalStreamInactive;
+ }
+ return res;
+}
+
static void initiate_outgoing(const SalStreamDescription *local_offer,
const SalStreamDescription *remote_answer,
SalStreamDescription *result){
@@ -105,7 +120,7 @@ static void initiate_outgoing(const SalStreamDescription *local_offer,
result->payloads=match_payloads(local_offer->payloads,remote_answer->payloads,TRUE);
result->proto=local_offer->proto;
result->type=local_offer->type;
- result->dir=local_offer->dir;
+ result->dir=compute_dir(local_offer->dir,remote_answer->dir);
if (result->payloads && !only_telephone_event(result->payloads)){
strcpy(result->addr,remote_answer->addr);
diff --git a/gtk/incall_view.c b/gtk/incall_view.c
index fca97adda..ffa6329d3 100644
--- a/gtk/incall_view.c
+++ b/gtk/incall_view.c
@@ -72,7 +72,11 @@ void linphone_gtk_create_in_call_view(LinphoneCall *call){
GtkNotebook *notebook=(GtkNotebook *)linphone_gtk_get_widget(main_window,"viewswitch");
static int call_index=1;
int idx;
-
+
+ if (ms_list_size(linphone_core_get_calls(linphone_gtk_get_core()))==1){
+ /*this is the only call at this time */
+ call_index=1;
+ }
g_object_set_data(G_OBJECT(call_view),"call",call);
linphone_call_set_user_pointer (call,call_view);
linphone_call_ref(call);
@@ -131,20 +135,26 @@ void linphone_gtk_in_call_view_set_calling(LinphoneCall *call){
}else gtk_image_set_from_stock(GTK_IMAGE(animation),GTK_STOCK_FIND,GTK_ICON_SIZE_DIALOG);
}
-void linphone_gtk_in_call_view_set_incoming(LinphoneCall *call){
+void linphone_gtk_in_call_view_set_incoming(LinphoneCall *call, bool_t with_pause){
GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
GtkWidget *status=linphone_gtk_get_widget(callview,"in_call_status");
GtkWidget *callee=linphone_gtk_get_widget(callview,"in_call_uri");
GtkWidget *duration=linphone_gtk_get_widget(callview,"in_call_duration");
GtkWidget *animation=linphone_gtk_get_widget(callview,"in_call_animation");
GdkPixbufAnimation *pbuf=create_pixbuf_animation("calling_anim.gif");
+ GtkWidget *answer_button;
gtk_label_set_markup(GTK_LABEL(status),_("Incoming call"));
gtk_widget_show_all(linphone_gtk_get_widget(callview,"answer_decline_panel"));
display_peer_name_in_label(callee,linphone_call_get_remote_address (call));
- gtk_button_set_image(GTK_BUTTON(linphone_gtk_get_widget(callview,"accept_call")),
+ answer_button=linphone_gtk_get_widget(callview,"accept_call");
+ gtk_button_set_image(GTK_BUTTON(answer_button),
create_pixmap (linphone_gtk_get_ui_config("start_call_icon","startcall-green.png")));
+ if (with_pause){
+ gtk_button_set_label(GTK_BUTTON(answer_button),
+ _("Pause all calls\nand answer"));
+ }else gtk_button_set_label(GTK_BUTTON(answer_button),_("Answer"));
gtk_button_set_image(GTK_BUTTON(linphone_gtk_get_widget(callview,"decline_call")),
create_pixmap (linphone_gtk_get_ui_config("stop_call_icon","stopcall-red.png")));
@@ -181,6 +191,13 @@ void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call){
g_object_set_data(G_OBJECT(holdbutton),"call",call);
}
+void linphone_gtk_in_call_view_set_paused(LinphoneCall *call){
+ GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
+ GtkWidget *status=linphone_gtk_get_widget(callview,"in_call_status");
+ gtk_widget_hide(linphone_gtk_get_widget(callview,"answer_decline_panel"));
+ gtk_label_set_markup(GTK_LABEL(status),_("Paused call with"));
+}
+
void linphone_gtk_in_call_view_update_duration(LinphoneCall *call){
GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
GtkWidget *duration_label=linphone_gtk_get_widget(callview,"in_call_duration");
diff --git a/gtk/linphone.h b/gtk/linphone.h
index c50dde591..0b77f6430 100644
--- a/gtk/linphone.h
+++ b/gtk/linphone.h
@@ -93,7 +93,8 @@ void linphone_gtk_in_call_view_set_calling(LinphoneCall *call);
void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call);
void linphone_gtk_in_call_view_update_duration(LinphoneCall *call);
void linphone_gtk_in_call_view_terminate(LinphoneCall *call, const char *error_msg);
-void linphone_gtk_in_call_view_set_incoming(LinphoneCall *call);
+void linphone_gtk_in_call_view_set_incoming(LinphoneCall *call, bool_t with_pause);
+void linphone_gtk_in_call_view_set_paused(LinphoneCall *call);
void linphone_gtk_enable_mute_button(GtkToggleButton *button, gboolean sensitive);
void linphone_gtk_enable_hold_button(GtkToggleButton *button, gboolean sensitive);
diff --git a/gtk/main.c b/gtk/main.c
index f435ff31a..6ad7c65fe 100644
--- a/gtk/main.c
+++ b/gtk/main.c
@@ -636,7 +636,8 @@ static gboolean in_call_timer(){
static bool_t all_calls_paused(const MSList *calls){
for(;calls!=NULL;calls=calls->next){
LinphoneCall *call=(LinphoneCall*)calls->data;
- if (linphone_call_get_state(call)!=LinphoneCallPaused)
+ LinphoneCallState cs=linphone_call_get_state(call);
+ if (cs!=LinphoneCallPaused && cs!=LinphoneCallIncomingReceived)
return FALSE;
}
return TRUE;
@@ -741,8 +742,10 @@ void linphone_gtk_decline_clicked(GtkWidget *button){
void linphone_gtk_answer_clicked(GtkWidget *button){
LinphoneCall *call=linphone_gtk_get_currently_displayed_call ();
- if (call)
+ if (call){
+ linphone_core_pause_all_calls(linphone_gtk_get_core());
linphone_core_accept_call(linphone_gtk_get_core(),call);
+ }
}
void linphone_gtk_set_audio_video(){
@@ -937,7 +940,7 @@ static void linphone_gtk_call_state_changed(LinphoneCore *lc, LinphoneCall *call
case LinphoneCallOutgoingProgress:
linphone_gtk_in_call_view_set_calling (call);
break;
- case LinphoneCallConnected:
+ case LinphoneCallStreamsRunning:
linphone_gtk_in_call_view_set_in_call(call);
linphone_gtk_enable_mute_button(
GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"main_mute")),
@@ -952,12 +955,15 @@ static void linphone_gtk_call_state_changed(LinphoneCore *lc, LinphoneCall *call
break;
case LinphoneCallIncomingReceived:
linphone_gtk_create_in_call_view (call);
- linphone_gtk_in_call_view_set_incoming(call);
+ linphone_gtk_in_call_view_set_incoming(call,!all_calls_paused (linphone_core_get_calls(lc)));
if (auto_answer) {
linphone_call_ref(call);
g_timeout_add(2000,(GSourceFunc)linphone_gtk_auto_answer ,call);
- }
-
+ }
+ break;
+ case LinphoneCallPaused:
+ case LinphoneCallPausedByRemote:
+ linphone_gtk_in_call_view_set_paused(call);
break;
default:
break;