1
/* Ekiga -- A VoIP and Video-Conferencing application
2
* Copyright (C) 2000-2009 Damien Sandras <dsandras@seconix.com>
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software Foundation,
16
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19
* Ekiga is licensed under the GPL license and as a special exception,
20
* you have permission to link or otherwise combine this program with the
21
* programs OPAL, OpenH323 and PWLIB, and distribute the combination,
22
* without applying the requirements of the GNU GPL to the OPAL, OpenH323
23
* and PWLIB programs, as long as you do follow the requirements of the
24
* GNU GPL for all the rest of the software thus combined.
29
* videooutput-manager-x.cpp - description
30
* ----------------------------------
31
* begin : Sun Nov 19 2006
32
* copyright : (C) 2006-2008 by Matthias Schneider
33
* (C) 2000-2008 by Damien Sandras
34
* description : Class to allow video output to a X/XVideo
38
#include "videooutput-manager-x.h"
46
GMVideoOutputManager_x::GMVideoOutputManager_x (Ekiga::ServiceCore & _core)
47
: GMVideoOutputManager(_core)
53
rDisplay = XOpenDisplay (NULL);
54
lDisplay = XOpenDisplay (NULL);
56
pip_window_available = true;
60
uninit_thread = false;
63
thread_created.Wait ();
66
GMVideoOutputManager_x::~GMVideoOutputManager_x ()
73
XCloseDisplay (lDisplay);
75
XCloseDisplay (rDisplay);
79
GMVideoOutputManager_x::frame_display_change_needed ()
81
switch (current_frame.mode)
83
case Ekiga::VO_MODE_LOCAL:
87
case Ekiga::VO_MODE_REMOTE:
91
case Ekiga::VO_MODE_FULLSCREEN:
92
case Ekiga::VO_MODE_PIP:
93
case Ekiga::VO_MODE_PIP_WINDOW:
94
if (!rxWindow || (pip_window_available && (!lxWindow)) )
97
case Ekiga::VO_MODE_UNSET:
101
return GMVideoOutputManager::frame_display_change_needed ();
106
GMVideoOutputManager_x::setup_frame_display ()
108
Ekiga::DisplayInfo local_display_info;
113
get_display_info(local_display_info);
115
switch (current_frame.mode) {
116
case Ekiga::VO_MODE_LOCAL:
117
Ekiga::Runtime::run_in_main (boost::bind (&GMVideoOutputManager_x::size_changed_in_main, this, (unsigned) (current_frame.local_width * current_frame.zoom / 100), (unsigned) (current_frame.local_height * current_frame.zoom / 100)));
119
case Ekiga::VO_MODE_REMOTE:
120
case Ekiga::VO_MODE_PIP:
121
Ekiga::Runtime::run_in_main (boost::bind (&GMVideoOutputManager_x::size_changed_in_main, this, (unsigned) (current_frame.remote_width * current_frame.zoom / 100), (unsigned) (current_frame.remote_height * current_frame.zoom / 100)));
123
case Ekiga::VO_MODE_FULLSCREEN:
124
Ekiga::Runtime::run_in_main (boost::bind (&GMVideoOutputManager_x::size_changed_in_main, this, 176, 144));
126
case Ekiga::VO_MODE_PIP_WINDOW:
127
Ekiga::Runtime::run_in_main (boost::bind (&GMVideoOutputManager_x::size_changed_in_main, this, 176, 144));
129
case Ekiga::VO_MODE_UNSET:
131
PTRACE (1, "GMVideoOutputManager_X\tDisplay variable not set");
136
if ((!local_display_info.widget_info_set) || (!local_display_info.config_info_set) ||
137
(local_display_info.mode == Ekiga::VO_MODE_UNSET) || (local_display_info.zoom == 0) || (current_frame.zoom == 0)) {
138
PTRACE(4, "GMVideoOutputManager_X\tWidget not yet realized or gconf info not yet set, not opening display");
142
close_frame_display ();
144
pip_window_available = false;
146
current_frame.accel = Ekiga::VO_ACCEL_NONE;
148
switch (current_frame.mode) {
149
// VO_MODE_LOCAL ------------------------------------------------------------------
150
case Ekiga::VO_MODE_LOCAL:
151
PTRACE(4, "GMVideoOutputManager_X\tOpening VO_MODE_LOCAL display with image of " << current_frame.local_width << "x" << current_frame.local_height);
153
if (!local_display_info.disable_hw_accel) {
154
lxWindow = new XVWindow ();
155
if (lxWindow->Init (lDisplay,
156
local_display_info.window,
157
local_display_info.gc,
158
local_display_info.x,
159
local_display_info.y,
160
(int) (current_frame.local_width * current_frame.zoom / 100),
161
(int) (current_frame.local_height * current_frame.zoom / 100),
162
current_frame.local_width,
163
current_frame.local_height)) {
164
current_frame.accel = Ekiga::VO_ACCEL_ALL;
165
PTRACE(4, "GMVideoOutputManager_X\tVO_MODE_LOCAL: Successfully opened XV Window");
170
current_frame.accel = Ekiga::VO_ACCEL_NONE;
171
PTRACE(4, "GMVideoOutputManager_X\tVO_MODE_LOCAL: Could not open XV Window");
175
if (current_frame.accel == Ekiga::VO_ACCEL_NONE) {
176
PTRACE(3, "GMVideoOutputManager_X\tFalling back to SW" << ((local_display_info.disable_hw_accel)
177
? " since HW acceleration was deactivated by configuration"
178
: " since HW acceleration failed to initalize"));
179
lxWindow = new XWindow ();
180
if (lxWindow->Init (lDisplay,
181
local_display_info.window,
182
local_display_info.gc,
183
local_display_info.x,
184
local_display_info.y,
185
(int) (current_frame.local_width * current_frame.zoom / 100),
186
(int) (current_frame.local_height * current_frame.zoom / 100),
187
current_frame.local_width,
188
current_frame.local_height)) {
189
lxWindow->SetSwScalingAlgo(local_display_info.sw_scaling_algorithm);
190
PTRACE(4, "GMVideoOutputManager_X\tVO_MODE_LOCAL: Successfully opened X Window");
195
video_disabled = true;
196
current_frame.accel = Ekiga::VO_ACCEL_NO_VIDEO;
197
PTRACE(1, "GMVideoOutputManager_X\tVO_MODE_LOCAL: Could not open X Window - no video");
201
last_frame.embedded_x = local_display_info.x;
202
last_frame.embedded_y = local_display_info.y;
204
last_frame.mode = Ekiga::VO_MODE_LOCAL;
205
last_frame.local_width = current_frame.local_width;
206
last_frame.local_height = current_frame.local_height;
207
last_frame.zoom = current_frame.zoom;
210
// VO_MODE_REMOTE ----------------------------------------------------------------
211
case Ekiga::VO_MODE_REMOTE:
212
PTRACE(4, "GMVideoOutputManager_X\tOpening VO_MODE_REMOTE display with image of " << current_frame.remote_width << "x" << current_frame.remote_height);
214
if (!local_display_info.disable_hw_accel) {
215
rxWindow = new XVWindow ();
216
if (rxWindow->Init (rDisplay,
217
local_display_info.window,
218
local_display_info.gc,
219
local_display_info.x,
220
local_display_info.y,
221
(int) (current_frame.remote_width * current_frame.zoom / 100),
222
(int) (current_frame.remote_height * current_frame.zoom / 100),
223
current_frame.remote_width,
224
current_frame.remote_height)) {
225
current_frame.accel = Ekiga::VO_ACCEL_ALL;
226
PTRACE(4, "GMVideoOutputManager_X\tVO_MODE_REMOTE: Successfully opened XV Window");
231
current_frame.accel = Ekiga::VO_ACCEL_NONE;
232
PTRACE(1, "GMVideoOutputManager_X\tVO_MODE_LOCAL: Could not open XV Window");
237
if (current_frame.accel == Ekiga::VO_ACCEL_NONE) {
238
PTRACE(3, "GMVideoOutputManager_X\tFalling back to SW" << ((local_display_info.disable_hw_accel)
239
? " since HW acceleration was deactivated by configuration"
240
: " since HW acceleration failed to initalize"));
241
rxWindow = new XWindow ();
242
if ( rxWindow->Init (rDisplay,
243
local_display_info.window,
244
local_display_info.gc,
245
local_display_info.x,
246
local_display_info.y,
247
(int) (current_frame.remote_width * current_frame.zoom / 100),
248
(int) (current_frame.remote_height * current_frame.zoom / 100),
249
current_frame.remote_width,
250
current_frame.remote_height)) {
251
rxWindow->SetSwScalingAlgo(local_display_info.sw_scaling_algorithm);
252
PTRACE(4, "GMVideoOutputManager_X\tVO_MODE_REMOTE: Successfully opened X Window");
257
video_disabled = true;
258
current_frame.accel = Ekiga::VO_ACCEL_NO_VIDEO;
259
PTRACE(1, "GMVideoOutputManager_X\tVO_MODE_REMOTE: Could not open X Window - no video");
263
last_frame.embedded_x = local_display_info.x;
264
last_frame.embedded_y = local_display_info.y;
266
last_frame.mode = Ekiga::VO_MODE_REMOTE;
267
last_frame.remote_width = current_frame.remote_width;
268
last_frame.remote_height = current_frame.remote_height;
269
last_frame.zoom = current_frame.zoom;
272
// PIP_VIDEO ------------------------------------------------------------------
273
case Ekiga::VO_MODE_FULLSCREEN:
274
case Ekiga::VO_MODE_PIP:
275
case Ekiga::VO_MODE_PIP_WINDOW:
276
PTRACE(4, "GMVideoOutputManager_X\tOpening display " << current_frame.mode << " with images of "
277
<< current_frame.local_width << "x" << current_frame.local_height << "(local) and "
278
<< current_frame.remote_width << "x" << current_frame.remote_height << "(remote)");
280
if (!local_display_info.disable_hw_accel) {
281
rxWindow = new XVWindow ();
282
if (rxWindow->Init ( rDisplay,
283
(current_frame.mode == Ekiga::VO_MODE_PIP) ? local_display_info.window : DefaultRootWindow (rDisplay),
284
(current_frame.mode == Ekiga::VO_MODE_PIP) ? local_display_info.gc : NULL,
285
(current_frame.mode == Ekiga::VO_MODE_PIP) ? local_display_info.x : 0,
286
(current_frame.mode == Ekiga::VO_MODE_PIP) ? local_display_info.y : 0,
287
(int) (current_frame.remote_width * current_frame.zoom / 100),
288
(int) (current_frame.remote_height * current_frame.zoom / 100),
289
current_frame.remote_width,
290
current_frame.remote_height)) {
291
current_frame.accel = Ekiga::VO_ACCEL_REMOTE_ONLY;
292
PTRACE(4, "GMVideoOutputManager_X\tPIP: Successfully opened remote XV Window");
298
current_frame.accel = Ekiga::VO_ACCEL_NONE;
299
PTRACE(1, "GMVideoOutputManager_X\tPIP: Could not open remote XV Window");
303
if (current_frame.accel == Ekiga::VO_ACCEL_NONE) {
304
PTRACE(3, "GMVideoOutputManager_X\tFalling back to SW" << ((local_display_info.disable_hw_accel)
305
? " since HW acceleration was deactivated by configuration"
306
: " since HW acceleration failed to initalize"));
307
rxWindow = new XWindow ();
308
if (rxWindow->Init ( rDisplay,
309
(current_frame.mode == Ekiga::VO_MODE_PIP) ? local_display_info.window : DefaultRootWindow (rDisplay),
310
(current_frame.mode == Ekiga::VO_MODE_PIP) ? local_display_info.gc : NULL,
311
(current_frame.mode == Ekiga::VO_MODE_PIP) ? local_display_info.x : 0,
312
(current_frame.mode == Ekiga::VO_MODE_PIP) ? local_display_info.y : 0,
313
(int) (current_frame.remote_width * current_frame.zoom / 100),
314
(int) (current_frame.remote_height * current_frame.zoom / 100),
315
current_frame.remote_width,
316
current_frame.remote_height)) {
317
rxWindow->SetSwScalingAlgo(local_display_info.sw_scaling_algorithm);
318
PTRACE(4, "GMVideoOutputManager_X\tPIP: Successfully opened remote X Window");
323
video_disabled = true;
324
current_frame.accel = Ekiga::VO_ACCEL_NO_VIDEO;
325
PTRACE(1, "GMVideoOutputManager_X\tPIP: Could not open remote X Window - no video");
331
if (current_frame.accel == Ekiga::VO_ACCEL_REMOTE_ONLY) {
332
lxWindow = new XVWindow();
333
if (lxWindow->Init ( rxWindow->GetDisplay (),
334
rxWindow->GetWindowHandle (),
336
(int) (current_frame.remote_width * current_frame.zoom / 100 * 2 / 3),
337
(int) (current_frame.remote_height * current_frame.zoom / 100 * 2 / 3),
338
(int) (current_frame.remote_width * current_frame.zoom / 100 / 3),
339
(int) (current_frame.remote_height * current_frame.zoom / 100 / 3),
340
current_frame.local_width,
341
current_frame.local_height)) {
342
current_frame.accel = Ekiga::VO_ACCEL_ALL;
343
pip_window_available = true;
344
PTRACE(4, "GMVideoOutputManager_X\tPIP: Successfully opened local XV Window");
349
pip_window_available = false;
350
PTRACE(1, "GMVideoOutputManager_X\tPIP: Could not open local XV Window");
354
if ((current_frame.accel != Ekiga::VO_ACCEL_ALL) && (local_display_info.allow_pip_sw_scaling)) {
355
PTRACE(3, "GMVideoOutputManager_X\tFalling back to SW" << ((local_display_info.disable_hw_accel)
356
? " since HW acceleration was deactivated by configuration"
357
: " since HW acceleration failed to initalize"));
358
lxWindow = new XWindow ();
359
if (lxWindow->Init ( lDisplay,
360
rxWindow->GetWindowHandle (),
361
(current_frame.mode == Ekiga::VO_MODE_PIP) ? local_display_info.gc : NULL,
362
(int) (current_frame.remote_width * current_frame.zoom / 100 * 2 / 3),
363
(int) (current_frame.remote_height * current_frame.zoom / 100 * 2 / 3),
364
(int) (current_frame.remote_width * current_frame.zoom / 100 / 3),
365
(int) (current_frame.remote_height * current_frame.zoom / 100 / 3),
366
current_frame.local_width,
367
current_frame.local_height)) {
368
lxWindow->SetSwScalingAlgo(local_display_info.sw_scaling_algorithm);
369
pip_window_available = true;
370
PTRACE(4, "GMVideoOutputManager_X\tPIP: Successfully opened local X Window");
375
pip_window_available = false;
376
PTRACE(4, "GMVideoOutputManager_X\tPIP: Could not open local X Window - picture-in-picture disabled");
380
if ((current_frame.accel != Ekiga::VO_ACCEL_ALL) && (!local_display_info.allow_pip_sw_scaling)) {
381
PTRACE(3, "GMVideoOutputManager_X\tNot opening PIP window since HW acceleration is not available and SW fallback is disabled by configuration");
382
current_frame.accel = Ekiga::VO_ACCEL_ALL;
385
if (rxWindow && lxWindow) {
387
rxWindow->RegisterSlave (lxWindow);
388
lxWindow->RegisterMaster (rxWindow);
391
if (rxWindow && current_frame.mode == Ekiga::VO_MODE_FULLSCREEN)
392
rxWindow->ToggleFullscreen ();
394
if ((current_frame.mode != Ekiga::VO_MODE_PIP_WINDOW) && (current_frame.mode != Ekiga::VO_MODE_FULLSCREEN)) {
395
last_frame.embedded_x = local_display_info.x;
396
last_frame.embedded_y = local_display_info.y;
399
last_frame.mode = current_frame.mode;
400
last_frame.local_width = current_frame.local_width;
401
last_frame.local_height = current_frame.local_height;
402
last_frame.remote_width = current_frame.remote_width;
403
last_frame.remote_height = current_frame.remote_height;
404
last_frame.zoom = current_frame.zoom;
407
case Ekiga::VO_MODE_UNSET:
413
if (local_display_info.on_top) {
416
lxWindow->ToggleOntop ();
418
rxWindow->ToggleOntop ();
421
last_frame.both_streams_active = current_frame.both_streams_active;
423
if (video_disabled) {
424
Ekiga::Runtime::run_in_main (boost::bind (&GMVideoOutputManager_x::device_error_in_main, this, Ekiga::VO_ERROR));
427
Ekiga::Runtime::run_in_main (boost::bind (&GMVideoOutputManager_x::device_opened_in_main, this, current_frame.accel, current_frame.mode, current_frame.zoom, current_frame.both_streams_active));
432
GMVideoOutputManager_x::close_frame_display ()
434
Ekiga::Runtime::run_in_main (boost::bind (&GMVideoOutputManager_x::device_closed_in_main, this));
437
rxWindow->RegisterSlave (NULL);
439
lxWindow->RegisterMaster (NULL);
453
GMVideoOutputManager_x::display_frame (const char *frame,
458
rxWindow->ProcessEvents();
461
lxWindow->ProcessEvents();
463
if ((current_frame.mode == Ekiga::VO_MODE_LOCAL) && (lxWindow))
464
lxWindow->PutFrame ((uint8_t *) frame, width, height);
466
if ((current_frame.mode == Ekiga::VO_MODE_REMOTE) && (rxWindow))
467
rxWindow->PutFrame ((uint8_t *) frame, width, height);
471
GMVideoOutputManager_x::display_pip_frames (const char *local_frame,
474
const char *remote_frame,
479
rxWindow->ProcessEvents();
482
lxWindow->ProcessEvents();
484
if (current_frame.mode == Ekiga::VO_MODE_FULLSCREEN && rxWindow && !rxWindow->IsFullScreen ())
485
Ekiga::Runtime::run_in_main (boost::bind (&GMVideoOutputManager_x::fullscreen_mode_changed_in_main, this, Ekiga::VO_FS_OFF));
487
if (rxWindow && (update_required.remote || (!update_required.remote && !update_required.local)))
488
rxWindow->PutFrame ((uint8_t *) remote_frame, rf_width, rf_height);
490
if (lxWindow && (update_required.local || (!update_required.remote && !update_required.local)))
491
lxWindow->PutFrame ((uint8_t *) local_frame, lf_width, lf_height);
495
GMVideoOutputManager_x::sync (UpdateRequired sync_required)
497
if (rxWindow && (sync_required.remote || (!sync_required.remote && !sync_required.local))) {
501
if (lxWindow && (sync_required.local || (!sync_required.remote && !sync_required.local))) {
507
GMVideoOutputManager_x::size_changed_in_main (unsigned width,
510
size_changed (width, height);
514
GMVideoOutputManager_x::device_opened_in_main (Ekiga::VideoOutputAccel accel,
515
Ekiga::VideoOutputMode mode,
519
device_opened (accel, mode, zoom, both);
523
GMVideoOutputManager_x::device_closed_in_main ()
529
GMVideoOutputManager_x::device_error_in_main (Ekiga::VideoOutputErrorCodes code)
535
GMVideoOutputManager_x::fullscreen_mode_changed_in_main (Ekiga::VideoOutputFSToggle val)
537
fullscreen_mode_changed (val);