40
#include "../../config.h"
39
#define P_FORCE_STATIC_PLUGIN
42
41
#include "videoinput.h"
56
GMVideoGrabber::GMVideoGrabber (BOOL start_grabbing,
59
: PThread (1000, NoAutoDeleteThread), ep (endpoint)
73
is_grabbing = start_grabbing;
85
/* Start the thread */
87
thread_sync_point.Wait ();
91
GMVideoGrabber::~GMVideoGrabber ()
96
/* Wait for the device to be unlocked */
97
PWaitAndSignal q(device_mutex);
99
/* Wait for the Main () method to be terminated */
100
PWaitAndSignal m(quit_mutex);
105
GMVideoGrabber::Main ()
109
PWaitAndSignal m(quit_mutex);
110
thread_sync_point.Signal ();
118
if (is_grabbing == 1) {
120
grabber->GetFrame (frame);
122
display->SetFrameData (0, 0,
123
grabber->GetFrameWidth (),
124
grabber->GetFrameHeight (),
129
Current()->Sleep (5);
137
GMVideoGrabber::StartGrabbing (void)
139
PWaitAndSignal m(var_mutex);
146
GMVideoGrabber::StopGrabbing (void)
148
PWaitAndSignal m(var_mutex);
155
GMVideoGrabber::IsGrabbing (void)
157
PWaitAndSignal m(var_mutex);
164
GMVideoGrabber::GetInputDevice (void)
166
PWaitAndSignal m(var_mutex);
173
GMVideoGrabber::GetOutputDevice (void)
175
PWaitAndSignal m(var_mutex);
182
GMVideoGrabber::SetColour (int colour)
184
PWaitAndSignal m(var_mutex);
187
return grabber->SetColour (colour);
194
GMVideoGrabber::SetBrightness (int brightness)
196
PWaitAndSignal m(var_mutex);
199
return grabber->SetBrightness (brightness);
206
GMVideoGrabber::SetWhiteness (int whiteness)
208
PWaitAndSignal m(var_mutex);
211
return grabber->SetWhiteness (whiteness);
218
GMVideoGrabber::SetContrast (int constrast)
220
PWaitAndSignal m(var_mutex);
223
return grabber->SetContrast (constrast);
230
GMVideoGrabber::GetParameters (int *whiteness,
237
PWaitAndSignal m(var_mutex);
239
grabber->GetParameters (whiteness, brightness, colour, contrast, &hue);
241
*whiteness = (int) *whiteness / 256;
242
*brightness = (int) *brightness / 256;
243
*colour = (int) *colour / 256;
244
*contrast = (int) *contrast / 256;
249
GMVideoGrabber::Lock ()
251
device_mutex.Wait ();
256
GMVideoGrabber::Unlock ()
258
device_mutex.Signal ();
263
GMVideoGrabber::VGOpen (void)
265
GtkWidget *history_window = NULL;
266
GtkWidget *main_window = NULL;
268
PString input_device;
271
gchar *dialog_title = NULL;
272
gchar *dialog_msg = NULL;
273
gchar *tmp_msg = NULL;
274
gchar *conf_value = NULL;
280
BOOL no_device_found = FALSE;
282
PVideoDevice::VideoFormat format = PVideoDevice::PAL;
284
history_window = GnomeMeeting::Process ()->GetHistoryWindow ();
285
main_window = GnomeMeeting::Process ()->GetMainWindow ();
289
/* Get the video device options from the configuration database */
290
gnomemeeting_threads_enter ();
292
conf_value = gm_conf_get_string (VIDEO_DEVICES_KEY "input_device");
293
input_device = conf_value;
296
conf_value = gm_conf_get_string (VIDEO_DEVICES_KEY "plugin");
300
channel = gm_conf_get_int (VIDEO_DEVICES_KEY "channel");
302
size = gm_conf_get_int (VIDEO_DEVICES_KEY "size");
305
(PVideoDevice::VideoFormat) gm_conf_get_int (VIDEO_DEVICES_KEY "format");
307
height = (size == 0) ? GM_QCIF_HEIGHT : GM_CIF_HEIGHT;
308
width = (size == 0) ? GM_QCIF_WIDTH : GM_CIF_WIDTH;
310
no_device_found = (input_device == _("No device found"));
311
gnomemeeting_threads_leave ();
314
/* If there is no device, directly open the fake device */
315
if (!no_device_found) {
317
gnomemeeting_threads_enter ();
318
gm_history_window_insert (history_window,
319
_("Opening video device %s with plugin %s"),
320
(const char *) input_device,
321
(const char *) plugin);
322
gnomemeeting_threads_leave ();
326
PVideoInputDevice::CreateOpenedDevice (plugin, input_device, FALSE);
329
else if (!grabber->SetVideoFormat (format))
331
else if (!grabber->SetChannel (channel))
333
else if (!grabber->SetColourFormatConverter ("YUV420P"))
335
else if (!grabber->SetFrameRate (30))
337
else if (!grabber->SetFrameSizeConverter (width, height, FALSE))
345
gnomemeeting_threads_enter ();
346
gm_history_window_insert (history_window,
347
_("Successfully opened video device %s, channel %d"),
348
(const char *) input_device,
350
gnomemeeting_threads_leave ();
354
/* If we want to open the fake device for a real error, and not because
355
the user chose the Picture device */
356
gnomemeeting_threads_enter ();
358
g_strdup_printf (_("Error while opening video device %s"),
359
(const char *) input_device);
361
/* Translators: Do not translate MovingLogo and Picture */
362
tmp_msg = g_strdup (_("A moving logo will be transmitted during calls. Notice that you can always transmit a given image or the moving logo by choosing \"Picture\" as video plugin and \"MovingLogo\" or \"StaticPicture\" as device."));
363
gm_history_window_insert (history_window,
364
_("Couldn't open the video device"));
365
switch (error_code) {
368
dialog_msg = g_strconcat (tmp_msg, "\n\n", _("There was an error while opening the device. Please check your permissions and make sure that the appropriate driver is loaded."), NULL);
372
dialog_msg = g_strconcat (tmp_msg, "\n\n", _("Your video driver doesn't support the requested video format."), NULL);
376
dialog_msg = g_strconcat (tmp_msg, "\n\n", _("Could not open the chosen channel."), NULL);
380
dialog_msg = g_strconcat (tmp_msg, "\n\n", _("Your driver doesn't seem to support any of the color formats supported by Ekiga.\n Please check your kernel driver documentation in order to determine which Palette is supported."), NULL);
384
dialog_msg = g_strconcat (tmp_msg, "\n\n", _("Error while setting the frame rate."), NULL);
388
dialog_msg = g_strconcat (tmp_msg, "\n\n", _("Error while setting the frame size."), NULL);
392
gnomemeeting_warning_dialog_on_widget (GTK_WINDOW (main_window),
393
VIDEO_DEVICES_KEY "enable_preview",
397
g_free (dialog_title);
400
gnomemeeting_threads_leave ();
404
if (error_code || no_device_found) {
406
/* delete the failed grabber and open the fake grabber */
415
PVideoInputDevice::CreateOpenedDevice ("Picture",
420
grabber->SetColourFormatConverter ("YUV420P");
421
grabber->SetVideoFormat (PVideoDevice::PAL);
422
grabber->SetChannel (1);
423
grabber->SetFrameRate (6);
424
grabber->SetFrameSizeConverter (width, height, FALSE);
426
gnomemeeting_threads_enter ();
427
gm_history_window_insert (history_window,
428
_("Opened the video device using the \"Picture\" video plugin"));
429
gnomemeeting_threads_leave ();
439
display = PVideoOutputDevice::CreateDevice ("GDK");
440
display->Open ("GDKIN", FALSE);
441
display->SetFrameSizeConverter (width, height, FALSE);
442
display->SetColourFormatConverter ("YUV420P");
448
/* Setup the video settings */
449
GetParameters (&whiteness, &brightness, &colour, &contrast);
450
if (whiteness > 0 || brightness > 0 || colour > 0 || contrast > 0) {
452
gnomemeeting_threads_enter ();
453
gm_main_window_set_video_sliders_values (main_window,
458
gnomemeeting_threads_leave ();
462
/* Driver made a reset, keep the old values */
463
gnomemeeting_threads_enter ();
464
gm_main_window_get_video_sliders_values (main_window,
469
gnomemeeting_threads_leave ();
472
SetWhiteness (whiteness << 8);
474
SetBrightness (brightness << 8);
476
SetColour (colour << 8);
478
SetContrast (contrast << 8);
482
/* Update the GUI sensitivity if not in a call */
483
if (ep.GetCallingState () == GMManager::Standby) {
485
gnomemeeting_threads_enter ();
486
gm_main_window_update_sensitivity (main_window, TRUE, FALSE, TRUE);
487
gnomemeeting_threads_leave ();
494
GMVideoGrabber::VGClose ()
496
GtkWidget *main_window = NULL;
498
main_window = GnomeMeeting::Process ()->GetMainWindow ();
507
/* Update menu sensitivity if we are not in a call */
508
gnomemeeting_threads_enter ();
509
if (ep.GetCallingState () == GMManager::Standby
510
&& !gm_conf_get_bool (VIDEO_DEVICES_KEY "enable_preview")) {
512
gm_main_window_update_sensitivity (main_window, TRUE, FALSE, FALSE);
513
gm_main_window_update_logo (main_window);
516
/* Update the GUI view mode to make sure the video is shown */
518
(ViewMode) gm_conf_get_int (USER_INTERFACE_KEY "main_window/view_mode");
519
gm_main_window_set_view_mode (main_window, m);
520
gnomemeeting_threads_leave ();
534
/* Quick Hack for buggy drivers that return from the ioctl before the device
536
PThread::Current ()->Sleep (1000);
540
/* The video tester class */
541
GMVideoTester::GMVideoTester (gchar *manager,
543
:PThread (1000, AutoDeleteThread)
546
video_manager = PString (manager);
548
video_recorder = PString (recorder);
554
thread_sync_point.Wait ();
558
GMVideoTester::~GMVideoTester ()
560
PWaitAndSignal m(quit_mutex);
564
void GMVideoTester::Main ()
566
GtkWidget *druid_window = NULL;
568
PVideoInputDevice *grabber = NULL;
570
int height = GM_QCIF_HEIGHT;
571
int width = GM_QCIF_WIDTH;
575
gchar *dialog_msg = NULL;
578
druid_window = GnomeMeeting::Process ()->GetDruidWindow ();
580
PWaitAndSignal m(quit_mutex);
581
thread_sync_point.Signal ();
583
if (video_recorder.IsEmpty ()
584
|| video_manager.IsEmpty ()
585
|| video_recorder == PString (_("No device found"))
586
|| video_recorder == PString (_("Picture")))
589
gdk_threads_enter ();
591
gtk_dialog_new_with_buttons ("Video test running",
592
GTK_WINDOW (druid_window),
593
(GtkDialogFlags) (GTK_DIALOG_MODAL),
598
g_strdup_printf (_("Ekiga is now testing the %s video device. If you experience machine crashes, then report a bug to the video driver author."), (const char *) video_recorder);
599
test_label = gtk_label_new (dialog_msg);
600
gtk_label_set_line_wrap (GTK_LABEL (test_label), true);
603
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (test_dialog)->vbox), test_label,
605
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (test_dialog)->vbox),
606
gtk_hseparator_new (), FALSE, FALSE, 2);
608
test_label = gtk_label_new (NULL);
609
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (test_dialog)->vbox),
610
test_label, FALSE, FALSE, 2);
612
g_signal_connect (G_OBJECT (test_dialog), "delete-event",
613
G_CALLBACK (gtk_widget_hide_on_delete), NULL);
615
gtk_window_set_transient_for (GTK_WINDOW (test_dialog),
616
GTK_WINDOW (druid_window));
617
gtk_widget_show_all (GTK_DIALOG (test_dialog)->vbox);
618
gnomemeeting_threads_dialog_show (test_dialog);
619
gdk_threads_leave ();
622
while (cpt < 6 && error_code == -1) {
624
if (!video_recorder.IsEmpty ()
625
&& !video_manager.IsEmpty ()) {
630
PVideoInputDevice::CreateOpenedDevice (video_manager,
637
if (!grabber->SetVideoFormat (PVideoDevice::Auto))
640
if (!grabber->SetChannel (0))
643
if (!grabber->SetColourFormatConverter ("YUV420P"))
646
if (!grabber->SetFrameRate (30))
649
if (!grabber->SetFrameSizeConverter (width, height, FALSE))
659
if (error_code == -1)
660
dialog_msg = g_strdup_printf (_("Test %d done"), cpt);
662
dialog_msg = g_strdup_printf (_("Test %d failed"), cpt);
664
tmp = g_strdup_printf ("<b>%s</b>", dialog_msg);
665
gdk_threads_enter ();
666
gtk_label_set_markup (GTK_LABEL (test_label), tmp);
667
gdk_threads_leave ();
672
PThread::Current () ->Sleep (100);
676
if (error_code != - 1) {
678
switch (error_code) {
681
dialog_msg = g_strdup_printf (_("Error while opening %s."),
682
(const char *) video_recorder);
686
dialog_msg = g_strdup_printf (_("Your video driver doesn't support the requested video format."));
690
dialog_msg = g_strdup_printf (_("Could not open the chosen channel with the chosen video format."));
694
dialog_msg = g_strdup_printf (_("Your driver doesn't support any of the color formats tried by Ekiga"));
698
dialog_msg = g_strdup_printf ( _("Error with the frame rate."));
702
dialog_msg = g_strdup_printf (_("Error with the frame size."));
706
gdk_threads_enter ();
707
gnomemeeting_error_dialog (GTK_WINDOW (druid_window),
708
_("Failed to open the device"),
710
gdk_threads_leave ();
715
gdk_threads_enter ();
716
gm_druid_window_set_test_buttons_sensitivity (druid_window, FALSE);
718
gnomemeeting_threads_widget_destroy (test_dialog);
719
gdk_threads_leave ();
44
/* Plugin definition */
45
class PVideoInputDevice_EKIGA_PluginServiceDescriptor
46
: public PDevicePluginServiceDescriptor
49
virtual PObject *CreateInstance (int) const
51
return new PVideoInputDevice_EKIGA (*(GnomeMeeting::Process ()->GetServiceCore ()));
55
virtual PStringArray GetDeviceNames(int) const
57
return PStringList("EKIGA");
60
virtual bool ValidateDeviceName (const PString & deviceName,
63
return deviceName.Find("EKIGA") == 0;
65
} PVideoInputDevice_EKIGA_descriptor;
67
PCREATE_PLUGIN(EKIGA, PVideoInputDevice, &PVideoInputDevice_EKIGA_descriptor);
69
int PVideoInputDevice_EKIGA::devices_nbr = 0;
71
PVideoInputDevice_EKIGA::PVideoInputDevice_EKIGA (Ekiga::ServiceCore & _core)
72
: core (_core), videoinput_core (*(dynamic_cast<Ekiga::VideoInputCore *> (_core.get ("videoinput-core"))))
79
PVideoInputDevice_EKIGA::~PVideoInputDevice_EKIGA ()
85
PVideoInputDevice_EKIGA::Open (const PString &/*name*/,
88
if (start_immediate) {
90
if (devices_nbr == 0) {
91
videoinput_core.set_stream_config(frameWidth, frameHeight, frameRate);
92
videoinput_core.start_stream();
105
PVideoInputDevice_EKIGA::IsOpen ()
112
PVideoInputDevice_EKIGA::Close ()
117
videoinput_core.stop_stream();
127
PVideoInputDevice_EKIGA::Start ()
130
if (devices_nbr == 0) {
131
videoinput_core.set_stream_config(frameWidth, frameHeight, frameRate);
132
videoinput_core.start_stream();
143
PVideoInputDevice_EKIGA::Stop ()
150
PVideoInputDevice_EKIGA::IsCapturing ()
152
return IsCapturing ();
157
PVideoInputDevice_EKIGA::GetDeviceNames() const
159
PStringArray devlist;
160
devlist.AppendString(GetDeviceName());
167
PVideoInputDevice_EKIGA::SetFrameSize (unsigned int width,
170
if (!PVideoDevice::SetFrameSize (width, height))
178
PVideoInputDevice_EKIGA::GetFrameData (BYTE *frame,
183
videoinput_core.get_frame_data((char*)frame, width, height);
185
*i = width * height * 3 / 2;
191
bool PVideoInputDevice_EKIGA::GetFrameDataNoDelay (BYTE *frame,
196
videoinput_core.get_frame_data((char*)frame, width, height);
198
*i = width * height * 3 / 2;
204
PVideoInputDevice_EKIGA::TestAllFormats ()
211
PVideoInputDevice_EKIGA::GetMaxFrameBytes ()
213
return CalculateFrameBytes (frameWidth, frameHeight, colourFormat);
218
PVideoInputDevice_EKIGA::SetVideoFormat (VideoFormat newFormat)
220
return PVideoDevice::SetVideoFormat (newFormat);
225
PVideoInputDevice_EKIGA::GetNumChannels()
232
PVideoInputDevice_EKIGA::SetChannel (int /*newChannel*/)
239
PVideoInputDevice_EKIGA::SetColourFormat (const PString &newFormat)
241
if (newFormat == "YUV420P")
242
return PVideoDevice::SetColourFormat (newFormat);
249
PVideoInputDevice_EKIGA::SetFrameRate (unsigned rate)
251
PVideoDevice::SetFrameRate (rate);
258
PVideoInputDevice_EKIGA::GetFrameSizeLimits (unsigned & minWidth,
259
unsigned & minHeight,
261
unsigned & maxHeight)
272
bool PVideoInputDevice_EKIGA::GetParameters (int *whiteness,