~ubuntu-branches/ubuntu/maverick/zapping/maverick

« back to all changes in this revision

Viewing changes to src/fullscreen.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2005-03-08 23:19:08 UTC
  • mfrom: (2.1.1 sarge)
  • Revision ID: james.westby@ubuntu.com-20050308231908-oip7rfv6lcmo8c0e
Tags: 0.9.2-2ubuntu1
Rebuilt for Python transition (2.3 -> 2.4)

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
17
 */
18
18
 
 
19
/* $Id: fullscreen.c,v 1.42 2005/02/12 13:37:07 mschimek Exp $ */
 
20
 
19
21
/**
20
22
 * Fullscreen mode handling
21
 
 * $Id: fullscreen.c,v 1.21 2002/03/21 18:08:23 mschimek Exp $
 
23
 *
 
24
 * I wonder if we shouldn't simply switch the main window to
 
25
 * fullscreen...
22
26
 */
23
27
 
24
28
#ifdef HAVE_CONFIG_H
25
 
#  include <config.h>
 
29
#  include "config.h"
26
30
#endif
27
31
 
28
32
#include <gtk/gtk.h>
29
33
#include <gdk/gdkx.h>
30
 
#include "tveng.h"
 
34
#define ZCONF_DOMAIN "/zapping/options/main/"
 
35
#include "zconf.h"
 
36
#include "zgconf.h"
31
37
#include "osd.h"
32
38
#include "x11stuff.h"
33
 
#define ZCONF_DOMAIN "/zapping/options/main/"
34
 
#include "zmisc.h"
35
 
#include "zconf.h"
36
39
#include "interface.h"
37
 
#include "callbacks.h"
38
40
#include "v4linterface.h"
39
41
#include "fullscreen.h"
40
42
#include "audio.h"
41
43
#include "plugins.h"
42
 
 
43
 
static GtkWidget * black_window = NULL; /* The black window when you go
44
 
                                           fullscreen */
45
 
extern GtkWidget * main_window;
46
 
 
47
 
extern tveng_tuned_channel *global_channel_list;
48
 
 
49
 
extern enum tveng_capture_mode last_mode;
50
 
 
51
 
extern tveng_device_info *main_info;
52
 
 
53
 
/* Comment out the next line if you don't want to mess with the
54
 
   XScreensaver */
55
 
#define MESS_WITH_XSS 1
56
 
 
57
 
static gboolean
58
 
on_fullscreen_event                     (GtkWidget *    widget,
59
 
                                         GdkEvent *     event,
60
 
                                         gpointer       user_data)
61
 
{
62
 
  GtkWidget * window = GTK_WIDGET(user_data);
63
 
  GtkMenuItem * exit2 = GTK_MENU_ITEM(lookup_widget(window, "quit1"));
64
 
 
65
 
  if (event->type == GDK_KEY_PRESS)
66
 
    {
67
 
      GdkEventKey *kevent = (GdkEventKey *) event;
68
 
 
69
 
      if (kevent->keyval == GDK_q && (kevent->state & GDK_CONTROL_MASK))
70
 
        {
71
 
          extern gboolean was_fullscreen;
72
 
 
73
 
          was_fullscreen = TRUE;
74
 
          zmisc_switch_mode(last_mode, main_info);
75
 
          cmd_execute (GTK_WIDGET (exit2), "quit");
76
 
 
77
 
          return TRUE;
78
 
        }
79
 
      else
80
 
        {
81
 
          return on_user_key_press (widget, kevent, user_data)
82
 
            || on_channel_key_press (widget, kevent, user_data);
83
 
        }
84
 
    }
85
 
  else if (event->type == GDK_BUTTON_PRESS)
86
 
    {
87
 
      zmisc_switch_mode(last_mode, main_info);
88
 
      return TRUE;
89
 
    }
90
 
 
91
 
  return FALSE; /* We aren't interested in this event, pass it on */
 
44
#include "zvideo.h"
 
45
#include "globals.h"
 
46
#include "zvbi.h"
 
47
 
 
48
extern gboolean was_fullscreen;
 
49
 
 
50
static x11_vidmode_info *       svidmodes;
 
51
static GtkWidget *              drawing_area;
 
52
static GtkWidget *              black_window; /* The black window when you go
 
53
                                                 fullscreen */
 
54
static x11_vidmode_state        old_vidmode;
 
55
static const tv_screen *        screen;
 
56
 
 
57
static gint                     old_mw_x;
 
58
static gint                     old_mw_y;
 
59
 
 
60
static gboolean
 
61
on_key_press                    (GtkWidget *            widget,
 
62
                                 GdkEventKey *          event)
 
63
{
 
64
  if (GDK_q == event->keyval
 
65
      && (event->state & GDK_CONTROL_MASK))
 
66
    {
 
67
      was_fullscreen = TRUE;
 
68
 
 
69
      python_command (widget, "zapping.switch_mode('window'); zapping.quit()");
 
70
 
 
71
      return TRUE;
 
72
    }
 
73
  else if (GDK_Escape == event->keyval)
 
74
    {
 
75
      python_command (widget, "zapping.switch_mode('window')");
 
76
 
 
77
      return TRUE;
 
78
    }
 
79
 
 
80
#ifdef HAVE_LIBZVBI
 
81
  if (CAPTURE_MODE_TELETEXT == tv_get_capture_mode (zapping->info))
 
82
    {
 
83
      TeletextView *view;
 
84
 
 
85
      view = (TeletextView *) drawing_area;
 
86
      if (view->key_press (view, event))
 
87
        return TRUE;
 
88
    }
 
89
#endif
 
90
 
 
91
  return on_user_key_press (widget, event, NULL)
 
92
    || on_channel_key_press (widget, event, NULL);
 
93
}
 
94
 
 
95
static gboolean
 
96
on_button_press                 (GtkWidget *            widget,
 
97
                                 GdkEventButton *       event)
 
98
{
 
99
  switch (event->button)
 
100
    {
 
101
    case 2: /* Middle button */
 
102
      python_command (widget, "zapping.switch_mode('window')");
 
103
      return TRUE; /* handled */
 
104
 
 
105
    case 3: /* Right button */
 
106
      zapping_create_popup (zapping, event);
 
107
      return TRUE; /* handled */
 
108
 
 
109
    default:
 
110
      break;
 
111
    }
 
112
 
 
113
  return FALSE; /* pass on */
 
114
}
 
115
 
 
116
static gboolean
 
117
on_scroll_event                 (GtkWidget *            widget,
 
118
                                 GdkEventScroll *       event)
 
119
{
 
120
  switch (event->direction)
 
121
    {
 
122
    case GDK_SCROLL_UP:
 
123
    case GDK_SCROLL_LEFT:
 
124
      python_command (widget, "zapping.channel_up()");
 
125
      return TRUE; /* handled */
 
126
 
 
127
    case GDK_SCROLL_DOWN:
 
128
    case GDK_SCROLL_RIGHT:
 
129
      python_command (widget, "zapping.channel_down()");
 
130
      return TRUE; /* handled */
 
131
 
 
132
    default:
 
133
      break;
 
134
    }
 
135
 
 
136
  return FALSE; /* pass on */
92
137
}
93
138
 
94
139
/* Called when OSD changes the geometry of the pieces */
95
140
static void
96
 
osd_model_changed                       (ZModel         *ignored1,
 
141
osd_model_changed                       (ZModel *       ignored1 _unused_,
97
142
                                         tveng_device_info *info)
98
143
{
99
 
  struct tveng_window window;
100
 
  struct tveng_clip *clips;
 
144
  const tv_window *w;
 
145
  tv_clip_vector clip_vector;
 
146
  GdkWindow *gdk_window;
101
147
 
102
 
  if (info->current_controller == TVENG_CONTROLLER_XV ||
 
148
  if (tv_get_controller (info) == TVENG_CONTROLLER_XV ||
103
149
      !black_window || !black_window->window)
104
150
    return;
105
151
 
106
 
  /* save for later use */
107
 
  memcpy(&window, &info->window, sizeof(struct tveng_window));
108
 
 
109
 
  tveng_set_preview_off(info);
110
 
  memcpy(&info->window, &window, sizeof(struct tveng_window));
111
 
  clips = info->window.clips =
112
 
    x11_get_clips(GTK_BIN(black_window)->child->window,
113
 
                  window.x, window.y,
114
 
                  window.width,
115
 
                  window.height,
116
 
                  &window.clipcount);
117
 
  info->window.clipcount = window.clipcount;
118
 
  tveng_set_preview_window(info);
119
 
  tveng_set_preview_on(info);
120
 
 
121
 
  g_free(clips);
122
 
}
123
 
 
124
 
gint
125
 
fullscreen_start(tveng_device_info * info)
126
 
{
127
 
  GtkWidget * da; /* Drawing area */
128
 
  GdkColor chroma = {0, 0, 0, 0};
129
 
 
130
 
  /* Add a black background */
131
 
  black_window = gtk_window_new( GTK_WINDOW_POPUP );
132
 
  da = gtk_fixed_new();
133
 
 
134
 
  gtk_widget_show(da);
135
 
 
136
 
  gtk_container_add(GTK_CONTAINER(black_window), da);
137
 
  gtk_widget_set_usize(black_window, gdk_screen_width(),
138
 
                       gdk_screen_height());
139
 
 
140
 
  gtk_widget_realize(black_window);
141
 
  gtk_widget_realize(da);
142
 
  gdk_window_set_events(black_window->window, GDK_ALL_EVENTS_MASK);
143
 
  gdk_window_set_events(da->window, GDK_ALL_EVENTS_MASK);
144
 
  gtk_window_set_modal(GTK_WINDOW(black_window), TRUE);
145
 
  gdk_window_set_decorations(black_window->window, 0);
146
 
 
147
 
  /* hide the cursor in fullscreen mode */
148
 
  z_set_cursor(da->window, 0);
149
 
 
150
 
  if (info->current_controller != TVENG_CONTROLLER_XV &&
151
 
      (info->caps.flags & TVENG_CAPS_CHROMAKEY))
152
 
    {
153
 
      chroma.red = chroma.green = 0;
154
 
      chroma.blue = 0xffff;
155
 
      
156
 
      if (gdk_colormap_alloc_color(gdk_colormap_get_system(), &chroma,
157
 
                                   FALSE, TRUE))
158
 
        tveng_set_chromakey(chroma.red >> 8, chroma.green >> 8,
159
 
                            chroma.blue >> 8, info);
160
 
      else
161
 
        ShowBox("Couldn't allocate chromakey, chroma won't work",
162
 
                GNOME_MESSAGE_BOX_WARNING);
163
 
    }
164
 
 
165
 
  gdk_window_set_background(da->window, &chroma);
166
 
 
167
 
  if (chroma.pixel != 0)
168
 
    gdk_colormap_free_colors(gdk_colormap_get_system(), &chroma,
169
 
                             1);
170
 
 
171
 
  /* Needed for XV fullscreen */
172
 
  info->window.win = GDK_WINDOW_XWINDOW(da->window);
173
 
  info->window.gc = GDK_GC_XGC(da->style->white_gc);
174
 
 
175
 
  if (tveng_start_previewing(info, 1-zcg_int(NULL, "change_mode")) == -1)
176
 
    {
177
 
      ShowBox(_("Sorry, but cannot go fullscreen:\n%s"),
178
 
              GNOME_MESSAGE_BOX_ERROR, info->error);
179
 
      gtk_widget_destroy(black_window);
180
 
      zmisc_switch_mode(TVENG_CAPTURE_READ, info);
181
 
      return -1;
182
 
    }
183
 
 
184
 
  gtk_widget_show(black_window);
185
 
 
186
 
  if (info -> current_mode != TVENG_CAPTURE_PREVIEW)
187
 
    g_warning("Setting preview succeeded, but the mode is not set");
188
 
 
189
 
#ifdef MESS_WITH_XSS
190
 
  /* Set the blank screensaver */
191
 
  x11_set_screensaver(OFF);
192
 
#endif
193
 
 
194
 
  gtk_widget_grab_focus(black_window);
195
 
 
196
 
  gtk_signal_connect(GTK_OBJECT(black_window), "event",
197
 
                     GTK_SIGNAL_FUNC(on_fullscreen_event),
198
 
                     main_window);
199
 
#ifdef HAVE_LIBZVBI
200
 
  if (info->current_controller != TVENG_CONTROLLER_XV)
201
 
    osd_set_coords(da,
202
 
                   info->window.x, info->window.y, info->window.width,
203
 
                   info->window.height);
204
 
  else
205
 
    osd_set_coords(da, 0, 0, info->window.width,
206
 
                   info->window.height);
207
 
 
208
 
  gtk_signal_connect(GTK_OBJECT(osd_model), "changed",
209
 
                     GTK_SIGNAL_FUNC(osd_model_changed), info);
210
 
#endif
211
 
 
212
 
  return 0;
213
 
}
214
 
 
215
 
void
216
 
fullscreen_stop(tveng_device_info * info)
217
 
{
218
 
#ifdef MESS_WITH_XSS
219
 
  /* Restore the normal screensaver */
220
 
  x11_set_screensaver(ON);
221
 
#endif
222
 
 
223
 
#ifdef HAVE_LIBZVBI
224
 
  osd_unset_window();
225
 
#endif
 
152
  tv_enable_overlay (info, FALSE);
 
153
 
 
154
  tv_clip_vector_init (&clip_vector);
 
155
 
 
156
  gdk_window = GTK_BIN (black_window)->child->window;
 
157
 
 
158
  w = tv_cur_overlay_window (info);
 
159
 
 
160
  x11_window_clip_vector (&clip_vector,
 
161
                          GDK_WINDOW_XDISPLAY (gdk_window),
 
162
                          GDK_WINDOW_XID (gdk_window),
 
163
                          w->x,
 
164
                          w->y,
 
165
                          w->width,
 
166
                          w->height);
 
167
 
 
168
  tv_set_overlay_window_clipvec (info, w, &clip_vector);
 
169
 
 
170
  tv_clip_vector_destroy (&clip_vector);
 
171
 
 
172
  tv_enable_overlay (info, TRUE);
 
173
}
 
174
 
 
175
static void
 
176
on_cursor_blanked               (ZVideo *               video _unused_,
 
177
                                 gpointer               user_data _unused_)
 
178
{
 
179
  /* Recenter the viewport */
 
180
  x11_vidmode_switch (svidmodes, screens, NULL, NULL);
 
181
}
 
182
 
 
183
static void
 
184
set_blank_timeout               (ZVideo *               video)
 
185
{
 
186
  gint timeout;
 
187
 
 
188
  timeout = 0; /* disabled */
 
189
  z_gconf_get_int (&timeout, "/apps/zapping/blank_cursor_timeout");
 
190
 
 
191
  z_video_blank_cursor (video, timeout);
 
192
}
 
193
 
 
194
static const x11_vidmode_info *
 
195
find_vidmode                    (const x11_vidmode_info *vidmodes,
 
196
                                 guint                  width,
 
197
                                 guint                  height)
 
198
{
 
199
  const x11_vidmode_info *v;
 
200
  const x11_vidmode_info *vmin;
 
201
  gint64 amin;
 
202
 
 
203
  vmin = vidmodes;
 
204
  amin = ((gint64) 1) << 62;
 
205
 
 
206
  for (v = vidmodes; v; v = v->next)
 
207
    {
 
208
      gint64 a;
 
209
      gint64 dw, dh;
 
210
 
 
211
      if (0)
 
212
        fprintf (stderr, "width=%d height=%d cur %ux%u@%u best %ux%u@%u\n",
 
213
                 width, height,
 
214
                 v->width, v->height, (guint)(v->vfreq + 0.5),
 
215
                 vmin->width, vmin->height, (guint)(vmin->vfreq + 0.5));
 
216
 
 
217
      /* XXX ok? */
 
218
      dw = (gint64) v->width - width;
 
219
      dh = (gint64) v->height - height;
 
220
      a = dw * dw + dh * dh;
 
221
 
 
222
      if (a < amin
 
223
          || (a == amin && v->vfreq > vmin->vfreq))
 
224
        {
 
225
          vmin = v;
 
226
          amin = a;
 
227
        }
 
228
    }
 
229
 
 
230
  v = vmin;
 
231
 
 
232
  if (0)
 
233
    fprintf (stderr, "Using mode %ux%u@%u for video %ux%u\n",
 
234
             v->width, v->height, (guint)(v->vfreq + 0.5),
 
235
             width, height);
 
236
 
 
237
  return v;
 
238
}
 
239
 
 
240
static const tv_screen *
 
241
find_screen                     (void)
 
242
{
 
243
  gint x;
 
244
  gint y;
 
245
  gint width;
 
246
  gint height;
 
247
  GdkWindow *window;
 
248
  const tv_screen *xs;
 
249
 
 
250
  window = GTK_WIDGET (zapping)->window;
 
251
 
 
252
  /* Root window relative position. */
 
253
  gdk_window_get_origin (window, &x, &y);
 
254
 
 
255
  gdk_window_get_geometry (window,
 
256
                           /* x */ NULL,
 
257
                           /* y */ NULL,
 
258
                           &width,
 
259
                           &height,
 
260
                           /* depth */ NULL);
 
261
 
 
262
  xs = tv_screen_list_find (screens,
 
263
                            x, y,
 
264
                            (guint) width,
 
265
                            (guint) height);
 
266
  if (!xs)
 
267
    xs = screens;
 
268
 
 
269
  return xs;
 
270
}
 
271
 
 
272
gboolean
 
273
stop_fullscreen                 (void)
 
274
{
 
275
  g_assert (DISPLAY_MODE_FULLSCREEN == zapping->display_mode
 
276
            || DISPLAY_MODE_BACKGROUND == zapping->display_mode);
 
277
 
 
278
  switch (tv_get_capture_mode (zapping->info))
 
279
    {
 
280
    case CAPTURE_MODE_OVERLAY:
 
281
      /* Error ignored */
 
282
      tv_enable_overlay (zapping->info, FALSE);
 
283
 
 
284
      g_signal_handlers_disconnect_matched
 
285
        (G_OBJECT (osd_model), G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
 
286
         0, 0, NULL, G_CALLBACK (osd_model_changed), zapping->info);
 
287
 
 
288
      break;
 
289
 
 
290
    case CAPTURE_MODE_READ:
 
291
      if (!capture_stop ())
 
292
        return FALSE;
 
293
      break;
 
294
 
 
295
    case CAPTURE_MODE_TELETEXT:
 
296
      /* Nuk nuk. */
 
297
      break;
 
298
 
 
299
    default:
 
300
      g_assert_not_reached ();
 
301
    }
 
302
 
 
303
  zapping->display_mode = DISPLAY_MODE_WINDOW;
 
304
  tv_set_capture_mode (zapping->info, CAPTURE_MODE_NONE);
 
305
 
 
306
  x11_vidmode_restore (svidmodes, &old_vidmode);
 
307
 
 
308
  osd_unset_window ();
226
309
 
227
310
  /* Remove the black window */
228
 
  gtk_widget_destroy(black_window);
229
 
  x11_force_expose(0, 0, gdk_screen_width(), gdk_screen_height());
230
 
 
231
 
#ifdef HAVE_LIBZVBI
232
 
  gtk_signal_disconnect_by_func(GTK_OBJECT(osd_model),
233
 
                                GTK_SIGNAL_FUNC(osd_model_changed),
234
 
                                info);
235
 
#endif
 
311
  gtk_widget_destroy (black_window);
 
312
  black_window = NULL;
 
313
 
 
314
  x11_force_expose ((gint) screen->x,
 
315
                    (gint) screen->y,
 
316
                    screen->width,
 
317
                    screen->height);
 
318
 
 
319
  x11_vidmode_list_delete (svidmodes);
 
320
  svidmodes = NULL;
 
321
 
 
322
  gtk_widget_show (GTK_WIDGET (zapping));
 
323
 
 
324
  /* Undo "smart" placement by the WM. */
 
325
  gtk_window_move (GTK_WINDOW (zapping),
 
326
                   old_mw_x,
 
327
                   old_mw_y);
 
328
 
 
329
  return TRUE;
 
330
}
 
331
 
 
332
gboolean
 
333
start_fullscreen                (display_mode           dmode,
 
334
                                 capture_mode           cmode)
 
335
{
 
336
  const tv_screen *xs;
 
337
  GtkWindow *window;
 
338
  GdkColor chroma;
 
339
  const gchar *vm_name;
 
340
  const x11_vidmode_info *vm;
 
341
  gint vx;
 
342
  gint vy;
 
343
  guint vwidth;
 
344
  guint vheight;
 
345
  GtkWidget *fixed;
 
346
 
 
347
#ifdef HAVE_LIBZVBI
 
348
  if (CAPTURE_MODE_TELETEXT == cmode)
 
349
    if (!_teletext_view_new
 
350
        || !zvbi_get_object ())
 
351
      return FALSE;
 
352
#else
 
353
  if (CAPTURE_MODE_TELETEXT == cmode)
 
354
    return FALSE;
 
355
#endif
 
356
 
 
357
  xs = find_screen ();
 
358
  screen = xs;
 
359
 
 
360
  /* VidModes available on this screen. */
 
361
  svidmodes = x11_vidmode_list_new (NULL, xs->screen_number);
 
362
 
 
363
  CLEAR (chroma);
 
364
 
 
365
  black_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
 
366
  window = GTK_WINDOW (black_window);
 
367
 
 
368
  gtk_widget_realize (black_window);
 
369
  gdk_window_set_decorations (black_window->window, 0);
 
370
 
 
371
  gtk_widget_set_size_request (black_window,
 
372
                               (gint) xs->width,
 
373
                               (gint) xs->height);
 
374
 
 
375
  gtk_widget_modify_bg (black_window, GTK_STATE_NORMAL, &chroma);
 
376
 
 
377
  gtk_window_add_accel_group
 
378
    (window, gtk_ui_manager_get_accel_group (zapping->ui_manager));
 
379
 
 
380
 
 
381
  fixed = gtk_fixed_new ();
 
382
  gtk_widget_show (fixed);
 
383
  gtk_container_add (GTK_CONTAINER (black_window), fixed);
 
384
 
 
385
 
 
386
  if (CAPTURE_MODE_TELETEXT == cmode)
 
387
    {
 
388
#ifdef HAVE_LIBZVBI
 
389
      /* Welcome to the magic world of encapsulation. */ 
 
390
      drawing_area = _teletext_view_new ();
 
391
#endif
 
392
 
 
393
      /* Gdk scaling routines hang if we start with the default 1, 1. */
 
394
      gtk_widget_set_size_request (drawing_area, 400, 300);
 
395
 
 
396
      /* For Python bindings. */
 
397
      g_object_set_data (G_OBJECT (black_window),
 
398
                         "TeletextView", drawing_area);      
 
399
    }
 
400
  else
 
401
    {
 
402
      drawing_area = z_video_new ();
 
403
      Z_VIDEO (drawing_area)->size_magic = FALSE;
 
404
 
 
405
      set_blank_timeout (Z_VIDEO (drawing_area));
 
406
 
 
407
      g_signal_connect (G_OBJECT (drawing_area), "cursor-blanked",
 
408
                        G_CALLBACK (on_cursor_blanked), zapping->info);
 
409
    }
 
410
 
 
411
  gtk_widget_show (drawing_area);
 
412
  gtk_fixed_put (GTK_FIXED (fixed), drawing_area, 0, 0);
 
413
 
 
414
  gtk_widget_add_events (drawing_area,
 
415
                         GDK_BUTTON_PRESS_MASK |
 
416
                         GDK_BUTTON_RELEASE_MASK |
 
417
                         GDK_SCROLL_MASK |
 
418
                         GDK_KEY_PRESS_MASK);
 
419
 
 
420
  gtk_widget_modify_bg (drawing_area, GTK_STATE_NORMAL, &chroma);
 
421
 
 
422
  gtk_widget_show (black_window);
 
423
 
 
424
  if (CAPTURE_MODE_TELETEXT == cmode)
 
425
    {
 
426
      /* XXX TeletextView should already do this on realize, doesn't work??? */
 
427
      gdk_window_set_back_pixmap (drawing_area->window, NULL, FALSE);
 
428
    }
 
429
 
 
430
  /* Make sure we're on the right screen. */
 
431
  if (1)
 
432
    gtk_window_move (window, (gint) xs->x, (gint) xs->y);
 
433
  else /* debug */
 
434
    gtk_window_move (window, 700, 600);
 
435
 
 
436
  if (DISPLAY_MODE_BACKGROUND == dmode)
 
437
    {
 
438
      x11_window_below (window, TRUE);
 
439
    }
 
440
  else
 
441
    {
 
442
      /* This should span only one screen, with or without Xinerama,
 
443
         if the WM has proper Xinerama support. */
 
444
      x11_window_fullscreen (window, TRUE);
 
445
    }
 
446
 
 
447
  gtk_window_present (window);
 
448
 
 
449
 
 
450
  switch (cmode)
 
451
    {
 
452
    case CAPTURE_MODE_OVERLAY:
 
453
      /* Make sure we use an Xv adaptor which can render into da->window.
 
454
         (Won't help with X.org but it's the right thing to do.) */
 
455
      tveng_close_device(zapping->info);
 
456
 
 
457
      if (-1 == tveng_attach_device (zcg_char (NULL, "video_device"),
 
458
                                     GDK_WINDOW_XWINDOW (drawing_area->window),
 
459
                                     TVENG_ATTACH_XV,
 
460
                                     zapping->info))
 
461
        {
 
462
          ShowBox("Overlay mode not available:\n%s",
 
463
                  GTK_MESSAGE_ERROR, tv_get_errstr (zapping->info));
 
464
          goto failure;
 
465
        }
 
466
 
 
467
      if (tv_get_controller (zapping->info) != TVENG_CONTROLLER_XV &&
 
468
          (tv_get_caps (zapping->info)->flags & TVENG_CAPS_CHROMAKEY))
 
469
        {
 
470
          chroma.blue = 0xffff;
 
471
      
 
472
          if (gdk_colormap_alloc_color(gdk_colormap_get_system(), &chroma,
 
473
                                       FALSE, TRUE))
 
474
            {
 
475
              z_set_window_bg (drawing_area, &chroma);
 
476
              
 
477
              gdk_colormap_free_colors (gdk_colormap_get_system(), &chroma, 1);
 
478
            }
 
479
          else
 
480
            {
 
481
              ShowBox("Couldn't allocate chromakey, chroma won't work",
 
482
                      GTK_MESSAGE_WARNING);
 
483
            }
 
484
        }
 
485
      else if (tv_get_controller (zapping->info) == TVENG_CONTROLLER_XV)
 
486
        {
 
487
          GdkColor chroma;
 
488
          unsigned int chromakey;
 
489
          
 
490
          CLEAR (chroma);
 
491
          
 
492
          if (tv_get_overlay_chromakey (zapping->info, &chromakey))
 
493
            {
 
494
              chroma.pixel = chromakey;
 
495
              z_set_window_bg (drawing_area, &chroma);
 
496
            }
 
497
        }
 
498
 
 
499
      /* Disable double buffering just in case, will help when a
 
500
         XV driver doesn't provide XV_COLORKEY but requires the colorkey
 
501
         not to be overwritten */
 
502
      gtk_widget_set_double_buffered (drawing_area, FALSE);
 
503
 
 
504
      break;
 
505
 
 
506
    case CAPTURE_MODE_READ:
 
507
      tveng_close_device(zapping->info);
 
508
 
 
509
      if (-1 == tveng_attach_device (zcg_char (NULL, "video_device"),
 
510
                                     GDK_WINDOW_XWINDOW (drawing_area->window),
 
511
                                     TVENG_ATTACH_READ,
 
512
                                     zapping->info))
 
513
        {
 
514
          ShowBox("Capture mode not available:\n%s",
 
515
                  GTK_MESSAGE_ERROR, tv_get_errstr (zapping->info));
 
516
          goto failure;
 
517
        }
 
518
 
 
519
      break;
 
520
 
 
521
    case CAPTURE_MODE_TELETEXT:
 
522
      /* Bktr driver needs special programming for VBI-only mode. */
 
523
      tveng_close_device (zapping->info);
 
524
 
 
525
      if (-1 == tveng_attach_device (zcg_char (NULL, "video_device"),
 
526
                                     GDK_WINDOW_XWINDOW (drawing_area->window),
 
527
                                     TVENG_ATTACH_VBI,
 
528
                                     zapping->info))
 
529
        {
 
530
          ShowBox ("Teletext mode not available.",
 
531
                   GTK_MESSAGE_ERROR);
 
532
          goto failure;
 
533
        }
 
534
 
 
535
      break;
 
536
 
 
537
    default:
 
538
      goto failure;
 
539
    }
 
540
 
 
541
  /* Determine video size. XXX improve me. */
 
542
  if (CAPTURE_MODE_TELETEXT == cmode)
 
543
    {
 
544
      if ((vm_name = zcg_char (NULL, "fullscreen/vidmode"))
 
545
          && 0 != strcmp (vm_name, "auto"))
 
546
        {
 
547
          vm = x11_vidmode_by_name (svidmodes, vm_name);
 
548
        }
 
549
      else
 
550
        {
 
551
          vm = NULL;
 
552
        }
 
553
 
 
554
      if (vm && x11_vidmode_switch (svidmodes, screens, vm, &old_vidmode))
 
555
        {
 
556
          /* xs->width, height >= vm->width, height */
 
557
 
 
558
          vwidth = vm->width;
 
559
          vheight = vm->height;
 
560
        }
 
561
      else
 
562
        {
 
563
          x11_vidmode_clear_state (&old_vidmode);
 
564
 
 
565
          vwidth = xs->width;
 
566
          vheight = xs->height;
 
567
        }
 
568
    }
 
569
  else
 
570
    {
 
571
      const tv_video_standard *vs;
 
572
      const struct tveng_caps *caps;
 
573
 
 
574
      if ((vs = tv_cur_video_standard (zapping->info)))
 
575
        {
 
576
          vwidth = vs->frame_width;
 
577
          vheight = vs->frame_height;
 
578
        }
 
579
      else
 
580
        {
 
581
          vwidth = 640;
 
582
          vheight = 480;
 
583
        }
 
584
 
 
585
      /* Driver limit. */
 
586
      caps = tv_get_caps (zapping->info);
 
587
      vwidth = MIN ((guint) caps->maxwidth, vwidth);
 
588
      vheight = MIN ((guint) caps->maxheight, vheight);
 
589
 
 
590
      /* Screen limit. XXX should try to scale captured images down. */
 
591
      vwidth = MIN (xs->width, vwidth);
 
592
      vheight = MIN (xs->height, vheight);
 
593
 
 
594
      if ((vm_name = zcg_char (NULL, "fullscreen/vidmode")))
 
595
        {
 
596
          if (0 == strcmp (vm_name, "auto"))
 
597
            {
 
598
              vm = find_vidmode (svidmodes, vwidth, vheight);
 
599
            }
 
600
          else
 
601
            {
 
602
              vm = x11_vidmode_by_name (svidmodes, vm_name);
 
603
            }
 
604
        }
 
605
      else
 
606
        {
 
607
          vm = NULL;
 
608
        }
 
609
      
 
610
      if (vm && x11_vidmode_switch (svidmodes, screens, vm, &old_vidmode))
 
611
        {
 
612
          /* xs->width, height >= vm->width, height <=> vwidth, vheight */
 
613
        }
 
614
      else
 
615
        {
 
616
          x11_vidmode_clear_state (&old_vidmode);
 
617
 
 
618
          if (CAPTURE_MODE_READ == cmode)
 
619
            {
 
620
              /* XXX should check scaling abilities. */
 
621
              vwidth = xs->width;
 
622
              vheight = xs->height;
 
623
            }
 
624
          else
 
625
            {
 
626
              /* xs->width, height >= vwidth, vheight */
 
627
            }
 
628
        }
 
629
    }
 
630
 
 
631
  vx = (xs->width - vwidth) >> 1;
 
632
  vy = (xs->height - vheight) >> 1;
 
633
 
 
634
  if (0)
 
635
    fprintf (stderr, "vx=%u,%u vwidth=%u,%u xswidth=%u,%u\n",
 
636
             vx, vy, vwidth, vheight, xs->width, xs->height);
 
637
 
 
638
  gtk_widget_set_size_request (drawing_area, (gint) vwidth, (gint) vheight);
 
639
  gtk_fixed_move (GTK_FIXED (fixed), drawing_area, vx, vy);
 
640
 
 
641
  switch (cmode)
 
642
    {
 
643
    case CAPTURE_MODE_OVERLAY:
 
644
      /* XXX */
 
645
      if (tv_get_controller (zapping->info) == TVENG_CONTROLLER_XV)
 
646
        {
 
647
          /* Wait until da has the desired size. */
 
648
          while (gtk_events_pending ())
 
649
            gtk_main_iteration ();
 
650
 
 
651
          if (!tv_set_overlay_xwindow (zapping->info,
 
652
                                       GDK_WINDOW_XWINDOW (drawing_area->window),
 
653
                                       GDK_GC_XGC (drawing_area->style->white_gc)))
 
654
            goto failure;
 
655
 
 
656
          /* For OSD. */
 
657
          tv_overlay_hack (zapping->info, vx, vy, (int) vwidth, (int) vheight);
 
658
        }
 
659
      else
 
660
        {
 
661
          tv_window window;
 
662
          const tv_window *w;
 
663
 
 
664
          if (!z_set_overlay_buffer (zapping->info, xs, drawing_area->window))
 
665
            goto failure;
 
666
 
 
667
          CLEAR (w);
 
668
 
 
669
          window.x = vx;
 
670
          window.y = vy;
 
671
          window.width = vwidth;
 
672
          window.height = vheight;
 
673
 
 
674
          /* Set new capture dimensions */
 
675
          if (!tv_set_overlay_window_clipvec (zapping->info, &window, NULL))
 
676
            goto failure;
 
677
 
 
678
          w = tv_cur_overlay_window (zapping->info);
 
679
          if (w->width != vwidth
 
680
              || w->height != vheight)
 
681
            {
 
682
              window.x = (xs->width - w->width) >> 1;
 
683
              window.y = (xs->height - w->height) >> 1;
 
684
 
 
685
              if (!tv_set_overlay_window_clipvec
 
686
                  (zapping->info, &window, NULL))
 
687
                goto failure;
 
688
            }
 
689
        }
 
690
 
 
691
      /* Start preview */
 
692
      if (!tv_enable_overlay (zapping->info, TRUE))
 
693
        goto failure;
 
694
 
 
695
      break;
 
696
 
 
697
    case CAPTURE_MODE_READ:
 
698
      /* XXX error? */
 
699
      tveng_set_capture_size (vwidth, vheight, zapping->info);
 
700
 
 
701
      if (!capture_start (zapping->info, GTK_WIDGET (drawing_area)))
 
702
        goto failure;
 
703
 
 
704
      break;
 
705
 
 
706
    case CAPTURE_MODE_TELETEXT:
 
707
      /* Nuk nuk. */
 
708
      break;
 
709
 
 
710
    default:
 
711
      goto failure;
 
712
    }
 
713
 
 
714
  gdk_window_get_origin (GTK_WIDGET (zapping)->window,
 
715
                         &old_mw_x,
 
716
                         &old_mw_y);
 
717
 
 
718
  gtk_widget_hide (GTK_WIDGET (zapping));
 
719
 
 
720
  zapping->display_mode = DISPLAY_MODE_FULLSCREEN;
 
721
  tv_set_capture_mode (zapping->info, cmode);
 
722
 
 
723
  gtk_widget_grab_focus (black_window);
 
724
 
 
725
  g_signal_connect (G_OBJECT (black_window), "key_press_event",
 
726
                    G_CALLBACK (on_key_press),
 
727
                    GTK_WIDGET (zapping));
 
728
 
 
729
  g_signal_connect (G_OBJECT (black_window), "button_press_event",
 
730
                    G_CALLBACK (on_button_press),
 
731
                    GTK_WIDGET (zapping));
 
732
 
 
733
  g_signal_connect (G_OBJECT (drawing_area), "button_press_event",
 
734
                    G_CALLBACK (on_button_press),
 
735
                    GTK_WIDGET (zapping));
 
736
 
 
737
  g_signal_connect (G_OBJECT (drawing_area), "scroll_event",
 
738
                    G_CALLBACK (on_scroll_event),
 
739
                    GTK_WIDGET (zapping));
 
740
 
 
741
  switch (cmode)
 
742
    {
 
743
      const tv_window *w;
 
744
 
 
745
    case CAPTURE_MODE_OVERLAY:
 
746
      w = tv_cur_overlay_window (zapping->info);
 
747
 
 
748
      if (tv_get_controller (zapping->info) != TVENG_CONTROLLER_XV)
 
749
        {
 
750
          osd_set_coords (drawing_area,
 
751
                          w->x, w->y, (gint) w->width, (gint) w->height);
 
752
        }
 
753
      else
 
754
        {
 
755
          /* wrong because Xv may pad to this size (DMA hw limit) */
 
756
          osd_set_coords (drawing_area,
 
757
                          w->x, w->y, (gint) w->width, (gint) w->height);
 
758
        }
 
759
 
 
760
      g_signal_connect (G_OBJECT (osd_model), "changed",
 
761
                        G_CALLBACK (osd_model_changed), zapping->info);
 
762
 
 
763
      break;
 
764
 
 
765
    case CAPTURE_MODE_READ:
 
766
      osd_set_window (GTK_WIDGET (drawing_area));
 
767
      break;
 
768
 
 
769
    case CAPTURE_MODE_TELETEXT:
 
770
      /* Nuk nuk. */
 
771
      break;
 
772
 
 
773
    default:
 
774
      break;
 
775
    }
 
776
 
 
777
  return TRUE;
 
778
 
 
779
 failure:
 
780
  x11_vidmode_list_delete (svidmodes);
 
781
 
 
782
  gtk_widget_destroy (black_window);
 
783
 
 
784
  return FALSE;
236
785
}