From: Darren S. <ds...@us...> - 2005-06-08 20:12:36
|
Update of /cvsroot/xine/gnome-xine/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5030/src Modified Files: globals.h gtkvideo.c gtkvideo.h menu.c menu.h noskin_window.c player.c Log Message: Window resize changes. The scale factor is computed dynamically when you resize the window. It is then displayed in the View->Window menu unless it matches one of the presets (in which case the previous value, if there was one, remains available). This needs some testing - watch out for incorrect scaling and scale values. I'm reasonably sure that there's a race somewhere... Index: globals.h =================================================================== RCS file: /cvsroot/xine/gnome-xine/src/globals.h,v retrieving revision 1.27 retrieving revision 1.28 diff -u -r1.27 -r1.28 --- globals.h 11 May 2005 20:13:17 -0000 1.27 +++ globals.h 8 Jun 2005 20:12:22 -0000 1.28 @@ -49,7 +49,7 @@ extern pthread_mutex_t engine_lock; typedef struct { - GtkToggleAction *fullscreen, *auto_resize, *auto_rescale, + GtkToggleAction *fullscreen, *resize_factor, *auto_resize, *auto_rescale, *deinterlace, *vo_postproc, *ao_postproc, *toolbar; GSList *aspect, *vis, *toolbar_pos, *video_size, *subtitles; } action_items_t; Index: gtkvideo.c =================================================================== RCS file: /cvsroot/xine/gnome-xine/src/gtkvideo.c,v retrieving revision 1.59 retrieving revision 1.60 diff -u -r1.59 -r1.60 --- gtkvideo.c 6 Jun 2005 17:16:00 -0000 1.59 +++ gtkvideo.c 8 Jun 2005 20:12:24 -0000 1.60 @@ -124,8 +124,14 @@ double display_ratio; - gboolean auto_resize, auto_rescale, pending_resize; - GtkRequisition pos, size, video_size, oldsize; + /* On exit from full-screen mode, we get multiple allocate events. + * Consequently, there may be multiple rescalings. + * We *don't* necessarily want to signal them. + */ + gboolean block_next_scale_change:8; + + gboolean auto_resize:8, auto_rescale:8, pending_resize:8; + GtkRequisition pos, size, video_size, old_video_size; float resize_factor; guint resizing; @@ -135,7 +141,7 @@ /* fullscreen stuff */ - gboolean fullscreen_mode, pointer_visible; + gboolean fullscreen_mode:8, pointer_visible:8; GtkRequisition fullscreen; Cursor pointer[2]; guint pointer_hide_timeout, screen_blanker_timeout; @@ -275,7 +281,7 @@ G_STRUCT_OFFSET (GtkVideoClass, keypress), NULL, NULL, g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); + G_TYPE_NONE, 1, GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); gtv_table_signals[GTK_VIDEO_KEYRELEASE] = g_signal_new ("keyrelease", @@ -284,7 +290,16 @@ G_STRUCT_OFFSET (GtkVideoClass, keyrelease), NULL, NULL, g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); + G_TYPE_NONE, 1, GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); + + gtv_table_signals[GTK_VIDEO_SCALE_FACTOR] = + g_signal_new ("scale-factor-changed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkVideoClass, scale_factor), + NULL, NULL, + g_cclosure_marshal_VOID__DOUBLE, + G_TYPE_NONE, 1, G_TYPE_DOUBLE); if (!key_snoop) key_snoop = gtk_key_snooper_install (key_snoop_cb, NULL); @@ -305,6 +320,11 @@ gtv = NULL; } +#define SCALE(factor) \ + (GtkRequisition) { \ + round (priv->video_size.width * (factor) / 100), \ + round (priv->video_size.height * (factor) / 100) \ + } #define IS_DOUBLE(W,H) (priv->auto_rescale \ && (W) <= priv->fullscreen.width / 3.0 \ @@ -325,14 +345,6 @@ GtkVideo *gv = (GtkVideo *) gv_gen; gtk_video_private_t *priv = gv->priv; - /* correct size with video_pixel_aspect */ -/* - if (video_pixel_aspect >= priv->display_ratio) - video_size.width = video_size.width * video_pixel_aspect / priv->display_ratio + .5; - else - video_size.height = video_size.height * priv->display_ratio / video_pixel_aspect + .5; - */ - if (priv->fullscreen_mode) { *dest_width = priv->fullscreen.width; *dest_height = priv->fullscreen.height; @@ -353,16 +365,13 @@ gtk_video_private_t *priv = gtv->priv; double factor = DOUBLE_STD(); - GtkRequisition video_size = { - priv->video_size.width * factor, priv->video_size.height * factor - }; + GtkRequisition video_size = SCALE (factor); XLockDisplay (priv->display); gdk_threads_enter (); logprintf ("gtkvideo: idle resize to %d x %d (factor %lf)\n", video_size.width, video_size.height, factor); - priv->resizing = 0; priv->size = video_size; if (priv->fullscreen_mode) @@ -389,6 +398,7 @@ logprintf ("gtkvideo: idle signal done\n"); } + priv->resizing = 0; gdk_threads_leave (); XUnlockDisplay (priv->display); } @@ -427,14 +437,17 @@ RESIZE_LOCK (); { double factor = DOUBLE(priv->resize_factor, video_width, video_height); - video_width *= factor; - video_height *= factor; + video_width = round (video_width * factor / 100); + video_height = round (video_height * factor / 100); /* size changed? */ if (video_width != priv->size.width || video_height != priv->size.height) { if (priv->fullscreen_mode) + { priv->size = (GtkRequisition){ video_width, video_height }; + priv->pending_resize = TRUE; + } else RESIZE_ADD_NOLOCK (); } @@ -984,7 +997,7 @@ priv->xine = xine; priv->stream = stream; priv->out = out; - priv->resize_factor = 0.5; + priv->resize_factor = 50; priv->auto_resize = TRUE; priv->size = (GtkRequisition){ default_width, default_height }; priv->video_size = priv->size; @@ -1031,7 +1044,7 @@ if (GTK_WIDGET_REALIZED (widget)) { - XLockDisplay (this->priv->display); + gboolean send_signal = FALSE; widget->allocation = *allocation; if (this->priv->fullscreen_mode) { @@ -1041,7 +1054,45 @@ gdk_window_move_resize (widget->window, allocation->x, allocation->y, widget->allocation.width, widget->allocation.height); - XUnlockDisplay (this->priv->display); + if (this->priv->old_video_size.width && !this->priv->resizing && !this->priv->fullscreen_mode) + { + gtk_video_private_t *const priv = this->priv; + gboolean is_double = + IS_DOUBLE(priv->old_video_size.width, priv->old_video_size.height); + double new_factor = + this->widget.allocation.width * 100 + / (double)priv->old_video_size.width / (1 + is_double); + double new_factor_V = + this->widget.allocation.height * 100 + / (double)priv->old_video_size.height / (1 + is_double); + if (new_factor > new_factor_V) + new_factor= new_factor_V; + /* tolerate rounding error when the video size has been changed... */ + if (round (priv->resize_factor * 64) != round (new_factor * 64) + && (fabs (new_factor - priv->resize_factor) + >= 25 / this->widget.allocation.height + || priv->old_video_size.height == priv->video_size.height)) + { + priv->resize_factor = new_factor; + send_signal = TRUE; + /* stop frame_output_cb from scheduling a resize */ + double factor = DOUBLE_STD(); + priv->size = SCALE (factor); + logprintf ("gxine: video rescaled to %lf%%\n", new_factor); + } + } + if (!this->priv->resizing) + this->priv->old_video_size = this->priv->video_size; + + if (send_signal) + { + if (this->priv->block_next_scale_change) + this->priv->block_next_scale_change = FALSE; + else + g_signal_emit ((GObject *)this, + gtv_table_signals[GTK_VIDEO_SCALE_FACTOR], 0, + this->priv->resize_factor); + } } else widget->allocation = *allocation; @@ -1070,29 +1121,21 @@ gtk_widget_size_request (toplevel, &req); do_pending_events (); XUnlockDisplay (gtv->priv->display); - gtv->widget.allocation.width = size->width > req.width - ? size->width : req.width; } - else - gtv->widget.allocation.width = size->width; - gtv->widget.allocation.height = size->height; gtk_widget_set_size_request (>v->widget, MIN_WIDTH, MIN_HEIGHT); } -void gtk_video_rescale (GtkVideo *gtv, float scale) +void gtk_video_rescale (GtkVideo *gtv, double scale) { RESIZE_LOCK (); { gtk_video_private_t *priv = gtv->priv; - double factor = DOUBLE(scale, priv->video_size.width, + double factor = DOUBLE (scale, priv->video_size.width, priv->video_size.height); - GtkRequisition size = { - priv->video_size.width * factor + .5, - priv->video_size.height * factor + .5 - }; - priv->size = size; - priv->resize_factor = scale; - + priv->size = SCALE (factor); + priv->resize_factor = scale; + logprintf ("rescale: size = %d,%d factor=%f\n", + priv->size.width, priv->size.height, scale); if (priv->fullscreen_mode) priv->pending_resize = TRUE; else @@ -1121,11 +1164,6 @@ if (fullscreen) { do_pending_events (); /* there may be pending resize events... */ - if (toplevel) - gtk_window_get_size ((GtkWindow *)toplevel, - &priv->oldsize.width, &priv->oldsize.height); - else - priv->oldsize.width = 0; gtk_window_fullscreen (toplevel); gtk_window_set_keep_above (toplevel, TRUE); gtk_window_stick (toplevel); @@ -1136,21 +1174,17 @@ } else { + priv->block_next_scale_change = priv->pending_resize; gtk_window_unstick (toplevel); gtk_window_set_keep_above (toplevel, FALSE); gtk_window_unfullscreen (toplevel); g_source_remove (priv->screen_blanker_timeout); gtv_show_pointer (gtv); gdk_flush (); - do_pending_events (); /* events have been generated - process them */ /* resize the window, one way or another */ - if (toplevel) - gtk_window_resize ((GtkWindow *)toplevel, - priv->oldsize.width, priv->oldsize.height); if (priv->pending_resize) - gtv_do_rescale (gtv); - + gtv_do_rescale ((GtkVideo *)gtv); } XUnlockDisplay (priv->display); Index: gtkvideo.h =================================================================== RCS file: /cvsroot/xine/gnome-xine/src/gtkvideo.h,v retrieving revision 1.13 retrieving revision 1.14 diff -u -r1.13 -r1.14 --- gtkvideo.h 30 May 2005 19:09:53 -0000 1.13 +++ gtkvideo.h 8 Jun 2005 20:12:24 -0000 1.14 @@ -36,6 +36,7 @@ enum { GTK_VIDEO_KEYPRESS, /* caught keypress in fullscreen mode */ GTK_VIDEO_KEYRELEASE, /* caught keyrelease in fullscreen mode */ + GTK_VIDEO_SCALE_FACTOR, /* video scale has been changed by a resize */ LAST_SIGNAL }; @@ -60,8 +61,9 @@ struct _GtkVideoClass { GtkWidgetClass parent_class; - void (*keypress) (GtkWidget *gtv); - void (*keyrelease) (GtkWidget *gtv); + void (*keypress) (GtkWidget *, GdkEventKey *, gpointer); + void (*keyrelease) (GtkWidget *, GdkEventKey *, gpointer); + void (*scale_factor) (GtkWidget *, double, gpointer); }; GtkType gtk_video_get_type (void); @@ -77,7 +79,7 @@ gint x, gint y, gint width, gint height); - void gtk_video_rescale (GtkVideo *gtv, float scale); + void gtk_video_rescale (GtkVideo *gtv, double scale); xine_video_port_t *gtk_video_get_port (GtkVideo *gtv); gboolean gtk_video_is_fullscreen (GtkVideo *gtv) ; void gtk_video_set_fullscreen (GtkVideo *gtv, gboolean fullscreen); Index: menu.c =================================================================== RCS file: /cvsroot/xine/gnome-xine/src/menu.c,v retrieving revision 1.51 retrieving revision 1.52 diff -u -r1.51 -r1.52 --- menu.c 3 Jun 2005 18:36:53 -0000 1.51 +++ menu.c 8 Jun 2005 20:12:24 -0000 1.52 @@ -247,7 +247,12 @@ #define JS_CB_R(func) \ static always_inline void js_##func##_cb_int (int); \ static void js_##func##_cb (GtkRadioAction *action, gpointer data) \ - { js_##func##_cb_int (gtk_radio_action_get_current_value (action)); } \ + { \ + gint value, current = gtk_radio_action_get_current_value (action); \ + g_object_get ((GObject *)action, "value", &value, NULL); \ + if (value != current) \ + js_##func##_cb_int (current); \ + } \ static always_inline void js_##func##_cb_int (int v) /* function body goes here */ @@ -281,7 +286,7 @@ } JS_CB_T (FSToolbarVisible) { window_toolbar_show (v); } JS_CB_R (FSToolbarPos) { window_toolbar_position (v); } -JS_CB_R (Window) { gtk_video_rescale (GTK_VIDEO(gtv), (double) v / 100.0); } +JS_CB_R (Window) { gtk_video_rescale (GTK_VIDEO(gtv), (double) v / 1e+6); } JS_CB_T (WindowAutosize) { gtk_video_set_auto_resize (GTK_VIDEO(gtv), v); } JS_CB_T (WindowMagLow) { gtk_video_set_auto_rescale (GTK_VIDEO(gtv), v); } JS_CB (ZoomIn, "vo_zoom.v += 5;") @@ -400,9 +405,10 @@ }, window_actions[] = { { "WindowOther", NULL, "", NULL, NULL, 0 }, - { "Window50", NULL, N_("_50%"), NULL, NULL, 50 }, - { "Window100", NULL, N_("_100%"), NULL, NULL, 100 }, - { "Window200", NULL, N_("_200%"), NULL, NULL, 200 }, + { "Window50", NULL, N_("_50%"), NULL, NULL, 50e+6 }, + { "Window100", NULL, N_("_100%"), NULL, NULL, 100e+6 }, + { "Window200", NULL, N_("_200%"), NULL, NULL, 200e+6 }, + { "WindowDynamic", NULL, "", NULL, NULL, -1 }, }, aspect_actions[] = { { "AspectAuto", NULL, N_("_Auto"), NULL, NULL, XINE_VO_ASPECT_AUTO }, @@ -456,6 +462,8 @@ "<menuitem action='Window50' />\n" "<menuitem action='Window100' />\n" "<menuitem action='Window200' />\n" + "<menuitem action='WindowDynamic' />\n" + "<separator />\n" "<menuitem action='WindowAutosize' />\n" "<menuitem action='WindowMagLow' />\n" "</menu>\n" @@ -535,10 +543,48 @@ } } +GtkAction *find_video_size_action (gdouble factor) +{ + GSList *action; + gint value, zoom = factor * 1e+6; + foreach_glist (action, action_items.video_size) + if (action->data != action_items.resize_factor /* ignore "Other" */ + && (g_object_get (action->data, "value", &value, NULL), value) == zoom) + return action->data; + foreach_glist (action, action_items.video_size) + if (action->data == action_items.resize_factor /* require "Other" */ + && (g_object_get (action->data, "value", &value, NULL), value) == zoom) + return action->data; + return NULL; +} + +void scale_changed_cb (GtkWidget *widget, gdouble factor, gpointer data) +{ + logprintf ("gxine: received scale change event (%lf%%)\n", factor); + if (action_items.resize_factor && !find_video_size_action (factor)) + { + char *label = g_strdup_printf (_("_Other (%.1lf%%)"), factor); + g_object_set ((GObject *)action_items.resize_factor, "label", label, NULL); + free (label); + GSList *changed; + foreach_glist (changed, gtk_radio_action_get_group + (GTK_RADIO_ACTION (action_items.resize_factor))) + if (g_signal_handlers_block_by_func (changed->data, js_Window_cb, NULL)) + break; + g_object_set ((GObject *)action_items.resize_factor, + "value", (gint)(factor * 1e+6), NULL); + gtk_action_set_visible ((GtkAction *)action_items.resize_factor, TRUE); + gtk_toggle_action_set_active ((GtkToggleAction *)action_items.resize_factor, TRUE); + do_pending_events (); + if (changed) + g_signal_handlers_unblock_by_func (changed->data, js_Window_cb, NULL); + } +} + void create_menus (GtkWidget *window) { GtkActionGroup *action; - static const int scale[] = { 50, 100, 200 }; + static const int scale[] = { 50e+6, 100e+6, 200e+6 }; ui = ui_create_manager ("gxine", window); action = ui_get_action_group (ui); @@ -579,6 +625,8 @@ gtk_ui_manager_ensure_update (ui); action_items.fullscreen = get_toggle ("Fullscreen"); + action_items.resize_factor = get_toggle ("WindowDynamic"); + gtk_action_set_visible (GTK_ACTION(action_items.resize_factor), FALSE); action_items.auto_resize = get_toggle ("WindowAutosize"); action_items.auto_rescale = get_toggle ("WindowMagLow"); action_items.deinterlace = get_toggle ("Deinterlace"); Index: menu.h =================================================================== RCS file: /cvsroot/xine/gnome-xine/src/menu.h,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- menu.h 11 May 2005 20:13:18 -0000 1.5 +++ menu.h 8 Jun 2005 20:12:25 -0000 1.6 @@ -30,4 +30,8 @@ const char *const label, guint merge, size_t count); const char *menu_get_tree_name (int); +/* signal callback & support for dynamic scale changes */ +void scale_changed_cb (GtkWidget *, gdouble, gpointer); +GtkAction *find_video_size_action (gdouble); + #endif Index: noskin_window.c =================================================================== RCS file: /cvsroot/xine/gnome-xine/src/noskin_window.c,v retrieving revision 1.64 retrieving revision 1.65 diff -u -r1.64 -r1.65 --- noskin_window.c 6 Jun 2005 00:06:26 -0000 1.64 +++ noskin_window.c 8 Jun 2005 20:12:25 -0000 1.65 @@ -570,10 +570,12 @@ G_CALLBACK (keypress_cb), NULL); g_signal_connect (G_OBJECT (gtv), "keyrelease", G_CALLBACK (keyrelease_cb), NULL); + g_signal_connect (G_OBJECT (gtv), "scale-factor-changed", + G_CALLBACK (scale_changed_cb), NULL); if (xine_config_lookup_entry (xine, "gui.window_size", &entry)) { - static const float scale[] = { 0.5, 1, 2 }; + static const gdouble scale[] = { 50, 100, 200 }; gtk_video_rescale ((GtkVideo *)gtv, scale[entry.num_value]); } if (xine_config_lookup_entry (xine, "gui.magnify_lowres_video", &entry)) Index: player.c =================================================================== RCS file: /cvsroot/xine/gnome-xine/src/player.c,v retrieving revision 1.41 retrieving revision 1.42 diff -u -r1.41 -r1.42 --- player.c 4 Jun 2005 15:45:36 -0000 1.41 +++ player.c 8 Jun 2005 20:12:25 -0000 1.42 @@ -30,6 +30,7 @@ #include <gtk/gtkradiomenuitem.h> #include "globals.h" +#include "menu.h" #include "ui.h" #include "utils.h" #include "playlist.h" @@ -540,6 +541,7 @@ se_t *se = (se_t *) JS_GetContextPrivate(cx); int zoom; + GtkAction *action; se_log_fncall ("set_video_size"); se_argc_check (1, "set_video_size"); @@ -552,20 +554,15 @@ else if (zoom>XINE_VO_ZOOM_MAX) zoom = XINE_VO_ZOOM_MAX; - switch (zoom) + /* find & activate an action item which corresponds to the requested scale */ + action = find_video_size_action (zoom); + if (action) + gtk_action_activate (action); + else { - case 50: - gtk_action_activate (action_items.video_size->next->next->data); - break; - case 100: - gtk_action_activate (action_items.video_size->next->data); - break; - case 200: - gtk_action_activate (action_items.video_size->data); - break; - default: /* not in menu */ - gtk_action_activate (action_items.video_size->next->next->next->data); - gtk_video_rescale (GTK_VIDEO(gtv), (double) zoom / 100.0); + scale_changed_cb (NULL, zoom, NULL); + do_pending_events (); + gtk_video_rescale (gtv, zoom); } return JS_TRUE; |