initial commit
[goodguy/history.git] / cinelerra-5.0 / cinelerra / preferencesthread.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 "aboutprefs.h"
23 #include "asset.h"
24 #include "audiodevice.inc"
25 #include "bcsignals.h"
26 #include "cache.h"
27 #include "cplayback.h"
28 #include "cwindow.h"
29 #include "cwindowgui.h"
30 #include "bchash.h"
31 #include "edl.h"
32 #include "edlsession.h"
33 #include "filesystem.h"
34 #include "fonts.h"
35 #include "interfaceprefs.h"
36 #include "keys.h"
37 #include "language.h"
38 #include "levelwindow.h"
39 #include "levelwindowgui.h"
40 #include "mainerror.h"
41 #include "meterpanel.h"
42 #include "mutex.h"
43 #include "mwindow.h"
44 #include "mwindowgui.h"
45 #include "patchbay.h"
46 #include "performanceprefs.h"
47 #include "playbackengine.h"
48 #include "playbackprefs.h"
49 #include "preferences.h"
50 #include "recordprefs.h"
51 #include "theme.h"
52 #include "trackcanvas.h"
53 #include "transportque.h"
54 #include "vwindow.h"
55 #include "vwindowgui.h"
56
57 #include <string.h>
58
59
60
61 #define WIDTH 750
62 #define HEIGHT 670
63
64
65 PreferencesMenuitem::PreferencesMenuitem(MWindow *mwindow)
66  : BC_MenuItem(_("Preferences..."), "Shift+P", 'P')
67 {
68         this->mwindow = mwindow; 
69
70         set_shift(1);
71         thread = new PreferencesThread(mwindow);
72 }
73
74 PreferencesMenuitem::~PreferencesMenuitem()
75 {
76         delete thread;
77 }
78
79
80 int PreferencesMenuitem::handle_event() 
81 {
82         mwindow->gui->unlock_window();
83         thread->start();
84         mwindow->gui->lock_window("PreferencesMenuitem::handle_event");
85         return 1;
86 }
87
88
89
90
91 PreferencesThread::PreferencesThread(MWindow *mwindow)
92  : BC_DialogThread()
93 {
94         this->mwindow = mwindow;
95         window = 0;
96         thread_running = 0;
97 }
98
99 PreferencesThread::~PreferencesThread()
100 {
101 }
102
103 BC_Window* PreferencesThread::new_gui()
104 {
105
106         preferences = new Preferences;
107         edl = new EDL;
108         edl->create_objects();
109         current_dialog = mwindow->defaults->get("DEFAULTPREF", 0);
110         preferences->copy_from(mwindow->preferences);
111         edl->copy_session(mwindow->edl);
112         redraw_indexes = 0;
113         redraw_meters = 0;
114         redraw_times = 0;
115         redraw_overlays = 0;
116         close_assets = 0;
117         reload_plugins = 0;
118         //int need_new_indexes = 0;
119         rerender = 0;
120
121         mwindow->gui->lock_window("NewThread::new_gui");
122         int scr_x = mwindow->gui->get_screen_x(0, -1);
123         int scr_w = mwindow->gui->get_screen_w(0, -1);
124         int scr_h = mwindow->gui->get_screen_h(0, -1);
125
126         int x = scr_x + scr_w / 2 - WIDTH / 2;
127         int y = scr_h / 2 - HEIGHT / 2;
128
129         window = new PreferencesWindow(mwindow, this, x, y);
130         window->create_objects();
131         mwindow->gui->unlock_window();
132
133         thread_running = 1;
134         return window;
135 }
136
137 void PreferencesThread::handle_close_event(int result)
138 {
139         thread_running = 0;
140         if(!result)
141         {
142                 apply_settings();
143                 mwindow->save_defaults();
144         }
145
146         window = 0;
147         delete preferences;
148         edl->Garbage::remove_user();
149         preferences = 0;
150         edl = 0;
151
152         mwindow->defaults->update("DEFAULTPREF", current_dialog);
153 }
154
155
156
157 int PreferencesThread::update_framerate()
158 {
159         if(thread_running)
160         {
161                 lock_gui("PreferencesThread::update_framerate");
162                 PreferencesWindow *window = (PreferencesWindow*)get_gui();
163                 if(window) window->update_framerate();
164                 unlock_gui();
165         }
166         return 0;
167 }
168
169
170 void PreferencesThread::update_rates()
171 {
172         if(thread_running)
173         {
174                 lock_gui("PreferencesThread::update_framerate");
175                 PreferencesWindow *window = (PreferencesWindow*)get_gui();
176                 if(window) window->update_rates();
177                 unlock_gui();
178         }
179 }
180
181 int PreferencesThread::apply_settings()
182 {
183 // Compare sessions                                                                                     
184
185         PlaybackConfig *this_playback_config = edl->session->playback_config;
186         AudioOutConfig *this_aconfig = this_playback_config->aconfig;
187         VideoOutConfig *this_vconfig = this_playback_config->vconfig;
188         PlaybackConfig *playback_config = mwindow->edl->session->playback_config;
189         AudioOutConfig *aconfig = playback_config->aconfig;
190         VideoOutConfig *vconfig = playback_config->vconfig;
191
192         rerender = 
193                 edl->session->need_rerender(mwindow->edl->session) ||
194                 (preferences->force_uniprocessor != preferences->force_uniprocessor) ||
195                 this_playback_config->active_config != playback_config->active_config ||
196                 (*this_aconfig != *aconfig) || (*this_vconfig != *vconfig) ||
197                 !preferences->brender_asset->equivalent(*mwindow->preferences->brender_asset, 0, 1);
198
199         if( preferences->file_forking != mwindow->preferences->file_forking ) {
200                 MainError::show_error(
201                         _("Reseting file forking requires restarting cinelerra"));
202         }
203         mwindow->edl->copy_session(edl, 1);
204         mwindow->preferences->copy_from(preferences);
205         mwindow->init_brender();
206
207         BC_Signals::set_catch_segv(mwindow->preferences->trap_sigsegv);
208         BC_Signals::set_catch_intr(mwindow->preferences->trap_sigintr);
209
210         mwindow->reset_android_remote();
211
212 //edl->session->recording_format->dump();
213 //mwindow->edl->session->recording_format->dump();
214
215         if(((mwindow->edl->session->output_w % 4) || 
216                 (mwindow->edl->session->output_h % 4)) && 
217                 mwindow->edl->session->playback_config->vconfig->driver == PLAYBACK_X11_GL)
218         {
219                 MainError::show_error(
220                         _("This project's dimensions are not multiples of 4 so\n"
221                         "it can't be rendered by OpenGL."));
222         }
223
224
225         if(redraw_meters)
226         {
227                 mwindow->cwindow->gui->lock_window("PreferencesThread::apply_settings");
228                 mwindow->cwindow->gui->meters->change_format(edl->session->meter_format,
229                         edl->session->min_meter_db,
230                         edl->session->max_meter_db);
231                 mwindow->cwindow->gui->unlock_window();
232
233
234
235                 for(int i = 0; i < mwindow->vwindows.size(); i++)
236                 {
237                         VWindow *vwindow = mwindow->vwindows.get(i);
238                         vwindow->gui->lock_window("PreferencesThread::apply_settings");
239                         vwindow->gui->meters->change_format(edl->session->meter_format,
240                                 edl->session->min_meter_db,
241                                 edl->session->max_meter_db);
242                         vwindow->gui->unlock_window();
243
244                 }
245
246
247                 mwindow->gui->lock_window("PreferencesThread::apply_settings 1");
248                 mwindow->gui->set_meter_format(edl->session->meter_format,
249                         edl->session->min_meter_db,
250                         edl->session->max_meter_db);
251                 mwindow->gui->unlock_window();
252
253
254
255                 mwindow->lwindow->gui->lock_window("PreferencesThread::apply_settings");
256                 mwindow->lwindow->gui->panel->change_format(edl->session->meter_format,
257                         edl->session->min_meter_db,
258                         edl->session->max_meter_db);
259                 mwindow->lwindow->gui->unlock_window();
260         }
261
262         if(redraw_overlays)
263         {
264                 mwindow->gui->lock_window("PreferencesThread::apply_settings 2");
265                 mwindow->gui->draw_overlays(1);
266                 mwindow->gui->unlock_window();
267         }
268
269         if(redraw_times)
270         {
271                 mwindow->gui->lock_window("PreferencesThread::apply_settings 3");
272                 mwindow->gui->update(0, 0, 1, 0, 0, 1, 0);
273                 mwindow->gui->redraw_time_dependancies();
274                 mwindow->gui->unlock_window();
275         }
276
277         if(rerender)
278         {
279 //printf("PreferencesThread::apply_settings 1\n");
280 // This doesn't stop and restart, only reloads the assets before
281 // the next play command.
282                 mwindow->cwindow->playback_engine->que->send_command(CURRENT_FRAME,
283                         CHANGE_ALL,
284                         mwindow->edl,
285                         1);
286 //printf("PreferencesThread::apply_settings 10\n");
287         }
288
289         if(redraw_times || redraw_overlays)
290         {
291                 mwindow->gui->lock_window("PreferencesThread::apply_settings 4");
292                 mwindow->gui->flush();
293                 mwindow->gui->unlock_window();
294         }
295
296         return 0;
297 }
298
299 const char* PreferencesThread::category_to_text(int category)
300 {
301         PlaybackConfig *playback_config = edl->session->playback_config;
302         switch(category)
303         {
304                 case PLAYBACK_A:
305                         return playback_config->active_config==0 ?
306                                  _("*Playback A") : _("Playback A");
307                 case PLAYBACK_B:
308                         return playback_config->active_config==1 ?
309                                  _("*Playback B") : _("Playback B");
310                 case RECORD:
311                         return _("Recording");
312                 case PERFORMANCE:
313                         return _("Performance");
314                 case INTERFACE:
315                         return _("Interface");
316                 case ABOUT:
317                         return _("About");
318         }
319         return "";
320 }
321
322 int PreferencesThread::text_to_category(const char *category)
323 {
324 SET_TRACE
325         int min_result = -1, result, result_num = 0;
326         for(int i = 0; i < CATEGORIES; i++)
327         {
328                 result = labs(strcmp(category_to_text(i), category));
329                 if(result < min_result || min_result < 0) 
330                 {
331                         min_result = result;
332                         result_num = i;
333                 }
334         }
335 SET_TRACE
336         return result_num;
337 }
338
339
340
341
342
343
344
345
346 PreferencesWindow::PreferencesWindow(MWindow *mwindow, 
347         PreferencesThread *thread,
348         int x,
349         int y)
350  : BC_Window(PROGRAM_NAME ": Preferences", 
351         x,
352         y,
353         WIDTH, 
354         HEIGHT,
355         (int)BC_INFINITY,
356         (int)BC_INFINITY,
357         0,
358         0,
359         1)
360 {
361         this->mwindow = mwindow;
362         this->thread = thread;
363         dialog = 0;
364         category = 0;
365 }
366
367 PreferencesWindow::~PreferencesWindow()
368 {
369         lock_window("PreferencesWindow::~PreferencesWindow");
370         delete category;
371
372
373         if(dialog) delete dialog;
374
375
376         for(int i = 0; i < categories.total; i++)
377                 delete categories.values[i];
378         unlock_window();
379 }
380
381 void PreferencesWindow::create_objects()
382 {
383         BC_Button *button;
384
385
386
387         lock_window("PreferencesWindow::create_objects");
388
389         mwindow->theme->draw_preferences_bg(this);
390         flash();
391
392         int x = mwindow->theme->preferencescategory_x;
393         int y = mwindow->theme->preferencescategory_y;
394         for(int i = 0; i < CATEGORIES; i++)
395         {
396                 add_subwindow(category_button[i] = new PreferencesButton(mwindow,
397                         thread,
398                         x,
399                         y,
400                         i,
401                         thread->category_to_text(i),
402                         (i == thread->current_dialog) ?
403                                 mwindow->theme->get_image_set("category_button_checked") : 
404                                 mwindow->theme->get_image_set("category_button")));
405                 x += category_button[i]->get_w() -
406                         mwindow->theme->preferences_category_overlap;
407         }
408
409
410 //      for(int i = 0; i < CATEGORIES; i++)
411 //              categories.append(new BC_ListBoxItem(thread->category_to_text(i)));
412 //      category = new PreferencesCategory(mwindow, 
413 //              thread, 
414 //              mwindow->theme->preferencescategory_x, 
415 //              mwindow->theme->preferencescategory_y);
416 //      category->create_objects();
417
418
419         add_subwindow(button = new PreferencesOK(mwindow, thread));
420         add_subwindow(new PreferencesApply(mwindow, thread));
421         add_subwindow(new PreferencesCancel(mwindow, thread));
422
423         set_current_dialog(thread->current_dialog);
424
425         show_window();
426         unlock_window();
427 }
428
429 int PreferencesWindow::update_framerate()
430 {
431         lock_window("PreferencesWindow::update_framerate");
432         if(thread->current_dialog < PreferencesThread::RECORD)
433         {
434                 dialog->draw_framerate(1);
435 //              flash();
436         }
437         unlock_window();
438         return 0;
439 }
440
441
442 void PreferencesWindow::update_rates()
443 {
444         lock_window("PreferencesWindow::update_rates");
445         if(thread->current_dialog == PreferencesThread::PERFORMANCE)
446         {
447                 dialog->update_rates();
448         }
449         unlock_window();
450 }
451
452
453 int PreferencesWindow::set_current_dialog(int number)
454 {
455         if(dialog) delete dialog;
456         dialog = 0;
457         thread->current_dialog = number;
458
459 //PRINT_TRACE
460         PreferencesDialog *dialog2 = dialog;
461         dialog = 0;
462 //PRINT_TRACE
463
464 // Redraw category buttons
465         for(int i = 0; i < CATEGORIES; i++)
466         {
467                 if(i == number)
468                 {
469                         category_button[i]->set_images(
470                                 mwindow->theme->get_image_set("category_button_checked"));
471                 }
472                 else
473                 {
474                         category_button[i]->set_images(
475                                 mwindow->theme->get_image_set("category_button"));
476                 }
477                 category_button[i]->draw_face(0);
478
479 // Copy face to background for next button's overlap.
480 // Still can't do state changes right.
481         }
482
483
484 //PRINT_TRACE
485         PlaybackConfig *playback_config = thread->edl->session->playback_config;
486         switch(number)
487         {
488                 case PreferencesThread::PLAYBACK_A:
489                 case PreferencesThread::PLAYBACK_B:
490                         playback_config->load_defaults(mwindow->defaults,
491                                 number == PreferencesThread::PLAYBACK_A ? 0 : 1);
492                         add_subwindow(dialog = new PlaybackPrefs(mwindow, this, number));
493                         break;
494         
495                 case PreferencesThread::RECORD:
496                         add_subwindow(dialog = new RecordPrefs(mwindow, this));
497                         break;
498         
499                 case PreferencesThread::PERFORMANCE:
500                         add_subwindow(dialog = new PerformancePrefs(mwindow, this));
501                         break;
502         
503                 case PreferencesThread::INTERFACE:
504                         add_subwindow(dialog = new InterfacePrefs(mwindow, this));
505                         break;
506         
507                 case PreferencesThread::ABOUT:
508                         add_subwindow(dialog = new AboutPrefs(mwindow, this));
509                         break;
510         }
511
512 //PRINT_TRACE
513         if(dialog)
514         {
515                 dialog->draw_top_background(this, 0, 0, dialog->get_w(), dialog->get_h());
516 //printf("PreferencesWindow::set_current_dialog %d\n", __LINE__);
517                 dialog->create_objects();
518 //printf("PreferencesWindow::set_current_dialog %d\n", __LINE__);
519                 dialog->show_window(0);
520         }
521
522         if(dialog2) 
523         {
524                 dialog2->hide_window(0);
525                 delete dialog2;
526         }
527
528         return 0;
529 }
530
531
532
533
534
535
536
537
538
539
540
541 PreferencesButton::PreferencesButton(MWindow *mwindow, 
542         PreferencesThread *thread, 
543         int x, 
544         int y,
545         int category,
546         const char *text,
547         VFrame **images)
548  : BC_GenericButton(x, y, text, images)
549 {
550         this->mwindow = mwindow;
551         this->thread = thread;
552         this->category = category;
553 }
554
555 int PreferencesButton::handle_event()
556 {
557         thread->window->set_current_dialog(category);
558         return 1;
559 }
560
561
562
563
564
565
566
567
568
569 PreferencesDialog::PreferencesDialog(MWindow *mwindow, 
570         PreferencesWindow *pwindow)
571  : BC_SubWindow(10, 
572         40, 
573         pwindow->get_w() - 20, 
574         pwindow->get_h() - BC_GenericButton::calculate_h() - 10 - 40)
575 {
576         this->pwindow = pwindow;
577         this->mwindow = mwindow;
578         preferences = pwindow->thread->preferences;
579 }
580
581 PreferencesDialog::~PreferencesDialog()
582 {
583 }
584
585 // ============================== category window
586
587
588
589
590 PreferencesApply::PreferencesApply(MWindow *mwindow, PreferencesThread *thread)
591  : BC_GenericButton(thread->window->get_w() / 2 - BC_GenericButton::calculate_w(thread->window, _("Apply")) / 2, 
592         thread->window->get_h() - BC_GenericButton::calculate_h() - 10, 
593         _("Apply"))
594 {
595         this->mwindow = mwindow;
596         this->thread = thread;
597 }
598
599 int PreferencesApply::handle_event()
600 {
601         thread->apply_settings();
602         return 1;
603 }
604
605
606
607
608 PreferencesOK::PreferencesOK(MWindow *mwindow, PreferencesThread *thread)
609  : BC_GenericButton(10, 
610         thread->window->get_h() - BC_GenericButton::calculate_h() - 10,
611         _("OK"))
612 {
613         this->mwindow = mwindow;
614         this->thread = thread;
615 }
616
617 int PreferencesOK::keypress_event()
618 {
619         if(get_keypress() == RETURN)
620         {
621                 thread->window->set_done(0);
622                 return 1;
623         }
624         return 0;
625 }
626 int PreferencesOK::handle_event()
627 {
628         thread->window->set_done(0);
629         return 1;
630 }
631
632
633
634 PreferencesCancel::PreferencesCancel(MWindow *mwindow, PreferencesThread *thread)
635  : BC_GenericButton(thread->window->get_w() - BC_GenericButton::calculate_w(thread->window, _("Cancel")) - 10,
636         thread->window->get_h() - BC_GenericButton::calculate_h() - 10,
637         _("Cancel"))
638 {
639         this->mwindow = mwindow;
640         this->thread = thread;
641 }
642 int PreferencesCancel::keypress_event()
643 {
644         if(get_keypress() == ESC)
645         {
646                 thread->window->set_done(1);
647                 return 1;
648         }
649         return 0;
650 }
651
652 int PreferencesCancel::handle_event()
653 {
654         thread->window->set_done(1);
655         return 1;
656 }
657
658
659
660
661
662
663
664
665
666
667 PreferencesCategory::PreferencesCategory(MWindow *mwindow, PreferencesThread *thread, int x, int y)
668  : BC_PopupTextBox(thread->window, 
669                 &thread->window->categories,
670                 thread->category_to_text(thread->current_dialog),
671                 x, 
672                 y, 
673                 200,
674                 150)
675 {
676         this->mwindow = mwindow;
677         this->thread = thread;
678 }
679
680 PreferencesCategory::~PreferencesCategory()
681 {
682 }
683
684 int PreferencesCategory::handle_event()
685 {
686 SET_TRACE
687         thread->window->set_current_dialog(thread->text_to_category(get_text()));
688 SET_TRACE
689         return 1;
690 }