diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index a307a1c5f..53b006d4d 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -94,7 +94,7 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia linphone_call_start_media_streams(call,all_muted,send_ringbacktone); } } - +#if 0 static bool_t is_duplicate_call(LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to){ MSList *elem; for(elem=lc->calls;elem!=NULL;elem=elem->next){ @@ -106,6 +106,22 @@ static bool_t is_duplicate_call(LinphoneCore *lc, const LinphoneAddress *from, c } return FALSE; } +#endif + +static bool_t already_a_call_pending(LinphoneCore *lc){ + MSList *elem; + for(elem=lc->calls;elem!=NULL;elem=elem->next){ + LinphoneCall *call=(LinphoneCall*)elem->data; + if (call->state==LinphoneCallIncomingReceived + || call->state==LinphoneCallOutgoingInit + || call->state==LinphoneCallOutgoingProgress + || call->state==LinphoneCallOutgoingEarlyMedia + || call->state==LinphoneCallOutgoingRinging){ + return TRUE; + } + } + return FALSE; +} static void call_received(SalOp *h){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h)); @@ -145,8 +161,8 @@ static void call_received(SalOp *h){ from_addr=linphone_address_new(from); to_addr=linphone_address_new(to); - if (is_duplicate_call(lc,from_addr,to_addr)){ - ms_warning("Receiving duplicated call, refusing this one."); + if (already_a_call_pending(lc)){ + ms_warning("Receiving another call while one is ringing or initiated, refusing this one with busy message."); sal_call_decline(h,SalReasonBusy,NULL); sal_op_release(h); linphone_address_destroy(from_addr); diff --git a/coreapi/conference.c b/coreapi/conference.c index 53abfab81..14867f72a 100644 --- a/coreapi/conference.c +++ b/coreapi/conference.c @@ -25,6 +25,7 @@ #include "private.h" +#include "mediastreamer2/msvolume.h" static void conference_check_init(LinphoneConference *ctx){ if (ctx->conf==NULL){ @@ -98,6 +99,18 @@ static void add_local_endpoint(LinphoneConference *conf,LinphoneCore *lc){ ms_audio_conference_add_member(conf->conf,conf->local_endpoint); } +float linphone_core_get_conference_local_input_volume(LinphoneCore *lc){ + LinphoneConference *conf=&lc->conf_ctx; + AudioStream *st=conf->local_participant; + if (st && st->volsend){ + float vol=0; + ms_filter_call_method(st->volsend,MS_VOLUME_GET,&vol); + return vol; + + } + return LINPHONE_VOLUME_DB_LOWEST; +} + int linphone_core_add_to_conference(LinphoneCore *lc, LinphoneCall *call){ LinphoneCallParams params; LinphoneConference *conf=&lc->conf_ctx; diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 8ab925cf4..f3b20a5b1 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -479,8 +479,9 @@ static void linphone_call_destroy(LinphoneCall *obj) * valid. Once the application no more needs this pointer, * it must call linphone_call_unref(). **/ -void linphone_call_ref(LinphoneCall *obj){ +LinphoneCall * linphone_call_ref(LinphoneCall *obj){ obj->refcnt++; + return obj; } /** @@ -1025,7 +1026,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna call->audio_profile, stream->addr[0]!='\0' ? stream->addr : call->resultdesc->addr, stream->port, - stream->port+1, + linphone_core_rtcp_enabled(lc) ? (stream->port+1) : 0, used_pt, jitt_comp, playfile, @@ -1110,7 +1111,7 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna video_stream_set_device_rotation(call->videostream, lc->device_rotation); video_stream_start(call->videostream, call->video_profile, addr, vstream->port, - vstream->port+1, + linphone_core_rtcp_enabled(lc) ? (vstream->port+1) : 0, used_pt, lc->rtp_conf.audio_jitt_comp, cam); video_stream_set_rtcp_information(call->videostream, cname,LINPHONE_RTCP_SDES_TOOL); } diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index cce64048e..f86337b8a 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -811,6 +811,10 @@ bool_t linphone_core_adaptive_rate_control_enabled(const LinphoneCore *lc){ return lp_config_get_int(lc->config,"net","adaptive_rate_control",FALSE); } +bool_t linphone_core_rtcp_enabled(const LinphoneCore *lc){ + return lp_config_get_int(lc->config,"rtp","rtcp_enabled",TRUE); +} + /** * Sets maximum available download bandwidth * diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 368746cda..65683870a 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -242,7 +242,7 @@ const LinphoneAddress * linphone_core_get_current_call_remote_address(struct _Li const LinphoneAddress * linphone_call_get_remote_address(const LinphoneCall *call); char *linphone_call_get_remote_address_as_string(const LinphoneCall *call); LinphoneCallDir linphone_call_get_dir(const LinphoneCall *call); -void linphone_call_ref(LinphoneCall *call); +LinphoneCall * linphone_call_ref(LinphoneCall *call); 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); @@ -1025,6 +1025,7 @@ int linphone_core_remove_from_conference(LinphoneCore *lc, LinphoneCall *call); bool_t linphone_core_is_in_conference(const LinphoneCore *lc); int linphone_core_enter_conference(LinphoneCore *lc); int linphone_core_leave_conference(LinphoneCore *lc); +float linphone_core_get_conference_local_input_volume(LinphoneCore *lc); int linphone_core_terminate_conference(LinphoneCore *lc); int linphone_core_get_conference_size(LinphoneCore *lc); diff --git a/coreapi/lsd.c b/coreapi/lsd.c index f22a5b207..e47023f4f 100644 --- a/coreapi/lsd.c +++ b/coreapi/lsd.c @@ -215,7 +215,7 @@ bool_t lsd_player_loop_enabled(const LsdPlayer *p){ void lsd_player_set_gain(LsdPlayer *p, float gain){ MSAudioMixerCtl gainctl; gainctl.pin=p->mixer_pin; - gainctl.gain=gain; + gainctl.param.gain=gain; ms_filter_call_method(p->lsd->mixer,MS_AUDIO_MIXER_SET_INPUT_GAIN,&gainctl); } diff --git a/coreapi/private.h b/coreapi/private.h index b8aba9d1f..1d44bb1cb 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -226,6 +226,7 @@ int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, LinphonePro void linphone_core_start_refered_call(LinphoneCore *lc, LinphoneCall *call); extern SalCallbacks linphone_sal_callbacks; void linphone_proxy_config_set_error(LinphoneProxyConfig *cfg, LinphoneReason error); +bool_t linphone_core_rtcp_enabled(const LinphoneCore *lc); struct _LinphoneProxyConfig { diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 828468144..2d62217ac 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -45,6 +45,7 @@ linphone_SOURCES= \ incall_view.c \ loginframe.c \ singleinstance.c \ + conference.c \ linphone.h linphone_LDADD=$(ORTP_LIBS) \ diff --git a/gtk/conference.c b/gtk/conference.c index c3df39593..eda0d9594 100644 --- a/gtk/conference.c +++ b/gtk/conference.c @@ -23,9 +23,89 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - #include "linphone.h" - - - - - \ No newline at end of file +#include "linphone.h" + +static GtkWidget *create_conference_label(void){ + GtkWidget *box=gtk_hbox_new(FALSE,0); + gtk_box_pack_start(GTK_BOX(box),gtk_image_new_from_stock(GTK_STOCK_ADD,GTK_ICON_SIZE_MENU),FALSE,FALSE,0); + gtk_box_pack_end(GTK_BOX(box),gtk_label_new(_("Conference")),TRUE,FALSE,0); + gtk_widget_show_all(box); + return box; +} + +static void init_local_participant(GtkWidget *participant){ + GtkWidget *sound_meter; + gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(participant,"callee_name_label")),_("Me")); + sound_meter=linphone_gtk_get_widget(participant,"sound_indicator"); + gtk_widget_hide(linphone_gtk_get_widget(participant,"hangup_button")); + linphone_gtk_init_audio_meter(sound_meter, (get_volume_t) linphone_core_get_conference_local_input_volume, linphone_gtk_get_core()); +} + +static GtkWidget *get_conference_tab(GtkWidget *mw){ + GtkWidget *box=(GtkWidget*)g_object_get_data(G_OBJECT(mw),"conference_tab"); + if (box==NULL){ + GtkWidget *box=gtk_vbox_new(FALSE,0); + GtkWidget *participant=linphone_gtk_create_widget("main","callee_frame"); + init_local_participant(participant); + gtk_box_pack_start(GTK_BOX(box),participant,FALSE,FALSE,0); + gtk_widget_show(box); + g_object_set_data(G_OBJECT(mw),"conference_tab",box); + gtk_notebook_append_page(GTK_NOTEBOOK(linphone_gtk_get_widget(mw,"viewswitch")),box, + create_conference_label()); + } + return box; +} + +void linphone_gtk_add_to_conference(LinphoneCall *call){ + GtkWidget *mw=linphone_gtk_get_main_window(); + GtkWidget *tab=get_conference_tab(mw); + GtkWidget *participant=linphone_gtk_create_widget("main","callee_frame"); + const char *hangup_image=linphone_gtk_get_ui_config("stop_call_icon","stopcall-red.png"); + const LinphoneAddress *addr=linphone_call_get_remote_address(call); + GtkWidget *sound_meter; + GtkWidget *viewswitch=linphone_gtk_get_widget(mw,"viewswitch"); + gchar *markup; + if (linphone_address_get_display_name(addr)!=NULL){ + markup=g_strdup_printf("%s",linphone_address_get_display_name(addr)); + }else{ + char *tmp=linphone_address_as_string_uri_only(addr); + markup=g_strdup_printf("%s",tmp); + ms_free(tmp); + } + gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(participant,"callee_name_label")),markup); + g_free(markup); + gtk_button_set_image(GTK_BUTTON(linphone_gtk_get_widget(participant,"hangup_button")),create_pixmap(hangup_image)); + sound_meter=linphone_gtk_get_widget(participant,"sound_indicator"); + linphone_gtk_init_audio_meter(sound_meter, (get_volume_t) linphone_call_get_play_volume, call); + gtk_box_pack_end(GTK_BOX(tab),participant,FALSE,FALSE,0); + g_object_set_data_full(G_OBJECT(participant),"call",linphone_call_ref(call),(GDestroyNotify)linphone_call_unref); + gtk_widget_show(participant); + gtk_notebook_set_current_page(GTK_NOTEBOOK(viewswitch), + gtk_notebook_page_num(GTK_NOTEBOOK(viewswitch),tab)); + linphone_core_add_to_conference(linphone_gtk_get_core(),call); +} + +static GtkWidget *find_conferencee_from_call(LinphoneCall *call){ + GtkWidget *mw=linphone_gtk_get_main_window(); + GtkWidget *tab=get_conference_tab(mw); + GList *elem; + GtkWidget *ret=NULL; + GList *l=gtk_container_get_children(GTK_CONTAINER(tab)); + for(elem=l;elem!=NULL;elem=elem->next){ + GtkWidget *frame=(GtkWidget*)elem->data; + if (call==g_object_get_data(G_OBJECT(frame),"call")){ + ret=frame; + break; + } + } + g_list_free(l); + return ret; +} + +void linphone_gtk_remove_from_conference(LinphoneCall *call){ + GtkWidget *frame=find_conferencee_from_call(call); + if (frame){ + gtk_widget_destroy(frame); + } +} + diff --git a/gtk/incall_view.c b/gtk/incall_view.c index 0fc8a5545..6411a9e52 100644 --- a/gtk/incall_view.c +++ b/gtk/incall_view.c @@ -150,7 +150,8 @@ void linphone_gtk_enable_transfer_button(LinphoneCore *lc, gboolean value){ } static void conference_button_clicked(GtkWidget *button, gpointer call_ref){ - + linphone_gtk_add_to_conference((LinphoneCall*)call_ref); + gtk_widget_set_sensitive(button,FALSE); } void linphone_gtk_enable_conference_button(LinphoneCore *lc, gboolean value){ @@ -319,7 +320,7 @@ static gboolean linphone_gtk_in_call_view_refresh(LinphoneCall *call){ return TRUE; } -typedef float (*get_volume_t)(void *data); + typedef struct _volume_ctx{ GtkWidget *widget; @@ -363,7 +364,15 @@ void linphone_gtk_init_audio_meter(GtkWidget *w, get_volume_t get_volume, void * } } -void linphone_gtk_in_call_view_enable_audio_view(LinphoneCall *call){ +void linphone_gtk_uninit_audio_meter(GtkWidget *w){ + guint task_id=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"task_id")); + if (task_id!=0){ + g_object_set_data(G_OBJECT(w),"ctx",NULL); + g_object_set_data(G_OBJECT(w),"task_id",NULL); + } +} + +void linphone_gtk_in_call_view_enable_audio_view(LinphoneCall *call, gboolean val){ GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call); GtkWidget *audio_view=linphone_gtk_get_widget(callview,"incall_audioview"); //GtkWidget *mic=linphone_gtk_get_widget(callview,"incall_mic_icon"); @@ -373,11 +382,16 @@ void linphone_gtk_in_call_view_enable_audio_view(LinphoneCall *call){ GdkPixbuf *pbuf; //gtk_image_set_from_pixbuf(GTK_IMAGE(mic),(pbuf=create_pixbuf("mic_active.png"))); //g_object_unref(pbuf); - gtk_image_set_from_pixbuf(GTK_IMAGE(spk),(pbuf=create_pixbuf("speaker.png"))); - g_object_unref(pbuf); - linphone_gtk_init_audio_meter(mic_level,(get_volume_t)linphone_call_get_record_volume,call); - linphone_gtk_init_audio_meter(spk_level,(get_volume_t)linphone_call_get_play_volume,call); - gtk_widget_show_all(audio_view); + if (val){ + gtk_image_set_from_pixbuf(GTK_IMAGE(spk),(pbuf=create_pixbuf("speaker.png"))); + g_object_unref(pbuf); + linphone_gtk_init_audio_meter(mic_level,(get_volume_t)linphone_call_get_record_volume,call); + linphone_gtk_init_audio_meter(spk_level,(get_volume_t)linphone_call_get_play_volume,call); + gtk_widget_show_all(audio_view); + }else{ + linphone_gtk_uninit_audio_meter(mic_level); + linphone_gtk_uninit_audio_meter(spk_level); + } } void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call){ @@ -386,22 +400,23 @@ void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call){ GtkWidget *callee=linphone_gtk_get_widget(callview,"in_call_uri"); GtkWidget *duration=linphone_gtk_get_widget(callview,"in_call_duration"); guint taskid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(callview),"taskid")); + gboolean in_conf=linphone_call_params_local_conference_mode(linphone_call_get_current_params(call)); display_peer_name_in_label(callee,linphone_call_get_remote_address (call)); - gtk_widget_show(linphone_gtk_get_widget(callview,"mute_pause_buttons")); + gtk_widget_set_visible(linphone_gtk_get_widget(callview,"mute_pause_buttons"),!in_conf); gtk_widget_hide(linphone_gtk_get_widget(callview,"answer_decline_panel")); - gtk_label_set_markup(GTK_LABEL(status),_("In call")); + gtk_label_set_markup(GTK_LABEL(status),in_conf ? _("In conference") : _("In call")); gtk_label_set_text(GTK_LABEL(duration),_("00::00::00")); linphone_gtk_in_call_set_animation_image(callview,GTK_STOCK_MEDIA_PLAY,TRUE); linphone_gtk_enable_mute_button( - GTK_BUTTON(linphone_gtk_get_widget(callview,"incall_mute")),TRUE); + GTK_BUTTON(linphone_gtk_get_widget(callview,"incall_mute")),!in_conf); if (taskid==0){ taskid=g_timeout_add(250,(GSourceFunc)linphone_gtk_in_call_view_refresh,call); g_object_set_data(G_OBJECT(callview),"taskid",GINT_TO_POINTER(taskid)); } - linphone_gtk_in_call_view_enable_audio_view(call); + linphone_gtk_in_call_view_enable_audio_view(call, !in_conf); } void linphone_gtk_in_call_view_set_paused(LinphoneCall *call){ @@ -433,6 +448,7 @@ void linphone_gtk_in_call_view_terminate(LinphoneCall *call, const char *error_m GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call); GtkWidget *status=linphone_gtk_get_widget(callview,"in_call_status"); guint taskid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(callview),"taskid")); + gboolean in_conf=linphone_call_params_local_conference_mode(linphone_call_get_current_params(call)); if (error_msg==NULL) gtk_label_set_markup(GTK_LABEL(status),_("Call ended.")); @@ -449,6 +465,9 @@ void linphone_gtk_in_call_view_terminate(LinphoneCall *call, const char *error_m linphone_gtk_enable_mute_button( GTK_BUTTON(linphone_gtk_get_widget(callview,"incall_mute")),FALSE); linphone_gtk_enable_hold_button(call,FALSE,TRUE); + if (in_conf){ + linphone_gtk_remove_from_conference(call); + } if (taskid!=0) g_source_remove(taskid); g_timeout_add_seconds(2,(GSourceFunc)in_call_view_terminated,call); } diff --git a/gtk/linphone.h b/gtk/linphone.h index db25bbdd2..32b5fdab7 100644 --- a/gtk/linphone.h +++ b/gtk/linphone.h @@ -108,6 +108,10 @@ void linphone_gtk_enable_mute_button(GtkButton *button, gboolean sensitive); void linphone_gtk_enable_hold_button(LinphoneCall *call, gboolean sensitive, gboolean holdon); void linphone_gtk_enable_transfer_button(LinphoneCore *lc, gboolean value); void linphone_gtk_enable_conference_button(LinphoneCore *lc, gboolean value); +void linphone_gtk_add_to_conference(LinphoneCall *call); +void linphone_gtk_remove_from_conference(LinphoneCall *call); +typedef float (*get_volume_t)(void *data); +void linphone_gtk_init_audio_meter(GtkWidget *w, get_volume_t get_volume, void *data); void linphone_gtk_show_login_frame(LinphoneProxyConfig *cfg); void linphone_gtk_exit_login_frame(void); diff --git a/mediastreamer2 b/mediastreamer2 index 28a643d20..85e43112e 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 28a643d20f6d6384d96590ab6e988928597878cf +Subproject commit 85e43112e4054ba9112751655a52a42bb381584f