improve delays created by vicon drawing locks, reset_cache segv fix, gang track toolt...
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / vdeviceprefs.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2011 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "bcsignals.h"
23 #include "channeldb.h"
24 #include "channelpicker.h"
25 #include "clip.h"
26 #include "edl.h"
27 #include "edlsession.h"
28 #include "formattools.h"
29 #include "language.h"
30 #include "mwindow.h"
31 #include "mainsession.h"
32 #include "vdeviceprefs.h"
33 #include "videoconfig.h"
34 #include "videodevice.inc"
35 #include "overlayframe.inc"
36 #include "playbackconfig.h"
37 #include "preferences.h"
38 #include "preferencesthread.h"
39 #include "recordconfig.h"
40 #include "recordprefs.h"
41 #include "theme.h"
42 #include <string.h>
43
44
45 VDevicePrefs::VDevicePrefs(int x,
46         int y,
47         PreferencesWindow *pwindow,
48         PreferencesDialog *dialog,
49         VideoOutConfig *out_config,
50         VideoInConfig *in_config,
51         int mode)
52 {
53         this->pwindow = pwindow;
54         this->dialog = dialog;
55         this->driver = DEV_UNKNOWN;
56         this->mode = mode;
57         this->out_config = out_config;
58         this->in_config = in_config;
59         this->x = x;
60         this->y = y;
61         menu = 0;
62         reset_objects();
63
64 }
65
66 VDevicePrefs::~VDevicePrefs()
67 {
68         delete_objects();
69         if(menu) delete menu;
70         int config = -1;
71         switch( pwindow->thread->current_dialog ) {
72         case PreferencesThread::PLAYBACK_A:  config = 0;  break;
73         case PreferencesThread::PLAYBACK_B:  config = 1;  break;
74         }
75         if( config >= 0 )
76                 pwindow->mwindow->session->save_x11_host(config, out_config->x11_host);
77 }
78
79
80 void VDevicePrefs::reset_objects()
81 {
82         device_title = 0;
83         port_title = 0;
84         follow_video_config = 0;
85         dvb_adapter_title = 0;
86         dvb_adapter_device = 0;
87         channel_title = 0;
88         output_title = 0;
89         syt_title = 0;
90
91         device_text = 0;
92         firewire_port = 0;
93         firewire_channel = 0;
94         firewire_channels = 0;
95         firewire_syt = 0;
96         firewire_path = 0;
97         fields_title = 0;
98         device_fields = 0;
99         use_direct_x11 = 0;
100
101         channel_picker = 0;
102 }
103
104 int VDevicePrefs::initialize(int creation)
105 {
106         int *driver = 0;
107         delete_objects();
108
109         switch(mode)
110         {
111                 case MODEPLAY:
112                         driver = &out_config->driver;
113                         break;
114
115                 case MODERECORD:
116                         driver = &in_config->driver;
117                         break;
118         }
119         this->driver = *driver;
120
121         if(!menu)
122         {
123                 dialog->add_subwindow(menu = new VDriverMenu(x, y + yS(10),
124                                 this, (mode == MODERECORD), driver));
125                 menu->create_objects();
126         }
127
128         switch(this->driver)
129         {
130                 case DEV_UNKNOWN:
131                         break;
132                 case VIDEO4LINUX2:
133                 case CAPTURE_JPEG_WEBCAM:
134                 case CAPTURE_YUYV_WEBCAM:
135                         create_v4l2_objs();
136                         break;
137                 case VIDEO4LINUX2JPEG:
138                         create_v4l2jpeg_objs();
139                         break;
140                 case VIDEO4LINUX2MPEG:
141                         create_v4l2mpeg_objs();
142                         break;
143                 case SCREENCAPTURE:
144                         create_screencap_objs();
145                         break;
146                 case PLAYBACK_X11:
147                 case PLAYBACK_X11_XV:
148                 case PLAYBACK_X11_GL:
149                         create_x11_objs();
150                         break;
151                 case PLAYBACK_DV1394:
152                 case PLAYBACK_FIREWIRE:
153                 case PLAYBACK_IEC61883:
154                 case CAPTURE_FIREWIRE:
155                 case CAPTURE_IEC61883:
156                         create_firewire_objs();
157                         break;
158                 case CAPTURE_DVB:
159                         create_dvb_objs();
160                         break;
161         }
162
163
164
165 // Update driver dependancies in file format
166         if(mode == MODERECORD && dialog && !creation)
167         {
168                 RecordPrefs *record_prefs = (RecordPrefs*)dialog;
169                 record_prefs->recording_format->update_driver(this->driver);
170         }
171
172         return 0;
173 }
174
175 int VDevicePrefs::delete_objects()
176 {
177         delete output_title;
178         delete channel_picker;
179         delete device_title;
180         delete device_text;
181         delete dvb_adapter_device;
182         delete follow_video_config;
183         delete dvb_adapter_title;
184         delete use_direct_x11;
185
186         delete port_title;
187
188         if(firewire_port) delete firewire_port;
189         if(channel_title) delete channel_title;
190         if(firewire_channel) delete firewire_channel;
191         if(firewire_path) delete firewire_path;
192         if(syt_title) delete syt_title;
193         if(firewire_syt) delete firewire_syt;
194         if(fields_title) delete fields_title;
195         if(device_fields) delete device_fields;
196
197         reset_objects();
198         driver = -1;
199         return 0;
200 }
201
202 int VDevicePrefs::get_h()
203 {
204         int margin = pwindow->mwindow->theme->widget_border;
205         return BC_Title::calculate_h(dialog, "X", MEDIUMFONT) + margin +
206                 BC_TextBox::calculate_h(dialog, MEDIUMFONT, 1, 1);
207 }
208
209 void VDevicePrefs::create_dvb_objs()
210 {
211         int x1 = x + menu->get_w() + xS(30);
212         int y1 = y + yS(10);
213         char *output_char = in_config->dvb_in_adapter;
214         int y2 = y1 - BC_Title::calculate_h(dialog, _("DVB Adapter:"), MEDIUMFONT) - yS(5);
215         BC_Resources *resources = BC_WindowBase::get_resources();
216         dvb_adapter_title = new BC_Title(x1, y2, _("DVB Adapter:"),
217                         MEDIUMFONT, resources->text_default);
218         dialog->add_subwindow(dvb_adapter_title);
219         dialog->add_subwindow(device_text = new VDeviceTextBox(x1, y1, output_char));
220         int x2 = x1 + device_text->get_w() + xS(5);
221         device_title = new BC_Title(x2, y2, _("dev:"),
222                         MEDIUMFONT, resources->text_default);
223         dialog->add_subwindow(device_title);
224         int *output_int = &in_config->dvb_in_device;
225         dvb_adapter_device = new VDeviceTumbleBox(this, x2, y1, output_int, 0, 9, xS(20));
226         dvb_adapter_device->create_objects();
227         x1 += xS(64);  y1 += device_text->get_h() + yS(5);
228         follow_video_config = new BC_CheckBox(x1, y1,
229                         &in_config->follow_video, _("Follow video config"));
230         dialog->add_subwindow(follow_video_config);
231 }
232
233 int VDevicePrefs::create_firewire_objs()
234 {
235         int xs5 = xS(5), ys20 = yS(20);
236         int *output_int = 0;
237         char *output_char = 0;
238         int x1 = x + menu->get_w() + xS(5);
239         BC_Resources *resources = BC_WindowBase::get_resources();
240
241 // Firewire path
242         switch(mode)
243         {
244                 case MODEPLAY:
245                         if(driver == PLAYBACK_DV1394)
246                                 output_char = out_config->dv1394_path;
247                         else
248                         if(driver == PLAYBACK_FIREWIRE)
249                                 output_char = out_config->firewire_path;
250                         break;
251                 case MODERECORD:
252                         if(driver == CAPTURE_FIREWIRE)
253                                 output_char = in_config->firewire_path;
254                         break;
255         }
256
257         if(output_char)
258         {
259                 dialog->add_subwindow(device_title = new BC_Title(x1, y, _("Device Path:"), MEDIUMFONT, resources->text_default));
260                 dialog->add_subwindow(firewire_path = new VDeviceTextBox(x1, y + ys20, output_char));
261                 x1 += firewire_path->get_w() + xs5;
262         }
263
264 // Firewire port
265         switch(mode)
266         {
267                 case MODEPLAY:
268                         if(driver == PLAYBACK_DV1394)
269                                 output_int = &out_config->dv1394_port;
270                         else
271                                 output_int = &out_config->firewire_port;
272                         break;
273                 case MODERECORD:
274                         output_int = &in_config->firewire_port;
275                         break;
276         }
277         dialog->add_subwindow(port_title = new BC_Title(x1, y, _("Port:"), MEDIUMFONT, resources->text_default));
278         dialog->add_subwindow(firewire_port = new VDeviceIntBox(x1, y + ys20, output_int));
279         x1 += firewire_port->get_w() + xs5;
280
281 // Firewire channel
282         switch(mode)
283         {
284                 case MODEPLAY:
285                         if(driver == PLAYBACK_DV1394)
286                                 output_int = &out_config->dv1394_channel;
287                         else
288                                 output_int = &out_config->firewire_channel;
289                         break;
290                 case MODERECORD:
291                         output_int = &in_config->firewire_channel;
292                         break;
293         }
294
295         dialog->add_subwindow(channel_title = new BC_Title(x1, y, _("Channel:"), MEDIUMFONT, resources->text_default));
296         dialog->add_subwindow(firewire_channel = new VDeviceIntBox(x1, y + ys20, output_int));
297         x1 += firewire_channel->get_w() + xs5;
298
299
300 // Firewire syt
301         switch(mode)
302         {
303                 case MODEPLAY:
304                         if(driver == PLAYBACK_DV1394)
305                                 output_int = &out_config->dv1394_syt;
306                         else
307                         if(driver == PLAYBACK_FIREWIRE)
308                                 output_int = &out_config->firewire_syt;
309                         else
310                                 output_int = 0;
311                         break;
312                 case MODERECORD:
313                         output_int = 0;
314                         break;
315         }
316         if(output_int)
317         {
318                 dialog->add_subwindow(syt_title = new BC_Title(x1, y, _("Syt Offset:"), MEDIUMFONT, resources->text_default));
319                 dialog->add_subwindow(firewire_syt = new VDeviceIntBox(x1, y + ys20, output_int));
320         }
321
322         return 0;
323 }
324
325 int VDevicePrefs::create_v4l2_objs()
326 {
327         int xs5 = xS(5), ys20 = yS(20);
328         char *output_char;
329         BC_Resources *resources = BC_WindowBase::get_resources();
330         int x1 = x + menu->get_w() + xs5;
331         output_char = pwindow->thread->edl->session->vconfig_in->v4l2_in_device;
332         dialog->add_subwindow(device_title = new BC_Title(x1, y, _("Device path:"), MEDIUMFONT, resources->text_default));
333         dialog->add_subwindow(device_text = new VDeviceTextBox(x1, y + ys20, output_char));
334
335         return 0;
336 }
337
338 int VDevicePrefs::create_v4l2jpeg_objs()
339 {
340         int xs5 = xS(5), ys20 = yS(20);
341         BC_Resources *resources = BC_WindowBase::get_resources();
342         int x1 = x + menu->get_w() + xs5;
343         char *output_char = &pwindow->thread->edl->session->vconfig_in->v4l2jpeg_in_device[0];
344         dialog->add_subwindow(device_title = new BC_Title(x1, y, _("Device path:"), MEDIUMFONT, resources->text_default));
345         dialog->add_subwindow(device_text = new VDeviceTextBox(x1, y + ys20, output_char));
346         x1 += bmax(device_title->get_w(),device_text->get_w()) + xs5;
347         int *output_int = &pwindow->thread->edl->session->vconfig_in->v4l2jpeg_in_fields;
348         fields_title = new BC_Title(x1, y, _("Fields:"), MEDIUMFONT, resources->text_default);
349         dialog->add_subwindow(fields_title);
350         device_fields = new VDeviceTumbleBox(this, x1, y + ys20, output_int, 1, 2, xS(20));
351         device_fields->create_objects();
352         return 0;
353 }
354
355 int VDevicePrefs::create_v4l2mpeg_objs()
356 {
357         char *output_char;
358         BC_Resources *resources = BC_WindowBase::get_resources();
359         int x1 = x + menu->get_w() + xS(5);
360         output_char = pwindow->thread->edl->session->vconfig_in->v4l2mpeg_in_device;
361         dialog->add_subwindow(device_title = new BC_Title(x1, y, _("Device path:"), MEDIUMFONT, resources->text_default));
362         int y1 = y + yS(20);
363         dialog->add_subwindow(device_text = new VDeviceTextBox(x1, y1, output_char));
364         x1 += xS(64);  y1 += device_text->get_h() + yS(5);
365         follow_video_config = new BC_CheckBox(x1, y1,
366                         &in_config->follow_video, _("Follow video config"));
367         dialog->add_subwindow(follow_video_config);
368         return 0;
369 }
370
371
372 int VDevicePrefs::create_screencap_objs()
373 {
374         char *output_char;
375         BC_Resources *resources = BC_WindowBase::get_resources();
376         int x1 = x + menu->get_w() + xS(5);
377         output_char = pwindow->thread->edl->session->vconfig_in->screencapture_display;
378         dialog->add_subwindow(device_title = new BC_Title(x1, y, _("Display:"), MEDIUMFONT, resources->text_default));
379         dialog->add_subwindow(device_text = new VDeviceTextBox(x1, y + yS(20), output_char));
380         return 0;
381 }
382
383 int VDevicePrefs::create_x11_objs()
384 {
385         char *output_char;
386         BC_Resources *resources = BC_WindowBase::get_resources();
387         output_char = out_config->x11_host;
388         const char *x11_display;
389         switch( pwindow->thread->current_dialog ) {
390         default:
391         case PreferencesThread::PLAYBACK_A:
392                 x11_display = _("Default A Display:");  break;
393                 break;
394         case PreferencesThread::PLAYBACK_B:
395                 x11_display = _("Default B Display:");  break;
396                 break;
397         }
398         int x1 = menu->get_x() + menu->get_w() + xS(10);
399         int y1 = menu->get_y();
400         if( driver == PLAYBACK_X11 ) y1 -= yS(10);
401         dialog->add_subwindow(device_title = new BC_Title(x1, y1+yS(4), x11_display,
402                         MEDIUMFONT, resources->text_default));
403         int x2 = x1 + device_title->get_w() + xS(10), dy = device_title->get_h();
404         dialog->add_subwindow(device_text = new VDeviceTextBox(x2, y1, output_char));
405         if( driver == PLAYBACK_X11 ) {
406                 int y2 = device_text->get_h();
407                 if( dy < y2 ) dy = y2;
408                 y1 += dy + yS(5);
409                 use_direct_x11 = new BC_CheckBox(x1, y1,
410                         &out_config->use_direct_x11, _("use direct x11 render if possible"));
411                 dialog->add_subwindow(use_direct_x11);
412         }
413         return 0;
414 }
415
416
417
418
419 VDriverMenu::VDriverMenu(int x, int y,
420         VDevicePrefs *device_prefs, int do_input, int *output)
421  : BC_PopupMenu(x, y, xS(200), driver_to_string(*output))
422 {
423         this->output = output;
424         this->do_input = do_input;
425         this->device_prefs = device_prefs;
426 }
427
428 VDriverMenu::~VDriverMenu()
429 {
430 }
431
432 char* VDriverMenu::driver_to_string(int driver)
433 {
434         switch(driver)
435         {
436                 case DEV_UNKNOWN:
437                         sprintf(string, DEV_UNKNOWN_TITLE);
438                         break;
439                 case VIDEO4LINUX2:
440                         sprintf(string, VIDEO4LINUX2_TITLE);
441                         break;
442                 case CAPTURE_JPEG_WEBCAM:
443                         sprintf(string, CAPTURE_JPEG_WEBCAM_TITLE);
444                         break;
445                 case CAPTURE_YUYV_WEBCAM:
446                         sprintf(string, CAPTURE_YUYV_WEBCAM_TITLE);
447                         break;
448                 case VIDEO4LINUX2JPEG:
449                         sprintf(string, VIDEO4LINUX2JPEG_TITLE);
450                         break;
451                 case VIDEO4LINUX2MPEG:
452                         sprintf(string, VIDEO4LINUX2MPEG_TITLE);
453                         break;
454                 case SCREENCAPTURE:
455                         sprintf(string, SCREENCAPTURE_TITLE);
456                         break;
457 #ifdef HAVE_FIREWIRE
458                 case CAPTURE_FIREWIRE:
459                         sprintf(string, CAPTURE_FIREWIRE_TITLE);
460                         break;
461                 case CAPTURE_IEC61883:
462                         sprintf(string, CAPTURE_IEC61883_TITLE);
463                         break;
464 #endif
465                 case CAPTURE_DVB:
466                         sprintf(string, CAPTURE_DVB_TITLE);
467                         break;
468                 case PLAYBACK_X11:
469                         sprintf(string, PLAYBACK_X11_TITLE);
470                         break;
471                 case PLAYBACK_X11_XV:
472                         sprintf(string, PLAYBACK_X11_XV_TITLE);
473                         break;
474                 case PLAYBACK_X11_GL:
475                         sprintf(string, PLAYBACK_X11_GL_TITLE);
476                         break;
477 #ifdef HAVE_FIREWIRE
478                 case PLAYBACK_FIREWIRE:
479                         sprintf(string, PLAYBACK_FIREWIRE_TITLE);
480                         break;
481                 case PLAYBACK_DV1394:
482                         sprintf(string, PLAYBACK_DV1394_TITLE);
483                         break;
484                 case PLAYBACK_IEC61883:
485                         sprintf(string, PLAYBACK_IEC61883_TITLE);
486                         break;
487 #endif
488                 default:
489                         string[0] = 0;
490         }
491         return string;
492 }
493
494 void VDriverMenu::create_objects()
495 {
496         if(do_input)
497         {
498 #ifdef HAVE_VIDEO4LINUX2
499                 add_item(new VDriverItem(this, VIDEO4LINUX2_TITLE, VIDEO4LINUX2));
500                 add_item(new VDriverItem(this, CAPTURE_JPEG_WEBCAM_TITLE, CAPTURE_JPEG_WEBCAM));
501                 add_item(new VDriverItem(this, CAPTURE_YUYV_WEBCAM_TITLE, CAPTURE_YUYV_WEBCAM));
502                 add_item(new VDriverItem(this, VIDEO4LINUX2JPEG_TITLE, VIDEO4LINUX2JPEG));
503                 add_item(new VDriverItem(this, VIDEO4LINUX2MPEG_TITLE, VIDEO4LINUX2MPEG));
504 #endif
505
506                 add_item(new VDriverItem(this, SCREENCAPTURE_TITLE, SCREENCAPTURE));
507 #ifdef HAVE_FIREWIRE
508                 add_item(new VDriverItem(this, CAPTURE_FIREWIRE_TITLE, CAPTURE_FIREWIRE));
509                 add_item(new VDriverItem(this, CAPTURE_IEC61883_TITLE, CAPTURE_IEC61883));
510 #endif
511 #ifdef HAVE_DVB
512                 add_item(new VDriverItem(this, CAPTURE_DVB_TITLE, CAPTURE_DVB));
513 #endif
514         }
515         else
516         {
517                 add_item(new VDriverItem(this, PLAYBACK_X11_TITLE, PLAYBACK_X11));
518 #ifdef HAVE_XV
519                 add_item(new VDriverItem(this, PLAYBACK_X11_XV_TITLE, PLAYBACK_X11_XV));
520 #endif
521 #ifdef HAVE_GL
522 // Check runtime glx version. pbuffer needs >= 1.3
523                 if(get_opengl_server_version() >= 103)
524                         add_item(new VDriverItem(this, PLAYBACK_X11_GL_TITLE, PLAYBACK_X11_GL));
525 #endif
526 #ifdef HAVE_FIREWIRE
527                 add_item(new VDriverItem(this, PLAYBACK_FIREWIRE_TITLE, PLAYBACK_FIREWIRE));
528                 add_item(new VDriverItem(this, PLAYBACK_DV1394_TITLE, PLAYBACK_DV1394));
529                 add_item(new VDriverItem(this, PLAYBACK_IEC61883_TITLE, PLAYBACK_IEC61883));
530 #endif
531         }
532 }
533
534
535 VDriverItem::VDriverItem(VDriverMenu *popup, const char *text, int driver)
536  : BC_MenuItem(text)
537 {
538         this->popup = popup;
539         this->driver = driver;
540 }
541
542 VDriverItem::~VDriverItem()
543 {
544 }
545
546 int VDriverItem::handle_event()
547 {
548         popup->set_text(get_text());
549         *(popup->output) = driver;
550         popup->device_prefs->initialize(0);
551         popup->device_prefs->pwindow->show_dialog();
552         return 1;
553 }
554
555
556
557
558 VDeviceTextBox::VDeviceTextBox(int x, int y, char *output)
559  : BC_TextBox(x, y, xS(200), 1, output)
560 {
561         this->output = output;
562 }
563
564 int VDeviceTextBox::handle_event()
565 {
566 // Suggestions
567         calculate_suggestions(0);
568
569         strcpy(output, get_text());
570         return 1;
571 }
572
573 VDeviceTumbleBox::VDeviceTumbleBox(VDevicePrefs *prefs,
574         int x, int y, int *output, int min, int max, int text_w)
575  : BC_TumbleTextBox(prefs->dialog, *output, min, max, x, y, text_w)
576 {
577         this->output = output;
578 }
579
580 int VDeviceTumbleBox::handle_event()
581 {
582         *output = atol(get_text());
583         return 1;
584 }
585
586
587
588
589
590
591 VDeviceIntBox::VDeviceIntBox(int x, int y, int *output)
592  : BC_TextBox(x, y, xS(60), 1, *output)
593 {
594         this->output = output;
595 }
596
597 int VDeviceIntBox::handle_event()
598 {
599         *output = atol(get_text());
600         return 1;
601 }
602
603
604
605
606
607 VDeviceCheckBox::VDeviceCheckBox(int x, int y, int *output, char *text)
608  : BC_CheckBox(x, y, *output, text)
609 {
610         this->output = output;
611 }
612 int VDeviceCheckBox::handle_event()
613 {
614         *output = get_value();
615         return 1;
616 }
617
618
619
620
621 VScalingItem::VScalingItem(VScalingEquation *popup, int interpolation)
622  : BC_MenuItem(popup->interpolation_to_string(interpolation))
623 {
624         this->popup = popup;
625         this->interpolation = interpolation;
626 }
627
628 VScalingItem::~VScalingItem()
629 {
630 }
631
632 int VScalingItem::handle_event()
633 {
634         popup->set_text(get_text());
635         *(popup->output) = interpolation;
636         return 1;
637 }
638
639
640 VScalingEquation::VScalingEquation(int x, int y, int *output)
641  : BC_PopupMenu(x, y, xS(240), interpolation_to_string(*output))
642 {
643         this->output = output;
644 }
645
646 VScalingEquation::~VScalingEquation()
647 {
648 }
649
650 const char *VScalingEquation::interpolation_to_string(int type)
651 {
652         switch( type ) {
653         case NEAREST_NEIGHBOR:  return _("Nearest Neighbor");
654         case CUBIC_CUBIC:       return _("BiCubic / BiCubic");
655         case CUBIC_LINEAR:      return _("BiCubic / BiLinear");
656         case LINEAR_LINEAR:     return _("BiLinear / BiLinear");
657         case LANCZOS_LANCZOS:   return _("Lanczos / Lanczos");
658         }
659         return _("Unknown");
660 }
661
662 void VScalingEquation::create_objects()
663 {
664         add_item(new VScalingItem(this, NEAREST_NEIGHBOR));
665         add_item(new VScalingItem(this, CUBIC_CUBIC));
666         add_item(new VScalingItem(this, CUBIC_LINEAR));
667         add_item(new VScalingItem(this, LINEAR_LINEAR));
668         add_item(new VScalingItem(this, LANCZOS_LANCZOS));
669 }
670