509
531
gtk_widget_set_size_request (>v->widget, size->width, size->height);
510
532
if (GTK_WIDGET_REALIZED(>v->widget) && gtv->widget.parent)
535
GtkWindow *toplevel = GTK_WINDOW (gtk_widget_get_toplevel (>v->widget));
536
if (toplevel->bin.child == >v->widget)
538
geom.min_width = size->width;
539
geom.min_height = size->height;
540
gtk_window_set_geometry_hints (toplevel, >v->widget, &geom,
512
543
gtk_window_resize ((GtkWindow *)gtk_widget_get_toplevel (>v->widget),
513
GTK_VIDEO_MIN_WIDTH, 1); /* note controlling geometry */
544
size->width, size->height); /* note controlling geometry */
545
if (toplevel->bin.child == >v->widget)
547
geom.min_aspect = geom.max_aspect = (double)size->width / (double)size->height;
548
gtk_window_set_geometry_hints (toplevel, >v->widget, &geom,
514
551
gtk_video_allow_shrink (gtv);
581
619
else if (!priv->pending_resize)
583
gtv_do_resize (gtv, &priv->size);
622
gtv_do_resize (gtv, &priv->size);
624
send_signal = gtv_update_resize_factor (gtv);
584
625
logprintf ("gtkvideo: idle signal done\n");
588
gtv_do_rescale (gtv);
630
gtv_do_rescale (gtv);
632
send_signal = gtv_update_resize_factor (gtv);
589
633
logprintf ("gtkvideo: idle signal done, pending resize handled\n");
637
g_signal_emit ((GObject *)gtv,
638
gtv_table_signals[GTK_VIDEO_SCALE_FACTOR], 0,
639
priv->resize_factor);
592
641
priv->resizing = 0;
593
642
priv->idle_resized = TRUE;
650
static gboolean gtk_video_idle_resize (GtkVideo *gtv)
652
return gtv_idle_resize (gtv, TRUE);
655
static gboolean gtk_video_idle_no_resize (GtkVideo *gtv)
657
return gtv_idle_resize (gtv, FALSE);
660
static gboolean end_time_check (gtk_video_private_t *priv)
662
gint pos_stream, pos_time, length_time;
663
priv->end_time_id = 0;
664
if (!xine_get_pos_length (stream, &pos_stream, &pos_time, &length_time))
665
pos_stream = pos_time = length_time = 0;
666
if (priv->end_time && pos_time >= priv->end_time)
668
logprintf ("gtkvideo: end time passed, sending stop event\n");
670
xine_stream_t *stream = priv->stream;
671
xine_set_param (stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE);
672
xine_event_t event = {
673
.type = XINE_EVENT_UI_PLAYBACK_FINISHED,
677
xine_event_send (stream, &event);
601
682
static void frame_output_cb (void *gv_gen,
602
683
int video_width, int video_height,
603
684
double video_pixel_aspect,
667
747
*dest_pixel_aspect = priv->display_ratio;
749
if (priv->end_time && !priv->end_time_id)
750
priv->end_time_id = g_idle_add ((GSourceFunc) end_time_check, priv);
754
if (priv->frame_cb_id)
755
g_source_remove (priv->frame_cb_id);
756
priv->frame_cb_id = g_idle_add (priv->frame_cb, priv->frame_cb_data);
761
# ifdef ENABLE_X11_VO
762
static xine_video_port_t *
763
gxine_open_video_driver (xine_t * self, const char *id, void *xcb, void *x11)
765
return xine_open_video_driver (self, id, XINE_VISUAL_TYPE_XCB, xcb)
766
? : xine_open_video_driver (self, id, XINE_VISUAL_TYPE_X11, x11);
768
# else /* ! ENABLE_X11_VO */
769
# define gxine_open_video_driver(SELF,ID,XCB,X11) \
770
xine_open_video_driver ((SELF), (ID), XINE_VISUAL_TYPE_XCB, (XCB))
772
#else /* ! HAVE_XCB */
773
# define gxine_open_video_driver(SELF,ID,X11,UNUSED) \
774
xine_open_video_driver ((SELF), (ID), XINE_VISUAL_TYPE_X11, (X11))
670
777
static xine_video_port_t *load_video_out_driver (GtkVideo *this)
672
779
double res_h, res_v;
674
781
const char *video_driver_id;
675
782
xine_video_port_t *video_port;
676
783
gtk_video_private_t *priv = this->priv;
678
788
vis.display = gtv_get_xdisplay (this);
679
789
vis.screen = gtv_get_xscreen_num (this);
680
790
vis.d = priv->video_window;
681
res_h = (DisplayWidth (vis.display, vis.screen)*1000
682
/ DisplayWidthMM (vis.display, vis.screen));
683
res_v = (DisplayHeight (vis.display, vis.screen)*1000
684
/ DisplayHeightMM (vis.display, vis.screen));
685
priv->display_ratio = res_v / res_h;
791
mm_h = DisplayWidthMM (vis.display, vis.screen);
792
res_h = DisplayWidth (vis.display, vis.screen);
793
mm_v = DisplayHeightMM (vis.display, vis.screen);
794
res_v = DisplayHeight (vis.display, vis.screen);
798
xcb_connection_t *connection = xcb_connect(NULL, &screen_no);
799
xcb_screen_iterator_t screen_it;
805
screen_it = xcb_setup_roots_iterator (xcb_get_setup (connection));
806
while (screen_it.rem > 1 && screen_no > 0)
808
xcb_screen_next (&screen_it);
812
vis.connection = connection;
813
vis.screen = screen_it.data;
814
vis.window = priv->video_window;
817
x11vis.display = gtv_get_xdisplay (this);
818
x11vis.screen = gtv_get_xscreen_num (this);
819
x11vis.d = priv->video_window;
822
/* why can't the 'Merkians spell "millimetre" correctly... */
823
mm_h = screen_it.data->width_in_millimeters;
824
res_h = screen_it.data->width_in_pixels;
825
mm_v = screen_it.data->height_in_millimeters;
826
res_v = screen_it.data->height_in_pixels;
827
#endif /* HAVE_XCB */
829
char *desc = g_strdup_printf (_("The reported value is %dmm."), mm_h);
830
mm = xine_config_register_range (priv->xine, "video.display_width",
832
N_("display width in mm\n(0 = autodetect)"), desc,
834
res_h = res_h * 1000 / (mm ? mm : mm_h);
837
desc = g_strdup_printf (_("The reported value is %dmm."), mm_v);
838
mm = xine_config_register_range (priv->xine, "video.display_height",
840
N_("display height in mm\n(0 = autodetect, -1 = assume square pixels)"), desc,
842
res_v = mm < 0 ? res_h : (res_v * 1000 / (mm ? mm : mm_v));
845
priv->display_ratio = (res_h <= 0.0 || res_v <= 0.0) ? 1 : res_v / res_h;
687
846
if (fabs(priv->display_ratio - 1.0) < 0.01)
688
847
priv->display_ratio = 1.0;
691
850
vis.frame_output_cb = frame_output_cb;
692
851
vis.user_data = this;
694
if (priv->video_driver_id)
695
video_driver_id = priv->video_driver_id;
698
char **choices = get_driver_ids (xine_list_video_output_plugins (priv->xine));
699
/* try to init video with stored information */
700
int i = xine_config_register_enum (priv->xine,
703
N_("video driver to use"),
704
NULL, 10, NULL, NULL);
705
video_driver_id = choices[i];
854
x11vis.dest_size_cb = dest_size_cb;
855
x11vis.frame_output_cb = frame_output_cb;
856
x11vis.user_data = this;
859
char **choices = get_driver_ids (xine_list_video_output_plugins (priv->xine));
860
/* try to init video with stored information */
861
int i = xine_config_register_enum (priv->xine,
862
"video.driver", 0, choices,
863
N_("video driver to use"),
864
NULL, 10, NULL, NULL);
865
video_driver_id = priv->video_driver_id ? : choices[i];
707
867
if (strcmp (video_driver_id, "auto"))
709
video_port=xine_open_video_driver (priv->xine,
711
XINE_VISUAL_TYPE_X11,
869
video_port = gxine_open_video_driver (priv->xine, video_driver_id,
870
(void *) &vis, (void *) &x11vis);
714
872
return video_port;
716
g_printerr (_("gtkvideo: video driver %s failed.\n"),
874
g_printerr (_("gtkvideo: video driver %s failed.\n"),
717
875
video_driver_id); /* => auto-detect */
720
return xine_open_video_driver (priv->xine, NULL,
721
XINE_VISUAL_TYPE_X11,
878
video_port = gxine_open_video_driver (priv->xine, NULL,
879
(void *) &vis, (void *) &x11vis);
884
g_printerr (_("gtkvideo: video driver %s failed.\n"), "auto");
885
return gxine_open_video_driver (priv->xine, "none",
886
(void *) &vis, (void *) &x11vis);
889
uint32_t gtk_video_get_capabilities (GtkVideo *this)
891
gtk_video_private_t *priv = this->priv;
892
return priv->video_port->get_capabilities (priv->video_port);
725
895
static void gtv_send_xine_mouse_event (gtk_video_private_t *priv,
763
933
if (!xev->xexpose.count)
764
936
xine_port_send_gui_data (priv->video_port,
765
937
XINE_GUI_SEND_EXPOSE_EVENT, xev);
939
xcb_expose_event_t xcb_event;
940
memset(&xcb_event, 0, sizeof(xcb_event));
942
xcb_event.window = xev->xexpose.window;
943
xcb_event.x = xev->xexpose.x;
944
xcb_event.y = xev->xexpose.y;
945
xcb_event.width = xev->xexpose.width;
946
xcb_event.height = xev->xexpose.height;
947
xcb_event.count = xev->xexpose.count;
949
xine_port_send_gui_data (priv->video_port,
950
XINE_GUI_SEND_EXPOSE_EVENT, &xcb_event);
766
953
logprintf ("gtkvideo: expose event: %d,%d %dx%d %d\n",
767
954
xev->xexpose.x, xev->xexpose.y,
768
955
xev->xexpose.width, xev->xexpose.height, xev->xexpose.count);
1040
1227
widget->allocation.height, 0,
1041
1228
black_pixel.pixel, black_pixel.pixel);
1230
/* not sure why this is needed in some situations... */
1232
XCheckWindowEvent (xdisplay, priv->video_window, -1, &event);
1043
1234
widget->window = gdk_window_foreign_new_for_display
1044
1235
(display, priv->video_window);
1236
if (!widget->window)
1238
g_printerr (_("gtkvideo: couldn't get a GDK handle for the video window!\n"));
1045
1241
gdk_window_set_user_data (widget->window, widget); /* allow GTK events */
1047
1243
/* enforce background colour */
1410
void gtk_video_set_frame_cb (GtkVideo *gtv, gtk_video_frame_cb_t cb,
1413
g_return_if_fail (GTK_IS_VIDEO(gtv));
1414
gtv->priv->frame_cb = cb;
1415
gtv->priv->frame_cb_data = data;
1418
void gtk_video_set_end_time (GtkVideo *gtv, gint end_time)
1420
g_return_if_fail (GTK_IS_VIDEO(gtv));
1421
gtv->priv->end_time = end_time;
1424
static gboolean gtv_update_resize_factor (GtkVideo *this)
1426
gboolean send_signal = FALSE;
1427
gtk_video_private_t *const priv = this->priv;
1429
if (priv->pending_resize)
1430
new_factor = priv->resize_factor;
1433
gboolean is_double =
1434
IS_DOUBLE(priv->video_size.width, priv->video_size.height);
1435
new_factor = this->widget.allocation.width * 100
1436
/ (double)priv->video_size.width / (1 + is_double);
1437
double new_factor_V = this->widget.allocation.height * 100
1438
/ (double)priv->video_size.height
1440
if (new_factor > new_factor_V)
1441
new_factor= new_factor_V;
1443
/* tolerate rounding error when the video size has been changed... */
1444
if (priv->pending_resize
1445
|| (round (priv->resize_factor * 64) != round (new_factor * 64)
1446
&& (fabs (new_factor - priv->resize_factor)
1447
>= 25 / this->widget.allocation.height
1448
|| priv->old_video_size.height == priv->video_size.height)))
1450
if (!priv->block_next_scale_change && GTK_WIDGET_VISIBLE (&this->widget))
1452
priv->resize_factor = new_factor;
1454
/* stop frame_output_cb from scheduling a resize */
1455
double factor = DOUBLE_STD();
1456
priv->size = SCALE (factor);
1457
logprintf ("gxine: video rescaled to %lf%%\n", new_factor);
1460
logprintf ("blocked rescaling to %lf%%\n", new_factor);
1213
1465
static void gtk_video_size_allocate (GtkWidget *widget,
1214
1466
GtkAllocation *allocation)
1238
1490
&& GTK_WIDGET_VISIBLE (widget)
1239
1491
&& widget->allocation.width > GTK_VIDEO_MIN_WIDTH
1240
1492
&& widget->allocation.height > GTK_VIDEO_MIN_HEIGHT)
1242
gtk_video_private_t *const priv = this->priv;
1244
if (priv->pending_resize)
1245
new_factor = priv->resize_factor;
1248
gboolean is_double =
1249
IS_DOUBLE(priv->old_video_size.width, priv->old_video_size.height);
1250
new_factor = this->widget.allocation.width * 100
1251
/ (double)priv->old_video_size.width / (1 + is_double);
1252
double new_factor_V = this->widget.allocation.height * 100
1253
/ (double)priv->old_video_size.height
1255
if (new_factor > new_factor_V)
1256
new_factor= new_factor_V;
1258
/* tolerate rounding error when the video size has been changed... */
1259
if (priv->pending_resize
1260
|| (round (priv->resize_factor * 64) != round (new_factor * 64)
1261
&& (fabs (new_factor - priv->resize_factor)
1262
>= 25 / this->widget.allocation.height
1263
|| priv->old_video_size.height == priv->video_size.height)))
1265
if (!priv->block_next_scale_change && GTK_WIDGET_VISIBLE (widget))
1267
priv->resize_factor = new_factor;
1269
/* stop frame_output_cb from scheduling a resize */
1270
double factor = DOUBLE_STD();
1271
priv->size = SCALE (factor);
1272
logprintf ("gxine: video rescaled to %lf%%\n", new_factor);
1275
logprintf ("blocked rescaling to %lf%%\n", new_factor);
1493
send_signal = gtv_update_resize_factor (this);
1278
1494
if (!this->priv->resizing)
1279
1495
this->priv->old_video_size = this->priv->video_size;
1280
1496
this->priv->idle_resized = FALSE;