linphone_core_get_local_ip(lc,linphone_address_get_domain(from),call->localip);
linphone_call_init_common(call, from, to);
linphone_core_init_default_params(lc, &call->params);
+ call->params.has_video &= !!lc->video_policy.automatically_accept;
call->localdesc=create_local_media_description (lc,call);
call->camera_active=call->params.has_video;
if (linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseStun)
const char **devices;
const MSList *elem;
int i;
+ LinphoneVideoPolicy vpol;
/* retrieve all video devices */
elem=ms_web_cam_manager_get_list(ms_web_cam_manager_get());
capture=lp_config_get_int(lc->config,"video","capture",1);
display=lp_config_get_int(lc->config,"video","display",1);
self_view=lp_config_get_int(lc->config,"video","self_view",1);
+ vpol.automatically_initiate=lp_config_get_int(lc->config,"video","automatically_initiate",1);
+ vpol.automatically_accept=lp_config_get_int(lc->config,"video","automatically_accept",1);
lc->video_conf.displaytype=lp_config_get_string(lc->config,"video","displaytype",NULL);
if(lc->video_conf.displaytype)
ms_message("we are using a specific display:%s\n",lc->video_conf.displaytype);
linphone_core_enable_video(lc,capture,display);
linphone_core_enable_self_view(lc,self_view);
+ linphone_core_set_video_policy(lc,&vpol);
#endif
}
void linphone_core_start_refered_call(LinphoneCore *lc, LinphoneCall *call){
if (call->refer_pending){
LinphoneCallParams *cp=linphone_core_create_default_call_parameters(lc);
+ cp->has_video &= !!lc->video_policy.automatically_initiate;
cp->referer=call;
ms_message("Starting new call to refered address %s",call->refer_to);
call->refer_pending=FALSE;
LinphoneCall * linphone_core_invite(LinphoneCore *lc, const char *url){
LinphoneCall *call;
LinphoneCallParams *p=linphone_core_create_default_call_parameters (lc);
+ p->has_video &= !!lc->video_policy.automatically_initiate;
call=linphone_core_invite_with_params(lc,url,p);
linphone_call_params_destroy(p);
return call;
**/
LinphoneCall * linphone_core_invite_address(LinphoneCore *lc, const LinphoneAddress *addr){
LinphoneCall *call;
- LinphoneCallParams *p=linphone_core_create_default_call_parameters (lc);
+ LinphoneCallParams *p=linphone_core_create_default_call_parameters(lc);
+ p->has_video &= !!lc->video_policy.automatically_initiate;
call=linphone_core_invite_address_with_params (lc,addr,p);
linphone_call_params_destroy(p);
return call;
linphone_core_get_upload_bandwidth(lc));
}
+bool_t linphone_core_video_supported(LinphoneCore *lc){
+#ifdef VIDEO_ENABLED
+ return TRUE;
+#else
+ return FALSE;
+#endif
+}
+
/**
* Returns TRUE if video is enabled, FALSE otherwise.
* @ingroup media_parameters
return (lc->video_conf.display || lc->video_conf.capture);
}
+/**
+ * Sets the default policy for video.
+ * This policy defines whether:
+ * - video shall be initiated by default for outgoing calls
+ * - video shall be accepter by default for incoming calls
+**/
+void linphone_core_set_video_policy(LinphoneCore *lc, const LinphoneVideoPolicy *policy){
+ lc->video_policy=*policy;
+ if (linphone_core_ready(lc)){
+ lp_config_set_int(lc->config,"video","automatically_initiate",policy->automatically_initiate);
+ lp_config_set_int(lc->config,"video","automatically_accept",policy->automatically_accept);
+ }
+}
+
+/**
+ * Get the default policy for video.
+ * See linphone_core_set_video_policy() for more details.
+**/
+const LinphoneVideoPolicy *linphone_core_get_video_policy(LinphoneCore *lc){
+ return &lc->video_policy;
+}
+
/**
* Controls video preview enablement.
*
const char *linphone_reason_to_string(LinphoneReason err);
+/**
+ * Structure describing policy regarding video streams establishments.
+**/
+struct _LinphoneVideoPolicy{
+ bool_t automatically_initiate; /**<Whether video shall be automatically proposed for outgoing calls.*/
+ bool_t automatically_accept; /**<Whether video shall be automatically accepted for incoming calls*/
+ bool_t unused[2];
+};
+
+typedef struct _LinphoneVideoPolicy LinphoneVideoPolicy;
+
/**
* The LinphoneCall object represents a call issued or received by the LinphoneCore
**/
void linphone_core_clear_call_logs(LinphoneCore *lc);
/* video support */
+bool_t linphone_core_video_supported(LinphoneCore *lc);
void linphone_core_enable_video(LinphoneCore *lc, bool_t vcap_enabled, bool_t display_enabled);
bool_t linphone_core_video_enabled(LinphoneCore *lc);
+void linphone_core_set_video_policy(LinphoneCore *lc, const LinphoneVideoPolicy *policy);
+const LinphoneVideoPolicy *linphone_core_get_video_policy(LinphoneCore *lc);
typedef struct MSVideoSizeDef{
MSVideoSize vsize;
MSList *hooks;
LinphoneConference conf_ctx;
char* zrtp_secrets_cache;
+ LinphoneVideoPolicy video_policy;
bool_t use_files;
bool_t apply_nat_settings;
bool_t initial_subscribes_sent;
GTK_BUTTON(linphone_gtk_get_widget(call_view,"incall_mute")),FALSE);
}
+static void video_button_clicked(GtkWidget *button, LinphoneCall *call){
+ gboolean adding=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button),"adding_video"));
+ LinphoneCore *lc=linphone_call_get_core(call);
+ LinphoneCallParams *params=linphone_call_params_copy(linphone_call_get_current_params(call));
+ gtk_widget_set_sensitive(button,FALSE);
+ linphone_call_params_enable_video(params,adding);
+ linphone_core_update_call(lc,call,params);
+ linphone_call_params_destroy(params);
+}
+
+void linphone_gtk_update_video_button(LinphoneCall *call){
+ GtkWidget *call_view=(GtkWidget*)linphone_call_get_user_pointer(call);
+ GtkWidget *button=linphone_gtk_get_widget(call_view,"video_button");
+ const LinphoneCallParams *params=linphone_call_get_current_params(call);
+ gboolean has_video=linphone_call_params_video_enabled(params);
+
+ gtk_button_set_image(GTK_BUTTON(button),
+ gtk_image_new_from_stock(has_video ? GTK_STOCK_REMOVE : GTK_STOCK_ADD,GTK_ICON_SIZE_BUTTON));
+ g_object_set_data(G_OBJECT(button),"adding_video",GINT_TO_POINTER(!has_video));
+ if (!linphone_core_video_supported(linphone_call_get_core(call))){
+ gtk_widget_set_sensitive(button,FALSE);
+ return;
+ }
+ if (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button),"signal_connected"))==0){
+ g_signal_connect(G_OBJECT(button),"clicked",(GCallback)video_button_clicked,call);
+ g_object_set_data(G_OBJECT(button),"signal_connected",GINT_TO_POINTER(1));
+ }
+ gtk_widget_set_sensitive(button,linphone_call_get_state(call)==LinphoneCallStreamsRunning);
+}
+
void linphone_gtk_remove_in_call_view(LinphoneCall *call){
GtkWidget *w=(GtkWidget*)linphone_call_get_user_pointer (call);
GtkWidget *main_window=linphone_gtk_get_main_window ();
void linphone_gtk_unset_from_conference(LinphoneCall *call);
void linphone_gtk_terminate_conference_participant(LinphoneCall *call);
void linphone_gtk_in_call_view_show_encryption(LinphoneCall *call);
+void linphone_gtk_update_video_button(LinphoneCall *call);
typedef float (*get_volume_t)(void *data);
void linphone_gtk_init_audio_meter(GtkWidget *w, get_volume_t get_volume, void *data);
linphone_core_set_waiting_callback(the_core,linphone_gtk_wait,NULL);
linphone_core_set_zrtp_secrets_file(the_core,secrets_file);
g_free(secrets_file);
+ linphone_core_enable_video(the_core,TRUE,TRUE);
}
linphone_gtk_enable_transfer_button(lc,call_list_size>1);
linphone_gtk_enable_conference_button(lc,call_list_size>1);
update_video_title();
+ if (call) linphone_gtk_update_video_button(call);
}
static gboolean linphone_gtk_start_call_do(GtkWidget *uri_bar){
void linphone_gtk_enable_video(GtkWidget *w){
gboolean val=gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w));
GtkWidget *selfview_item=linphone_gtk_get_widget(linphone_gtk_get_main_window(),"selfview_item");
- linphone_core_enable_video(linphone_gtk_get_core(),val,val);
+ LinphoneVideoPolicy policy={0};
+ policy.automatically_initiate=policy.automatically_accept=val;
+ linphone_core_enable_video(linphone_gtk_get_core(),TRUE,TRUE);
+ linphone_core_set_video_policy(linphone_gtk_get_core(),&policy);
+
gtk_widget_set_sensitive(selfview_item,val);
if (val){
linphone_core_enable_video_preview(linphone_gtk_get_core(),
}
}
+static void on_call_updated_response(GtkWidget *dialog, gint responseid, LinphoneCall *call){
+ if (linphone_call_get_state(call)==LinphoneCallUpdatedByRemote){
+ LinphoneCore *lc=linphone_call_get_core(call);
+ LinphoneCallParams *params=linphone_call_params_copy(linphone_call_get_current_params(call));
+ linphone_call_params_enable_video(params,responseid==GTK_RESPONSE_YES);
+ linphone_core_accept_call_update(lc,call,params);
+ linphone_call_params_destroy(params);
+ }
+ linphone_call_unref(call);
+ g_source_remove_by_user_data(dialog);
+ gtk_widget_destroy(dialog);
+}
+
+static void on_call_updated_timeout(GtkWidget *dialog){
+ gtk_widget_destroy(dialog);
+}
+
+static void linphone_gtk_call_updated_by_remote(LinphoneCall *call){
+ LinphoneCore *lc=linphone_call_get_core(call);
+ const LinphoneVideoPolicy *pol=linphone_core_get_video_policy(lc);
+ const LinphoneCallParams *rparams=linphone_call_get_remote_params(call);
+ const LinphoneCallParams *current_params=linphone_call_get_current_params(call);
+ gboolean video_requested=linphone_call_params_video_enabled(rparams);
+ gboolean video_used=linphone_call_params_video_enabled(current_params);
+ g_message("Video used=%i, video requested=%i, automatically_accept=%i",
+ video_used,video_requested,pol->automatically_accept);
+ if (video_used==FALSE && video_requested && !pol->automatically_accept){
+ linphone_core_defer_call_update(lc,call);
+ {
+ const LinphoneAddress *addr=linphone_call_get_remote_address(call);
+ GtkWidget *dialog;
+ const char *dname=linphone_address_get_display_name(addr);
+ if (dname==NULL) dname=linphone_address_get_username(addr);
+ if (dname==NULL) dname=linphone_address_get_domain(addr);
+ dialog=gtk_message_dialog_new(GTK_WINDOW(linphone_gtk_get_main_window()),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_YES_NO,
+ _("%s proposed to start video. Do you accept ?"),dname);
+ g_signal_connect(G_OBJECT(dialog),"response",(GCallback)on_call_updated_response,linphone_call_ref(call));
+ g_timeout_add(20000,(GSourceFunc)on_call_updated_timeout,dialog);
+ gtk_widget_show(dialog);
+ }
+ }
+}
+
static void linphone_gtk_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cs, const char *msg){
switch(cs){
case LinphoneCallOutgoingInit:
case LinphoneCallStreamsRunning:
linphone_gtk_in_call_view_set_in_call(call);
break;
+ case LinphoneCallUpdatedByRemote:
+ linphone_gtk_call_updated_by_remote(call);
+ break;
case LinphoneCallError:
linphone_gtk_in_call_view_terminate (call,msg);
break;
}
static void linphone_gtk_check_menu_items(void){
- bool_t video_enabled=linphone_core_video_enabled(linphone_gtk_get_core());
+ const LinphoneVideoPolicy *pol=linphone_core_get_video_policy(linphone_gtk_get_core());
+ bool_t video_enabled=pol->automatically_accept && pol->automatically_initiate;
bool_t selfview=linphone_gtk_get_ui_config_int("videoselfview",VIDEOSELFVIEW_DEFAULT);
GtkWidget *selfview_item=linphone_gtk_get_widget(
linphone_gtk_get_main_window(),"selfview_item");
#ifdef HAVE_GTK_OSX
static gboolean on_window_state_event(GtkWidget *w, GdkEventWindowState *event){
- if ((event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) ||(event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) ){
- linphone_core_enable_video_preview(linphone_gtk_get_core(),FALSE);
- }else{
- linphone_core_enable_video_preview(linphone_gtk_get_core(),
+ if ((event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) ||(event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) ){
+ linphone_core_enable_video_preview(linphone_gtk_get_core(),FALSE);
+ }else{
+ linphone_core_enable_video_preview(linphone_gtk_get_core(),
linphone_gtk_get_ui_config_int("videoselfview",VIDEOSELFVIEW_DEFAULT) && linphone_core_video_enabled(linphone_gtk_get_core()));
- }
- return FALSE;
+ }
+ return FALSE;
}
#endif
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="homogeneous">True</property>
- <property name="layout_style">center</property>
+ <property name="layout_style">spread</property>
<child>
<object class="GtkButton" id="hold_call">
<property name="label" translatable="yes">Pause</property>
<property name="position">0</property>
</packing>
</child>
+ <child>
+ <object class="GtkButton" id="video_button">
+ <property name="label" translatable="yes">Video</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
</object>
<packing>
<property name="expand">False</property>