diff --git a/NEWS b/NEWS
index 6fada612f..bb1d573a0 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,14 @@
+linphone-3.8.0 -- Date to be defined
+ Application level improvements:
+ * The video window has now controls in order to switch fullscreen mode and terminate call.
+ * The out of call video preview feature (to test camera) is moved into the settings and is no longer linked to the in-call video preview feature.
+ * Lots of updated translations.
+
+ Liblinphone level improvements:
+ * Support for RTP/AVPF (RFCxxxx) for video streams, allowing fast transmission error recovery with VP8 codec only.
+ * API enhancements, most objects can be ref-counted.
+ * Call video recording feature, in mkv format (H264 streams only for the moment)
+
linphone-3.7.0 -- February 20th, 2014
Application level improvements:
* It is now possible to configure multiple proxy accounts with different transports (UDP, TCP, TLS)
diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c
index c3a838aef..b0fa65e12 100644
--- a/coreapi/linphonecore.c
+++ b/coreapi/linphonecore.c
@@ -5640,6 +5640,22 @@ MSVideoSize linphone_core_get_preview_video_size(const LinphoneCore *lc){
return lc->video_conf.preview_vsize;
}
+/**
+ * Returns the effective video size for the captured video as provided by the camera.
+ * When preview is disabled or not yet started, this function returns a zeroed video size.
+ * @see linphone_core_set_preview_video_size()
+ * @ingroup media_parameters
+ * @param lc the core
+ * @return a MSVideoSize
+**/
+MSVideoSize linphone_core_get_current_preview_video_size(const LinphoneCore *lc){
+ MSVideoSize ret={0};
+ if (lc->previewstream){
+ ret=video_preview_get_current_size(lc->previewstream);
+ }
+ return ret;
+}
+
/**
* Sets the preview video size by its name. See linphone_core_set_preview_video_size() for more information about this feature.
*
diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h
index 5c24d14a7..155170338 100644
--- a/coreapi/linphonecore.h
+++ b/coreapi/linphonecore.h
@@ -2811,6 +2811,7 @@ LINPHONE_PUBLIC void linphone_core_set_preferred_video_size(LinphoneCore *lc, MS
LINPHONE_PUBLIC void linphone_core_set_preview_video_size(LinphoneCore *lc, MSVideoSize vsize);
LINPHONE_PUBLIC void linphone_core_set_preview_video_size_by_name(LinphoneCore *lc, const char *name);
LINPHONE_PUBLIC MSVideoSize linphone_core_get_preview_video_size(const LinphoneCore *lc);
+LINPHONE_PUBLIC MSVideoSize linphone_core_get_current_preview_video_size(const LinphoneCore *lc);
LINPHONE_PUBLIC MSVideoSize linphone_core_get_preferred_video_size(const LinphoneCore *lc);
/**
diff --git a/gtk/linphone.h b/gtk/linphone.h
index 70f1c58e3..cfb52f5e7 100644
--- a/gtk/linphone.h
+++ b/gtk/linphone.h
@@ -199,4 +199,5 @@ void linphone_gtk_close_config_fetching(GtkWidget *w, LinphoneConfiguringState s
const char *linphone_gtk_get_sound_path(const char *file);
void linphone_gtk_in_call_show_video(LinphoneCall *call);
char *linphone_gtk_address(const LinphoneAddress *addr);/*return human readable identifier for a LinphoneAddress */
+GtkWidget *linphone_gtk_get_camera_preview_window(void);
diff --git a/gtk/main.c b/gtk/main.c
index 2bb9d5446..4303a770c 100644
--- a/gtk/main.c
+++ b/gtk/main.c
@@ -827,9 +827,6 @@ bool_t linphone_gtk_video_enabled(void){
void linphone_gtk_show_main_window(){
GtkWidget *w=linphone_gtk_get_main_window();
- LinphoneCore *lc=linphone_gtk_get_core();
- linphone_core_enable_video_preview(lc,linphone_gtk_get_ui_config_int("videoselfview",
- VIDEOSELFVIEW_DEFAULT));
gtk_widget_show(w);
gtk_window_present(GTK_WINDOW(w));
}
@@ -1023,13 +1020,6 @@ void _linphone_gtk_enable_video(gboolean val){
linphone_core_enable_video_capture(linphone_gtk_get_core(), TRUE);
linphone_core_enable_video_display(linphone_gtk_get_core(), TRUE);
linphone_core_set_video_policy(linphone_gtk_get_core(),&policy);
-
- if (val){
- linphone_core_enable_video_preview(linphone_gtk_get_core(),
- linphone_gtk_get_ui_config_int("videoselfview",VIDEOSELFVIEW_DEFAULT));
- }else{
- linphone_core_enable_video_preview(linphone_gtk_get_core(),FALSE);
- }
}
void linphone_gtk_enable_video(GtkWidget *w){
@@ -1041,7 +1031,6 @@ void linphone_gtk_enable_video(GtkWidget *w){
void linphone_gtk_enable_self_view(GtkWidget *w){
gboolean val=gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w));
LinphoneCore *lc=linphone_gtk_get_core();
- linphone_core_enable_video_preview(lc,val);
linphone_core_enable_self_view(lc,val);
linphone_gtk_set_ui_config_int("videoselfview",val);
}
@@ -1838,10 +1827,11 @@ void linphone_gtk_manage_login(void){
gboolean linphone_gtk_close(GtkWidget *mw){
/*shutdown calls if any*/
LinphoneCore *lc=linphone_gtk_get_core();
+ GtkWidget *camera_preview=linphone_gtk_get_camera_preview_window();
if (linphone_core_in_call(lc)){
linphone_core_terminate_all_calls(lc);
}
- linphone_core_enable_video_preview(lc,FALSE);
+ if (camera_preview) gtk_widget_destroy(camera_preview);
#ifdef __APPLE__ /*until with have a better option*/
gtk_window_iconify(GTK_WINDOW(mw));
#else
@@ -1852,13 +1842,6 @@ gboolean linphone_gtk_close(GtkWidget *mw){
#ifdef HAVE_GTK_OSX
static gboolean on_window_state_event(GtkWidget *w, GdkEventWindowState *event){
- bool_t video_enabled=linphone_gtk_video_enabled();
- 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) && video_enabled);
- }
return FALSE;
}
#endif
@@ -1969,6 +1952,7 @@ static void linphone_gtk_init_main_window(){
g_signal_connect(G_OBJECT(main_window), "window-state-event",G_CALLBACK(on_window_state_event), NULL);
#endif
linphone_gtk_check_menu_items();
+ linphone_core_enable_video_preview(linphone_gtk_get_core(),FALSE);
}
void linphone_gtk_log_handler(OrtpLogLevel lev, const char *fmt, va_list args){
diff --git a/gtk/parameters.ui b/gtk/parameters.ui
index aa8480aa9..8c2483ef7 100644
--- a/gtk/parameters.ui
+++ b/gtk/parameters.ui
@@ -1233,7 +1233,7 @@
@@ -2188,7 +2204,7 @@
1
2
GTK_FILL
-
+
@@ -2250,7 +2266,7 @@
2
3
GTK_FILL
-
+
@@ -2265,7 +2281,7 @@
2
3
GTK_FILL
-
+
@@ -2538,7 +2554,7 @@
True
False
- label
+ label
1
@@ -2550,7 +2566,7 @@
True
False
- label
+ label
1
@@ -2564,7 +2580,7 @@
True
False
- label
+ label
1
diff --git a/gtk/videowindow.c b/gtk/videowindow.c
index f2247e573..220569077 100644
--- a/gtk/videowindow.c
+++ b/gtk/videowindow.c
@@ -94,7 +94,7 @@ static gboolean drag_drop(GtkWidget *widget, GdkDragContext *drag_context, gint
return TRUE;
}
-unsigned long get_native_handle(GdkWindow *gdkw){
+static unsigned long get_native_handle(GdkWindow *gdkw){
#ifdef GDK_WINDOWING_X11
return (unsigned long)GDK_WINDOW_XID(gdkw);
#elif defined(WIN32)
@@ -106,6 +106,15 @@ unsigned long get_native_handle(GdkWindow *gdkw){
return 0;
}
+static void _resize_video_window(GtkWidget *video_window, MSVideoSize vsize){
+ MSVideoSize cur;
+ gtk_window_get_size(GTK_WINDOW(video_window),&cur.width,&cur.height);
+ if (vsize.width*vsize.height > cur.width*cur.height ||
+ ms_video_size_get_orientation(vsize)!=ms_video_size_get_orientation(cur) ){
+ gtk_window_resize(GTK_WINDOW(video_window),vsize.width,vsize.height);
+ }
+}
+
static gint resize_video_window(LinphoneCall *call){
const LinphoneCallParams *params=linphone_call_get_current_params(call);
if (params){
@@ -114,13 +123,7 @@ static gint resize_video_window(LinphoneCall *call){
GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
GtkWidget *video_window=(GtkWidget*)g_object_get_data(G_OBJECT(callview),"video_window");
if (video_window){
- MSVideoSize cur;
- gtk_window_get_size(GTK_WINDOW(video_window),&cur.width,&cur.height);
- if (vsize.width*vsize.height > cur.width*cur.height ||
- ms_video_size_get_orientation(vsize)!=ms_video_size_get_orientation(cur) ){
- g_message("Resized to %ix%i",vsize.width,vsize.height);
- gtk_window_resize(GTK_WINDOW(video_window),vsize.width,vsize.height);
- }
+ _resize_video_window(video_window,vsize);
}
}
}
@@ -308,3 +311,55 @@ void linphone_gtk_in_call_show_video(LinphoneCall *call){
}
}
}
+
+static void on_video_preview_destroyed(GtkWidget *video_preview, GtkWidget *mw){
+ LinphoneCore *lc=linphone_gtk_get_core();
+ guint timeout_id=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(video_preview),"timeout-id"));
+ g_object_set_data(G_OBJECT(mw),"video_preview",NULL);
+ linphone_core_enable_video_preview(lc,FALSE);
+ linphone_core_set_native_preview_window_id(lc,-1);
+ g_source_remove(timeout_id);
+}
+
+GtkWidget *linphone_gtk_get_camera_preview_window(void){
+ return (GtkWidget *)g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"video_preview");
+}
+
+static gboolean check_preview_size(GtkWidget *video_preview){
+ MSVideoSize vsize=linphone_core_get_current_preview_video_size(linphone_gtk_get_core());
+ if (vsize.width && vsize.height){
+ MSVideoSize cur;
+ gtk_window_get_size(GTK_WINDOW(video_preview),&cur.width,&cur.height);
+ if (cur.width!=vsize.width || cur.height!=vsize.height){
+ gtk_window_resize(GTK_WINDOW(video_preview),vsize.width,vsize.height);
+ }
+ }
+ return TRUE;
+}
+
+void linphone_gtk_show_camera_preview_clicked(GtkButton *button){
+ GtkWidget *mw=linphone_gtk_get_main_window();
+ GtkWidget *video_preview=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"video_preview");
+
+ if (!video_preview){
+ gchar *title;
+ LinphoneCore *lc=linphone_gtk_get_core();
+ GdkColor color;
+ guint tid;
+
+ video_preview=gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ title=g_strdup_printf("%s - Video preview",linphone_gtk_get_ui_config("title","Linphone"));
+ gtk_window_set_title(GTK_WINDOW(video_preview),title);
+ gdk_color_parse("black",&color);
+ gtk_widget_modify_bg(video_preview,GTK_STATE_NORMAL,&color);
+ g_free(title);
+ g_object_set_data(G_OBJECT(mw),"video_preview",video_preview);
+ g_signal_connect(video_preview,"destroy",(GCallback)on_video_preview_destroyed,mw);
+ gtk_widget_show(video_preview);
+ linphone_core_set_native_preview_window_id(lc,get_native_handle(gtk_widget_get_window(video_preview)));
+ linphone_core_enable_video_preview(lc,TRUE);
+ tid=g_timeout_add(100,(GSourceFunc)check_preview_size,video_preview);
+ g_object_set_data(G_OBJECT(video_preview),"timeout-id",GINT_TO_POINTER(tid));
+ }
+}
+