Commit b9b8b9e0 authored by Simon Morlat's avatar Simon Morlat

gtk: implement fullscreen video mode by having gtk managing the video window...

gtk: implement fullscreen video mode by having gtk managing the video window (not created by mediastreamer2).
parent 590e1656
......@@ -500,7 +500,6 @@ static void *pipe_thread(void*p){
}
static void start_pipe_reader(void){
ms_mutex_init(&prompt_mutex,NULL);
pipe_reader_run=TRUE;
ortp_thread_create(&pipe_reader_th,NULL,pipe_thread,NULL);
}
......
......@@ -29,6 +29,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "linphone.h"
#ifdef __linux
#include <gdk/gdkx.h>
#elif defined(WIN32)
#include <gdk/gdk-win32.h>
#elif defined(__APPLE__)
#include <gdk/gdk-quartz.h>
#endif
#include <gdk/gdkkeysyms.h>
gboolean linphone_gtk_use_in_call_view(){
static int val=-1;
......@@ -687,6 +696,111 @@ void linphone_gtk_in_call_view_show_encryption(LinphoneCall *call){
}
}
char *linphone_gtk_address(const LinphoneAddress *addr){
const char *displayname=linphone_address_get_display_name(addr);
if (!displayname) return linphone_address_as_string_uri_only(addr);
return ms_strdup(displayname);
}
unsigned long get_native_handle(GdkWindow *gdkw){
#ifdef __linux
return GDK_WINDOW_XID(gdkw);
#elif defined(WIN32)
return GDK_WINDOW_HWND(gdkw);
#elif defined(__APPLE__)
return gdk_quartz_window_get_nsview(gdkw);
#endif
g_warning("No way to get the native handle from gdk window");
return 0;
}
static gint resize_video_window(LinphoneCall *call){
const LinphoneCallParams *params=linphone_call_get_current_params(call);
if (params){
MSVideoSize vsize=linphone_call_params_get_received_video_size(params);
if (vsize.width>0 && vsize.height>0){
GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
GtkWidget *video_window=(GtkWidget*)g_object_get_data(G_OBJECT(callview),"video_window");
gint curw,curh;
if (video_window){
gtk_window_get_size(GTK_WINDOW(video_window),&curw,&curh);
if (vsize.width*vsize.height>curw*curh){
gtk_window_resize(GTK_WINDOW(video_window),vsize.width,vsize.height);
}
}
}
}
return TRUE;
}
static void on_video_window_destroy(GtkWidget *w, guint timeout){
g_source_remove(timeout);
}
static void on_video_window_key_press(GtkWidget *w, GdkEvent *ev, gpointer up){
g_message("Key press event");
switch(ev->key.keyval){
case GDK_KEY_f:
case GDK_KEY_F:
gtk_window_fullscreen(GTK_WINDOW(w));
break;
case GDK_KEY_Escape:
gtk_window_unfullscreen(GTK_WINDOW(w));
break;
}
}
GtkWidget *create_video_window(LinphoneCall *call){
char *remote,*title;
GtkWidget *video_window;
const LinphoneAddress *addr;
const char *icon_path=linphone_gtk_get_ui_config("icon",LINPHONE_ICON);
GdkPixbuf *pbuf=create_pixbuf(icon_path);
guint timeout;
MSVideoSize vsize=MS_VIDEO_SIZE_CIF;
GdkColor color;
addr=linphone_call_get_remote_address(call);
remote=linphone_gtk_address(addr);
video_window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
title=g_strdup_printf("%s - Video call with %s",linphone_gtk_get_ui_config("title","Linphone"),remote);
ms_free(remote);
gtk_window_set_title(GTK_WINDOW(video_window),title);
g_free(title);
if (pbuf){
gtk_window_set_icon(GTK_WINDOW(video_window),pbuf);
}
gtk_window_resize(GTK_WINDOW(video_window),vsize.width,vsize.height);
gdk_color_parse("black",&color);
gtk_widget_modify_bg(video_window,GTK_STATE_NORMAL,&color);
gtk_widget_show(video_window);
timeout=g_timeout_add(500,(GSourceFunc)resize_video_window,call);
g_signal_connect(video_window,"destroy",(GCallback)on_video_window_destroy,GINT_TO_POINTER(timeout));
g_signal_connect(video_window,"key-press-event",(GCallback)on_video_window_key_press,NULL);
return video_window;
}
void linphone_gtk_in_call_show_video(LinphoneCall *call){
GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
GtkWidget *video_window=(GtkWidget*)g_object_get_data(G_OBJECT(callview),"video_window");
const LinphoneCallParams *params=linphone_call_get_current_params(call);
LinphoneCore *lc=linphone_gtk_get_core();
if (linphone_call_get_state(call)!=LinphoneCallPaused && params && linphone_call_params_video_enabled(params)){
if (video_window==NULL){
video_window=create_video_window(call);
g_object_set_data(G_OBJECT(callview),"video_window",video_window);
}
linphone_core_set_native_video_window_id(lc,get_native_handle(gtk_widget_get_window(video_window)));
}else{
linphone_core_set_native_video_window_id(lc,(unsigned long)-1);
if (video_window){
gtk_widget_destroy(video_window);
g_object_set_data(G_OBJECT(callview),"video_window",NULL);
}
}
}
void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call){
GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
GtkWidget *status=linphone_gtk_get_widget(callview,"in_call_status");
......@@ -696,6 +810,8 @@ void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call){
gboolean in_conf=linphone_call_params_get_local_conference_mode(linphone_call_get_current_params(call));
GtkWidget *call_stats=(GtkWidget*)g_object_get_data(G_OBJECT(callview),"call_stats");
linphone_gtk_in_call_show_video(call);
display_peer_name_in_label(callee,linphone_call_get_remote_address (call));
gtk_widget_hide(linphone_gtk_get_widget(callview,"answer_decline_panel"));
......@@ -736,7 +852,7 @@ void linphone_gtk_in_call_view_set_paused(LinphoneCall *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),_("<b>Paused call</b>"));
linphone_gtk_in_call_show_video(call);
linphone_gtk_in_call_set_animation_image(callview,GTK_STOCK_MEDIA_PAUSE,TRUE);
}
......@@ -760,13 +876,15 @@ static gboolean in_call_view_terminated(LinphoneCall *call){
void linphone_gtk_in_call_view_terminate(LinphoneCall *call, const char *error_msg){
GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
GtkWidget *status;
GtkWidget *video_window;
gboolean in_conf;
guint taskid;
if(callview==NULL) return;
video_window=(GtkWidget*)g_object_get_data(G_OBJECT(callview),"video_window");
status=linphone_gtk_get_widget(callview,"in_call_status");
taskid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(callview),"taskid"));
in_conf=linphone_call_params_get_local_conference_mode(linphone_call_get_current_params(call));
gtk_widget_destroy(video_window);
if (status==NULL) return;
if (error_msg==NULL)
gtk_label_set_markup(GTK_LABEL(status),_("<b>Call ended.</b>"));
......
......@@ -48,6 +48,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define LINPHONE_VERSION LINPHONE_VERSION_DATE
#endif
#define LINPHONE_ICON "linphone.png"
enum {
COMPLETION_HISTORY,
COMPLETION_LDAP
......
......@@ -48,7 +48,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifdef ENABLE_NLS
#include <locale.h>
#endif
#define LINPHONE_ICON "linphone.png"
const char *this_program_ident_string="linphone_ident_string=" LINPHONE_VERSION;
......@@ -318,6 +318,7 @@ static void linphone_gtk_init_liblinphone(const char *config_file,
g_free(secrets_file);
linphone_core_enable_video_capture(the_core, TRUE);
linphone_core_enable_video_display(the_core, TRUE);
linphone_core_set_native_video_window_id(the_core,-1);/*don't create the window*/
if (no_video) {
_linphone_gtk_enable_video(FALSE);
linphone_gtk_set_ui_config_int("videoselfview",0);
......@@ -566,102 +567,6 @@ void linphone_gtk_show_about(){
gtk_widget_show(about);
}
static void set_video_window_decorations(GdkWindow *w){
const char *title=linphone_gtk_get_ui_config("title","Linphone");
const char *icon_path=linphone_gtk_get_ui_config("icon",LINPHONE_ICON);
char video_title[256];
GdkPixbuf *pbuf=create_pixbuf(icon_path);
if (!linphone_core_in_call(linphone_gtk_get_core())){
snprintf(video_title,sizeof(video_title),"%s video",title);
/* When not in call, treat the video as a normal window */
gdk_window_set_keep_above(w, FALSE);
}else{
LinphoneAddress *uri =
linphone_address_clone(linphone_core_get_current_call_remote_address(linphone_gtk_get_core()));
char *display_name;
linphone_address_clean(uri);
if (linphone_address_get_display_name(uri)!=NULL){
display_name=ms_strdup(linphone_address_get_display_name(uri));
}else{
display_name=linphone_address_as_string(uri);
}
snprintf(video_title,sizeof(video_title),_("Call with %s"),display_name);
linphone_address_destroy(uri);
ms_free(display_name);
/* During calls, bring up the video window, arrange so that
it is above all the other windows */
gdk_window_deiconify(w);
gdk_window_set_keep_above(w,TRUE);
/* Maybe we should have the following, but then we want to
have a timer that turns it off after a little while. */
/* gdk_window_set_urgency_hint(w,TRUE); */
}
gdk_window_set_title(w,video_title);
/* Refrain the video window to be closed at all times. */
gdk_window_set_functions(w,
GDK_FUNC_RESIZE|GDK_FUNC_MOVE|
GDK_FUNC_MINIMIZE|GDK_FUNC_MAXIMIZE);
if (pbuf){
GList *l=NULL;
l=g_list_append(l,pbuf);
gdk_window_set_icon_list(w,l);
g_list_free(l);
g_object_unref(G_OBJECT(pbuf));
}
}
static gboolean video_needs_update=FALSE;
static void update_video_title(){
video_needs_update=TRUE;
}
static void update_video_titles(LinphoneCore *lc){
unsigned long id;
static unsigned long previd=0;
static unsigned long preview_previd=0;
id=linphone_core_get_native_video_window_id(lc);
if (id!=previd || video_needs_update){
GdkWindow *w;
previd=id;
if (id!=0){
ms_message("Updating window decorations");
#ifndef WIN32
w=gdk_window_foreign_new((GdkNativeWindow)id);
#else
w=gdk_window_foreign_new((HANDLE)id);
#endif
if (w) {
set_video_window_decorations(w);
g_object_unref(G_OBJECT(w));
}
else ms_error("gdk_window_foreign_new() failed");
if (video_needs_update) video_needs_update=FALSE;
}
}
id=linphone_core_get_native_preview_window_id (lc);
if (id!=preview_previd ){
GdkWindow *w;
preview_previd=id;
if (id!=0){
ms_message("Updating window decorations for preview");
#ifndef WIN32
w=gdk_window_foreign_new((GdkNativeWindow)id);
#else
w=gdk_window_foreign_new((HANDLE)id);
#endif
if (w) {
set_video_window_decorations(w);
g_object_unref(G_OBJECT(w));
}
else ms_error("gdk_window_foreign_new() failed");
if (video_needs_update) video_needs_update=FALSE;
}
}
}
static gboolean linphone_gtk_iterate(LinphoneCore *lc){
static gboolean first_time=TRUE;
......@@ -677,7 +582,6 @@ static gboolean linphone_gtk_iterate(LinphoneCore *lc){
first_time=FALSE;
}
update_video_titles(lc);
if (addr_to_call!=NULL){
/*make sure we are not showing the login screen*/
GtkWidget *mw=linphone_gtk_get_main_window();
......@@ -928,7 +832,6 @@ void linphone_gtk_call_terminated(LinphoneCall *call, const char *error){
}
if (linphone_gtk_use_in_call_view() && call)
linphone_gtk_in_call_view_terminate(call,error);
update_video_title();
}
static void linphone_gtk_update_call_buttons(LinphoneCall *call){
......@@ -971,7 +874,6 @@ static void linphone_gtk_update_call_buttons(LinphoneCall *call){
linphone_gtk_enable_transfer_button(lc,FALSE);
linphone_gtk_enable_conference_button(lc,FALSE);
}
update_video_title();
if (call) {
linphone_gtk_update_video_button(call);
}
......
mediastreamer2 @ c0c0c4c3
Subproject commit 4464c094410dd4396b3563798031ed50ae90d8c8
Subproject commit c0c0c4c351953cde12e68068fd9de4ad483e7daa
oRTP @ 72de9096
Subproject commit ab97ce3975b56bd84bcec900cfdd565c3e300599
Subproject commit 72de9096de5e4aba0dfd9dbcb4406a6753e7fe68
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment