3 #include "awindowgui.h"
5 #include "batchrender.h"
6 #include "bcdisplayinfo.h"
11 #include "channeldb.h"
13 #include "colormodels.h"
14 #include "cplayback.h"
16 #include "cwindowgui.h"
19 #include "devicedvbinput.inc"
20 #include "editpanel.h"
22 #include "edlsession.h"
24 #include "fileformat.h"
26 #include "filesystem.h"
28 #include "framecache.h"
30 #include "gwindowgui.h"
31 #include "indexfile.h"
32 #include "interlacemodes.h"
34 #include "levelwindowgui.h"
35 #include "levelwindow.h"
36 #include "loadfile.inc"
37 #include "localsession.h"
38 #include "maincursor.h"
39 #include "mainerror.h"
40 #include "mainindexes.h"
42 #include "mainprogress.h"
43 #include "mainsession.h"
47 #include "mwindowgui.h"
51 #include "playback3d.h"
52 #include "playbackengine.h"
54 #include "pluginserver.h"
55 #include "pluginset.h"
56 #include "preferences.h"
58 #include "recordlabel.h"
59 #include "removethread.h"
61 #include "samplescroll.h"
62 #include "sighandler.h"
63 #include "splashgui.h"
64 #include "statusbar.h"
66 #include "threadloader.h"
68 #include "tipwindow.h"
69 #include "trackcanvas.h"
72 #include "trackscroll.h"
74 #include "transition.h"
75 #include "transportque.h"
77 #include "videodevice.inc"
78 #include "videowindow.h"
79 #include "vplayback.h"
80 #include "vwindowgui.h"
82 #include "wavecache.h"
84 #include "exportedl.h"
96 // Hack for libdv to remove glib dependancy
99 // g_log (const char *log_domain,
101 // const char *format,
107 // g_logv (const char *log_domain,
109 // const char *format,
116 // Hack for XFree86 4.1.0
118 int atexit(void (*function)(void))
132 plugin_gui_lock = new Mutex("MWindow::plugin_gui_lock");
133 brender_lock = new Mutex("MWindow::brender_lock");
136 channeldb_buz = new ChannelDB;
137 channeldb_v4l2jpeg = new ChannelDB;
139 dvb_input_lock = new Mutex("MWindow::dvb_input_lock");
144 brender_lock->lock("MWindow::~MWindow");
145 if(brender) delete brender;
147 brender_lock->unlock();
158 // Give up and go to a movie
163 delete audio_cache; // delete the cache after the assets
164 delete video_cache; // delete the cache after the assets
171 // delete renderlist;
176 plugin_guis->remove_all_objects();
178 delete plugin_gui_lock;
181 void MWindow::init_error()
186 void MWindow::create_defaults_path(char *string)
188 // set the .bcast path
191 sprintf(string, "%s", BCASTDIR);
192 fs.complete_path(string);
193 if(!fs.is_dir(string))
195 fs.create_dir(string);
199 strcat(string, "Cinelerra_rc");
202 void MWindow::init_defaults(BC_Hash* &defaults, char *config_path)
204 char path[BCTEXTLEN];
205 // Use user supplied path
208 strcpy(path, config_path);
212 create_defaults_path(path);
215 defaults = new BC_Hash(path);
219 void MWindow::init_plugin_path(Preferences *preferences,
220 ArrayList<PluginServer*>* &plugindb,
222 SplashGUI *splash_window,
226 PluginServer *newplugin;
230 for(int i = 0; i < fs->dir_list.total; i++)
232 char path[BCTEXTLEN];
233 strcpy(path, fs->dir_list.values[i]->path);
235 // File is a directory
242 // Try to query the plugin
243 fs->complete_path(path);
244 //printf("MWindow::init_plugin_path %s\n", path);
245 PluginServer *new_plugin = new PluginServer(path);
246 int result = new_plugin->open_plugin(1, preferences, 0, 0, -1);
250 plugindb->append(new_plugin);
251 new_plugin->close_plugin();
253 splash_window->operation->update(_(new_plugin->title));
256 if(result == PLUGINSERVER_IS_LAD)
259 // Open LAD subplugins
263 new_plugin = new PluginServer(path);
264 result = new_plugin->open_plugin(1,
272 plugindb->append(new_plugin);
273 new_plugin->close_plugin();
275 splash_window->operation->update(_(new_plugin->title));
284 // Plugin failed to open
289 if(splash_window) splash_window->progress->update((*counter)++);
294 void MWindow::init_plugins(Preferences *preferences,
295 ArrayList<PluginServer*>* &plugindb,
296 SplashGUI *splash_window)
298 plugindb = new ArrayList<PluginServer*>;
302 FileSystem cinelerra_fs;
303 ArrayList<FileSystem*> lad_fs;
307 cinelerra_fs.set_filter("[*.plugin][*.so]");
308 result = cinelerra_fs.update(preferences->global_plugin_dir);
313 _("MWindow::init_plugins: couldn't open %s directory\n"),
314 preferences->global_plugin_dir);
317 // Parse LAD environment variable
318 char *env = getenv("LADSPA_PATH");
321 char string[BCTEXTLEN];
325 char *ptr = strchr(ptr1, ':');
333 end = env + strlen(env);
338 int len = end - ptr1;
339 memcpy(string, ptr1, len);
343 FileSystem *fs = new FileSystem;
345 fs->set_filter("*.so");
346 result = fs->update(string);
351 _("MWindow::init_plugins: couldn't open %s directory\n"),
363 int total = cinelerra_fs.total_files();
365 for(int i = 0; i < lad_fs.total; i++)
366 total += lad_fs.values[i]->total_files();
367 if(splash_window) splash_window->progress->update_length(total);
372 init_plugin_path(preferences,
378 // Call automatically generated routine to get plugins
382 for(int i = 0; i < lad_fs.total; i++)
383 init_plugin_path(preferences,
389 lad_fs.remove_all_objects();
392 void MWindow::delete_plugins()
394 for(int i = 0; i < plugindb->total; i++)
396 delete plugindb->values[i];
401 void MWindow::create_plugindb(int do_audio,
406 ArrayList<PluginServer*> &plugindb)
409 for(int i = 0; i < this->plugindb->total; i++)
411 PluginServer *current = this->plugindb->values[i];
413 if(current->audio == do_audio &&
414 current->video == do_video &&
415 (current->realtime == is_realtime || is_realtime < 0) &&
416 current->transition == is_transition &&
417 current->theme == is_theme)
418 plugindb.append(current);
421 // Alphabetize list by title
427 for(int i = 0; i < plugindb.total - 1; i++)
429 PluginServer *value1 = plugindb.values[i];
430 PluginServer *value2 = plugindb.values[i + 1];
431 if(strcmp(_(value1->title), _(value2->title)) > 0)
434 plugindb.values[i] = value2;
435 plugindb.values[i + 1] = value1;
441 PluginServer* MWindow::scan_plugindb(char *title,
446 printf("MWindow::scan_plugindb data_type < 0\n");
450 for(int i = 0; i < plugindb->total; i++)
452 PluginServer *server = plugindb->values[i];
453 if(!strcasecmp(server->title, title) &&
454 ((data_type == TRACK_AUDIO && server->audio) ||
455 (data_type == TRACK_VIDEO && server->video)))
456 return plugindb->values[i];
461 void MWindow::init_preferences()
463 preferences = new Preferences;
464 preferences->load_defaults(defaults);
465 session = new MainSession(this);
466 session->load_defaults(defaults);
469 void MWindow::clean_indexes()
474 int oldest_item = -1;
476 char string[BCTEXTLEN];
477 char string2[BCTEXTLEN];
479 // Delete extra indexes
480 fs.set_filter("*.idx");
481 fs.complete_path(preferences->index_directory);
482 fs.update(preferences->index_directory);
483 //printf("MWindow::clean_indexes 1 %d\n", fs.dir_list.total);
485 // Eliminate directories
490 for(int i = 0; i < fs.dir_list.total && !result; i++)
492 fs.join_names(string, preferences->index_directory, fs.dir_list.values[i]->name);
493 if(fs.is_dir(string))
495 delete fs.dir_list.values[i];
496 fs.dir_list.remove_number(i);
501 total_excess = fs.dir_list.total - preferences->index_count;
503 //printf("MWindow::clean_indexes 2 %d\n", fs.dir_list.total);
504 while(total_excess > 0)
507 for(int i = 0; i < fs.dir_list.total; i++)
509 fs.join_names(string, preferences->index_directory, fs.dir_list.values[i]->name);
511 if(i == 0 || fs.get_date(string) <= oldest)
513 oldest = fs.get_date(string);
521 fs.join_names(string,
522 preferences->index_directory,
523 fs.dir_list.values[oldest_item]->name);
524 //printf("MWindow::clean_indexes 1 %s\n", string);
526 perror("delete_indexes");
527 delete fs.dir_list.values[oldest_item];
528 fs.dir_list.remove_number(oldest_item);
530 // Remove table of contents if it exists
531 strcpy(string2, string);
532 char *ptr = strrchr(string2, '.');
535 //printf("MWindow::clean_indexes 2 %s\n", string2);
536 sprintf(ptr, ".toc");
545 void MWindow::init_awindow()
547 awindow = new AWindow(this);
548 awindow->create_objects();
551 void MWindow::init_gwindow()
553 gwindow = new GWindow(this);
554 gwindow->create_objects();
557 void MWindow::init_tipwindow()
559 twindow = new TipWindow(this);
563 void MWindow::init_theme()
567 // Replace blond theme with SUV since it doesn't work
568 if(!strcasecmp(preferences->theme, "Blond"))
569 strcpy(preferences->theme, DEFAULT_THEME);
571 for(int i = 0; i < plugindb->total; i++)
573 if(plugindb->values[i]->theme &&
574 !strcasecmp(preferences->theme, plugindb->values[i]->title))
576 PluginServer plugin = *plugindb->values[i];
577 plugin.open_plugin(0, preferences, 0, 0, -1);
578 theme = plugin.new_theme();
579 theme->mwindow = this;
580 strcpy(theme->path, plugin.path);
581 plugin.close_plugin();
587 fprintf(stderr, _("MWindow::init_theme: theme %s not found.\n"), preferences->theme);
591 // Load images which may have been forgotten
592 theme->Theme::initialize();
595 // Create menus with user colors
596 theme->build_menus();
602 void MWindow::init_3d()
604 playback_3d = new Playback3D(this);
605 playback_3d->create_objects();
608 void MWindow::init_edl()
611 edl->create_objects();
612 edl->load_defaults(defaults);
613 edl->create_default_tracks();
614 edl->tracks->update_y_pixels(theme);
617 void MWindow::init_compositor()
619 cwindow = new CWindow(this);
620 cwindow->create_objects();
623 void MWindow::init_levelwindow()
625 lwindow = new LevelWindow(this);
626 lwindow->create_objects();
629 void MWindow::init_viewer()
631 vwindow = new VWindow(this);
632 vwindow->load_defaults();
633 vwindow->create_objects();
636 void MWindow::init_cache()
638 audio_cache = new CICache(preferences, plugindb);
639 video_cache = new CICache(preferences, plugindb);
640 frame_cache = new FrameCache;
641 wave_cache = new WaveCache;
644 void MWindow::init_channeldb()
646 channeldb_buz->load("channeldb_buz");
647 channeldb_v4l2jpeg->load("channeldb_v4l2jpeg");
650 void MWindow::init_menus()
652 char string[BCTEXTLEN];
655 cmodel_to_text(string, BC_RGB888);
656 colormodels.append(new ColormodelItem(string, BC_RGB888));
657 cmodel_to_text(string, BC_RGBA8888);
658 colormodels.append(new ColormodelItem(string, BC_RGBA8888));
659 // cmodel_to_text(string, BC_RGB161616);
660 // colormodels.append(new ColormodelItem(string, BC_RGB161616));
661 // cmodel_to_text(string, BC_RGBA16161616);
662 // colormodels.append(new ColormodelItem(string, BC_RGBA16161616));
663 cmodel_to_text(string, BC_RGB_FLOAT);
664 colormodels.append(new ColormodelItem(string, BC_RGB_FLOAT));
665 cmodel_to_text(string, BC_RGBA_FLOAT);
666 colormodels.append(new ColormodelItem(string, BC_RGBA_FLOAT));
667 cmodel_to_text(string, BC_YUV888);
668 colormodels.append(new ColormodelItem(string, BC_YUV888));
669 cmodel_to_text(string, BC_YUVA8888);
670 colormodels.append(new ColormodelItem(string, BC_YUVA8888));
671 // cmodel_to_text(string, BC_YUV161616);
672 // colormodels.append(new ColormodelItem(string, BC_YUV161616));
673 // cmodel_to_text(string, BC_YUVA16161616);
674 // colormodels.append(new ColormodelItem(string, BC_YUVA16161616));
676 #define ILACEPROJECTMODELISTADD(x) ilacemode_to_text(string, x); \
677 interlace_project_modes.append(new InterlacemodeItem(string, x));
679 #define ILACEASSETMODELISTADD(x) ilacemode_to_text(string, x); \
680 interlace_asset_modes.append(new InterlacemodeItem(string, x));
682 #define ILACEFIXMETHODLISTADD(x) ilacefixmethod_to_text(string, x); \
683 interlace_asset_fixmethods.append(new InterlacefixmethodItem(string, x));
686 ILACEASSETMODELISTADD(BC_ILACE_MODE_UNDETECTED); // Not included in the list for the project options.
688 ILACEASSETMODELISTADD(BC_ILACE_MODE_TOP_FIRST);
689 ILACEPROJECTMODELISTADD(BC_ILACE_MODE_TOP_FIRST);
691 ILACEASSETMODELISTADD(BC_ILACE_MODE_BOTTOM_FIRST);
692 ILACEPROJECTMODELISTADD(BC_ILACE_MODE_BOTTOM_FIRST);
694 ILACEASSETMODELISTADD(BC_ILACE_MODE_NOTINTERLACED);
695 ILACEPROJECTMODELISTADD(BC_ILACE_MODE_NOTINTERLACED);
697 // Interlacing Fixing Methods
698 ILACEFIXMETHODLISTADD(BC_ILACE_FIXMETHOD_NONE);
699 ILACEFIXMETHODLISTADD(BC_ILACE_FIXMETHOD_UPONE);
700 ILACEFIXMETHODLISTADD(BC_ILACE_FIXMETHOD_DOWNONE);
703 void MWindow::init_indexes()
705 mainindexes = new MainIndexes(this);
706 mainindexes->start_loop();
709 void MWindow::init_gui()
711 gui = new MWindowGUI(this);
712 gui->create_objects();
713 gui->load_defaults(defaults);
716 void MWindow::init_signals()
718 sighandler = new SigHandler;
719 sighandler->initialize();
723 void MWindow::init_render()
725 render = new Render(this);
726 // renderlist = new Render(this);
727 batch_render = new BatchRenderThread(this);
730 void MWindow::init_exportedl()
732 exportedl = new ExportEDL(this);
735 void MWindow::init_brender()
737 if(preferences->use_brender && !brender)
739 brender_lock->lock("MWindow::init_brender 1");
740 brender = new BRender(this);
741 brender->initialize();
742 session->brender_end = 0;
743 brender_lock->unlock();
746 if(!preferences->use_brender && brender)
748 brender_lock->lock("MWindow::init_brender 2");
751 session->brender_end = 0;
752 brender_lock->unlock();
754 if(brender) brender->restart(edl);
757 void MWindow::restart_brender()
759 //printf("MWindow::restart_brender 1\n");
760 if(brender) brender->restart(edl);
763 void MWindow::stop_brender()
765 if(brender) brender->stop();
768 int MWindow::brender_available(int position)
771 brender_lock->lock("MWindow::brender_available 1");
774 if(brender->map_valid)
776 brender->map_lock->lock("MWindow::brender_available 2");
777 if(position < brender->map_size &&
780 //printf("MWindow::brender_available 1 %d %d\n", position, brender->map[position]);
781 if(brender->map[position] == BRender::RENDERED)
784 brender->map_lock->unlock();
787 brender_lock->unlock();
791 void MWindow::set_brender_start()
793 edl->session->brender_start = edl->local_session->get_selectionstart();
795 gui->canvas->draw_overlays();
796 gui->canvas->flash();
801 int MWindow::load_filenames(ArrayList<char*> *filenames,
809 ArrayList<EDL*> new_edls;
810 ArrayList<Asset*> new_assets;
811 ArrayList<File*> new_files;
814 gui->start_hourglass();
816 // Need to stop playback since tracking depends on the EDL not getting
818 cwindow->playback_engine->que->send_command(STOP,
822 vwindow->playback_engine->que->send_command(STOP,
826 cwindow->playback_engine->interrupt_playback(0);
827 vwindow->playback_engine->interrupt_playback(0);
831 // Define new_edls and new_assets to load
833 for(int i = 0; i < filenames->total; i++)
836 File *new_file = new File;
837 Asset *new_asset = new Asset(filenames->values[i]);
838 EDL *new_edl = new EDL;
839 char string[BCTEXTLEN];
841 // Set reel name and number for the asset
842 // If the user wants to overwrite the last used reel number for the clip,
843 // we have to rebuild the index for the file
847 char source_filename[BCTEXTLEN];
848 char index_filename[BCTEXTLEN];
850 strcpy(new_asset->reel_name, reel_name);
851 new_asset->reel_number = reel_number;
853 IndexFile::get_index_filename(source_filename,
854 preferences->index_directory,
857 remove(index_filename);
858 new_asset->index_status = INDEX_NOTTESTED;
861 new_edl->create_objects();
862 new_edl->copy_session(edl);
864 sprintf(string, "Loading %s", new_asset->path);
865 gui->show_message(string);
867 result = new_file->open_file(preferences, new_asset, 1, 0, 0, 0);
872 // Convert media file to EDL
874 // Warn about odd image dimensions
875 if(new_asset->video_data &&
876 ((new_asset->width % 2) ||
877 (new_asset->height % 2)))
879 char string[BCTEXTLEN];
880 sprintf(string, "%s's resolution is %dx%d.\nImages with odd dimensions may not decode properly.",
884 MainError::show_error(string);
888 if(load_mode != LOAD_RESOURCESONLY)
891 asset_to_edl(new_edl, new_asset);
893 new_edls.append(new_edl);
895 Garbage::delete_object(new_asset);
901 new_assets.append(new_asset);
904 // Set filename to nothing for assets since save EDL would overwrite them.
905 if(load_mode == LOAD_REPLACE ||
906 load_mode == LOAD_REPLACE_CONCATENATE)
909 // Reset timeline position
910 new_edl->local_session->view_start = 0;
911 new_edl->local_session->track_start = 0;
919 sprintf(string, _("Failed to open %s"), new_asset->path);
920 gui->show_message(string, theme->message_error);
925 case FILE_UNRECOGNIZED_CODEC:
928 IndexFile indexfile(this);
929 result = indexfile.open_index(this, new_asset);
932 indexfile.close_index();
935 // Test existing EDLs
938 for(int j = 0; j < new_edls.total + 1; j++)
941 if(j == new_edls.total)
943 if(old_asset = edl->assets->get_asset(new_asset->path))
945 *new_asset = *old_asset;
951 if(old_asset = new_edls.values[j]->assets->get_asset(new_asset->path))
953 *new_asset = *old_asset;
963 char string[BCTEXTLEN];
965 fs.extract_name(string, new_asset->path);
967 strcat(string, _("'s format couldn't be determined."));
968 new_asset->audio_data = 1;
969 new_asset->format = FILE_PCM;
970 new_asset->channels = defaults->get("AUDIO_CHANNELS", 2);
971 new_asset->sample_rate = defaults->get("SAMPLE_RATE", 44100);
972 new_asset->bits = defaults->get("AUDIO_BITS", 16);
973 new_asset->byte_order = defaults->get("BYTE_ORDER", 1);
974 new_asset->signed_ = defaults->get("SIGNED_", 1);
975 new_asset->header = defaults->get("HEADER", 0);
977 FileFormat fwindow(this);
978 fwindow.create_objects(new_asset, string);
979 result = fwindow.run_window();
981 defaults->update("AUDIO_CHANNELS", new_asset->channels);
982 defaults->update("SAMPLE_RATE", new_asset->sample_rate);
983 defaults->update("AUDIO_BITS", new_asset->bits);
984 defaults->update("BYTE_ORDER", new_asset->byte_order);
985 defaults->update("SIGNED_", new_asset->signed_);
986 defaults->update("HEADER", new_asset->header);
993 // Recalculate length
996 result = new_file->open_file(preferences, new_asset, 1, 0, 0, 0);
998 if(load_mode != LOAD_RESOURCESONLY)
1000 asset_to_edl(new_edl, new_asset);
1001 new_edls.append(new_edl);
1002 Garbage::delete_object(new_asset);
1007 new_assets.append(new_asset);
1020 xml_file.read_from_file(filenames->values[i]);
1021 // Load EDL for pasting
1022 new_edl->load_xml(plugindb, &xml_file, LOAD_ALL);
1023 test_plugins(new_edl, filenames->values[i]);
1025 // We don't want a valid reel name/number for projects
1026 strcpy(new_asset->reel_name, "");
1029 if(load_mode == LOAD_REPLACE ||
1030 load_mode == LOAD_REPLACE_CONCATENATE)
1032 strcpy(session->filename, filenames->values[i]);
1033 strcpy(new_edl->local_session->clip_title, filenames->values[i]);
1035 set_filename(new_edl->local_session->clip_title);
1038 new_edls.append(new_edl);
1048 Garbage::delete_object(new_asset);
1054 // Store for testing index
1055 new_files.append(new_file);
1061 if(!result) gui->statusbar->default_message();
1071 // Don't back up here.
1074 // For pasting, clear the active region
1075 if(load_mode == LOAD_PASTE)
1077 double start = edl->local_session->get_selectionstart();
1078 double end = edl->local_session->get_selectionend();
1079 if(!EQUIV(start, end))
1082 edl->session->labels_follow_edits,
1083 edl->session->plugins_follow_edits);
1086 paste_edls(&new_edls,
1090 edl->session->labels_follow_edits,
1091 edl->session->plugins_follow_edits,
1100 // Add new assets to EDL and schedule assets for index building.
1101 // Used for loading resources only.
1102 if(new_assets.total)
1104 for(int i = 0; i < new_assets.total; i++)
1106 Asset *new_asset = new_assets.values[i];
1108 File *index_file = 0;
1110 for(int j = 0; j < new_files.total; j++)
1112 new_file = new_files.values[j];
1113 if(!strcmp(new_file->asset->path,
1121 mainindexes->add_next_asset(got_it ? new_file : 0,
1123 edl->assets->update(new_asset);
1128 // Start examining next batch of index files
1129 mainindexes->start_build();
1133 update_project(load_mode);
1138 new_edls.remove_all_objects();
1140 for(int i = 0; i < new_assets.total; i++)
1141 Garbage::delete_object(new_assets.values[i]);
1143 new_assets.remove_all();
1145 new_files.remove_all_objects();
1148 undo->update_undo(_("load"), LOAD_ALL, 0);
1152 gui->stop_hourglass();
1161 void MWindow::test_plugins(EDL *new_edl, char *path)
1163 char string[BCTEXTLEN];
1164 // Do a check weather plugins exist
1165 for(Track *track = new_edl->tracks->first; track; track = track->next)
1167 for(int k = 0; k < track->plugin_set.total; k++)
1169 PluginSet *plugin_set = track->plugin_set.values[k];
1170 for(Plugin *plugin = (Plugin*)plugin_set->first;
1172 plugin = (Plugin*)plugin->next)
1174 if(plugin->plugin_type == PLUGIN_STANDALONE)
1176 // ok we need to find it in plugindb
1177 int plugin_found = 0;
1178 for(int j = 0; j < plugindb->total; j++)
1180 PluginServer *server = plugindb->values[j];
1181 if(!strcasecmp(server->title, plugin->title) &&
1182 ((track->data_type == TRACK_AUDIO && server->audio) ||
1183 (track->data_type == TRACK_VIDEO && server->video)) &&
1184 (!server->transition))
1190 "The effect '%s' in file '%s' is not part of your installation of Cinelerra.\n"
1191 "The project won't be rendered as it was meant and Cinelerra might crash.\n",
1194 MainError::show_error(string);
1199 for(Edit *edit = (Edit*)track->edits->first;
1201 edit = (Edit*)edit->next)
1203 if (edit->transition)
1205 // ok we need to find transition in plugindb
1206 int transition_found = 0;
1207 for(int j = 0; j < plugindb->total; j++)
1209 PluginServer *server = plugindb->values[j];
1210 if(!strcasecmp(server->title, edit->transition->title) &&
1211 ((track->data_type == TRACK_AUDIO && server->audio) ||
1212 (track->data_type == TRACK_VIDEO && server->video)) &&
1213 (server->transition))
1214 transition_found = 1;
1216 if (!transition_found)
1219 "The transition '%s' in file '%s' is not part of your installation of Cinelerra.\n"
1220 "The project won't be rendered as it was meant and Cinelerra might crash.\n",
1221 edit->transition->title,
1223 MainError::show_error(string);
1231 void MWindow::init_shm()
1233 // Fix shared memory
1234 FILE *fd = fopen("/proc/sys/kernel/shmmax", "w");
1237 fprintf(fd, "0x7fffffff");
1242 fd = fopen("/proc/sys/kernel/shmmax", "r");
1245 MainError::show_error("MWindow::init_shm: couldn't open /proc/sys/kernel/shmmax for reading.\n");
1250 fscanf(fd, "%lld", &result);
1253 if(result < 0x7fffffff)
1255 eprintf("WARNING: /proc/sys/kernel/shmmax is 0x%llx, which is too low.\n"
1256 "Before running Cinelerra do the following as root:\n"
1257 "echo \"0x7fffffff\" > /proc/sys/kernel/shmmax\n",
1264 void MWindow::create_objects(int want_gui,
1268 char string[BCTEXTLEN];
1275 remove_thread = new RemoveThread;
1276 remove_thread->create_objects();
1279 // For some reason, init_signals must come after show_splash or the signals won't
1287 init_defaults(defaults, config_path);
1291 init_plugins(preferences, plugindb, splash_window);
1292 if(splash_window) splash_window->operation->update(_("Initializing GUI"));
1295 // Default project created here
1321 mainprogress = new MainProgress(this, gui);
1322 undo = new MainUndo(this);
1324 plugin_guis = new ArrayList<PluginServer*>;
1327 if(session->show_vwindow) vwindow->gui->show_window();
1328 if(session->show_cwindow) cwindow->gui->show_window();
1329 if(session->show_awindow) awindow->gui->show_window();
1330 if(session->show_lwindow) lwindow->gui->show_window();
1331 if(session->show_gwindow) gwindow->gui->show_window();
1335 gui->mainmenu->load_defaults(defaults);
1337 gui->mainmenu->update_toggles(0);
1339 gui->patchbay->update();
1341 gui->canvas->draw();
1343 gui->cursor->draw(1);
1346 gui->raise_window();
1348 if(preferences->use_tipwindow)
1359 void MWindow::show_splash()
1361 #include "data/heroine_logo12_png.h"
1362 VFrame *frame = new VFrame(heroine_logo12_png);
1363 BC_DisplayInfo display_info;
1364 splash_window = new SplashGUI(frame,
1365 display_info.get_root_w() / 2 - frame->get_w() / 2,
1366 display_info.get_root_h() / 2 - frame->get_h() / 2);
1367 splash_window->create_objects();
1370 void MWindow::hide_splash()
1373 delete splash_window;
1378 void MWindow::start()
1387 playback_3d->start();
1395 void MWindow::show_vwindow()
1397 session->show_vwindow = 1;
1398 vwindow->gui->lock_window("MWindow::show_vwindow");
1399 vwindow->gui->show_window();
1400 vwindow->gui->raise_window();
1401 vwindow->gui->flush();
1402 vwindow->gui->unlock_window();
1403 gui->mainmenu->show_vwindow->set_checked(1);
1406 void MWindow::show_awindow()
1408 session->show_awindow = 1;
1409 awindow->gui->lock_window("MWindow::show_awindow");
1410 awindow->gui->show_window();
1411 awindow->gui->raise_window();
1412 awindow->gui->flush();
1413 awindow->gui->unlock_window();
1414 gui->mainmenu->show_awindow->set_checked(1);
1417 void MWindow::show_cwindow()
1419 session->show_cwindow = 1;
1420 cwindow->show_window();
1421 gui->mainmenu->show_cwindow->set_checked(1);
1424 void MWindow::show_gwindow()
1426 session->show_gwindow = 1;
1428 gwindow->gui->lock_window("MWindow::show_gwindow");
1429 gwindow->gui->show_window();
1430 gwindow->gui->raise_window();
1431 gwindow->gui->flush();
1432 gwindow->gui->unlock_window();
1434 gui->mainmenu->show_gwindow->set_checked(1);
1437 void MWindow::show_lwindow()
1439 session->show_lwindow = 1;
1440 lwindow->gui->lock_window("MWindow::show_lwindow");
1441 lwindow->gui->show_window();
1442 lwindow->gui->raise_window();
1443 lwindow->gui->flush();
1444 lwindow->gui->unlock_window();
1445 gui->mainmenu->show_lwindow->set_checked(1);
1448 void MWindow::tile_windows()
1450 session->default_window_positions();
1451 gui->default_positions();
1454 void MWindow::toggle_loop_playback()
1456 edl->local_session->loop_playback = !edl->local_session->loop_playback;
1457 set_loop_boundaries();
1460 gui->canvas->draw_overlays();
1461 gui->canvas->flash();
1462 sync_parameters(CHANGE_PARAMS);
1465 void MWindow::set_titles(int value)
1467 edl->session->show_titles = value;
1468 trackmovement(edl->local_session->track_start);
1471 void MWindow::set_auto_keyframes(int value)
1473 gui->lock_window("MWindow::set_auto_keyframes");
1474 edl->session->auto_keyframes = value;
1475 gui->mbuttons->edit_panel->keyframe->update(value);
1477 gui->unlock_window();
1478 cwindow->gui->lock_window("MWindow::set_auto_keyframes");
1479 cwindow->gui->edit_panel->keyframe->update(value);
1480 cwindow->gui->flush();
1481 cwindow->gui->unlock_window();
1484 int MWindow::set_editing_mode(int new_editing_mode)
1486 gui->lock_window("MWindow::set_editing_mode");
1487 edl->session->editing_mode = new_editing_mode;
1488 gui->mbuttons->edit_panel->editing_mode = edl->session->editing_mode;
1489 gui->mbuttons->edit_panel->update();
1490 gui->canvas->update_cursor();
1491 gui->unlock_window();
1492 cwindow->gui->lock_window("MWindow::set_editing_mode");
1493 cwindow->gui->edit_panel->update();
1494 cwindow->gui->edit_panel->editing_mode = edl->session->editing_mode;
1495 cwindow->gui->unlock_window();
1500 void MWindow::sync_parameters(int change_type)
1503 // Sync engines which are playing back
1504 if(cwindow->playback_engine->is_playing_back)
1506 if(change_type == CHANGE_PARAMS)
1508 // TODO: block keyframes until synchronization is done
1509 cwindow->playback_engine->sync_parameters(edl);
1514 int command = cwindow->playback_engine->command->command;
1515 cwindow->playback_engine->que->send_command(STOP,
1519 // Waiting for tracking to finish would make the restart position more
1520 // accurate but it can't lock the window to stop tracking for some reason.
1521 // Not waiting for tracking gives a faster response but restart position is
1522 // only as accurate as the last tracking update.
1523 cwindow->playback_engine->interrupt_playback(0);
1524 cwindow->playback_engine->que->send_command(command,
1533 cwindow->playback_engine->que->send_command(CURRENT_FRAME,
1540 void MWindow::age_caches()
1542 int64_t prev_memory_usage;
1543 int64_t memory_usage;
1547 memory_usage = audio_cache->get_memory_usage(1) +
1548 video_cache->get_memory_usage(1) +
1549 frame_cache->get_memory_usage() +
1550 wave_cache->get_memory_usage();
1552 if(memory_usage > preferences->cache_size)
1555 int oldest1 = audio_cache->get_oldest();
1556 int oldest2 = video_cache->get_oldest();
1557 if(oldest2 < oldest1) target = 2;
1558 int oldest3 = frame_cache->get_oldest();
1559 if(oldest3 < oldest1 && oldest3 < oldest2) target = 3;
1560 int oldest4 = wave_cache->get_oldest();
1561 if(oldest4 < oldest3 && oldest4 < oldest2 && oldest4 < oldest1) target = 4;
1564 case 1: audio_cache->delete_oldest(); break;
1565 case 2: video_cache->delete_oldest(); break;
1566 case 3: frame_cache->delete_oldest(); break;
1567 case 4: wave_cache->delete_oldest(); break;
1570 prev_memory_usage = memory_usage;
1571 memory_usage = audio_cache->get_memory_usage(1) +
1572 video_cache->get_memory_usage(1) +
1573 frame_cache->get_memory_usage() +
1574 wave_cache->get_memory_usage();
1576 prev_memory_usage != memory_usage &&
1577 memory_usage > preferences->cache_size);
1580 void MWindow::show_plugin(Plugin *plugin)
1583 //printf("MWindow::show_plugin 1\n");
1584 plugin_gui_lock->lock("MWindow::show_plugin");
1585 for(int i = 0; i < plugin_guis->total; i++)
1587 // Pointer comparison
1588 if(plugin_guis->values[i]->plugin == plugin)
1590 plugin_guis->values[i]->raise_window();
1596 //printf("MWindow::show_plugin 1\n");
1601 printf("MWindow::show_plugin track not defined.\n");
1603 PluginServer *server = scan_plugindb(plugin->title,
1604 plugin->track->data_type);
1606 //printf("MWindow::show_plugin %p %d\n", server, server->uses_gui);
1607 if(server && server->uses_gui)
1609 PluginServer *gui = plugin_guis->append(new PluginServer(*server));
1610 // Needs mwindow to do GUI
1611 gui->set_mwindow(this);
1612 gui->open_plugin(0, preferences, edl, plugin, -1);
1617 plugin_gui_lock->unlock();
1618 //printf("MWindow::show_plugin 2\n");
1621 void MWindow::hide_plugin(Plugin *plugin, int lock)
1624 gui->lock_window("MWindow::hide_plugin");
1625 gui->update(0, 1, 0, 0, 0, 0, 0);
1626 gui->unlock_window();
1628 if(lock) plugin_gui_lock->lock("MWindow::hide_plugin");
1629 for(int i = 0; i < plugin_guis->total; i++)
1631 if(plugin_guis->values[i]->plugin == plugin)
1633 PluginServer *ptr = plugin_guis->values[i];
1634 plugin_guis->remove(ptr);
1635 if(lock) plugin_gui_lock->unlock();
1636 // Last command executed in client side close
1641 if(lock) plugin_gui_lock->unlock();
1645 void MWindow::hide_plugins()
1647 plugin_gui_lock->lock("MWindow::hide_plugins");
1648 plugin_guis->remove_all_objects();
1649 plugin_gui_lock->unlock();
1652 void MWindow::update_plugin_guis()
1654 plugin_gui_lock->lock("MWindow::update_plugin_guis");
1656 for(int i = 0; i < plugin_guis->total; i++)
1658 plugin_guis->values[i]->update_gui();
1660 plugin_gui_lock->unlock();
1663 int MWindow::plugin_gui_open(Plugin *plugin)
1666 plugin_gui_lock->lock("MWindow::plugin_gui_open");
1667 for(int i = 0; i < plugin_guis->total; i++)
1669 if(plugin_guis->values[i]->plugin->identical_location(plugin))
1675 plugin_gui_lock->unlock();
1679 void MWindow::render_plugin_gui(void *data, Plugin *plugin)
1681 plugin_gui_lock->lock("MWindow::render_plugin_gui");
1682 for(int i = 0; i < plugin_guis->total; i++)
1684 if(plugin_guis->values[i]->plugin->identical_location(plugin))
1686 plugin_guis->values[i]->render_gui(data);
1690 plugin_gui_lock->unlock();
1693 void MWindow::render_plugin_gui(void *data, int size, Plugin *plugin)
1695 plugin_gui_lock->lock("MWindow::render_plugin_gui");
1696 for(int i = 0; i < plugin_guis->total; i++)
1698 if(plugin_guis->values[i]->plugin->identical_location(plugin))
1700 plugin_guis->values[i]->render_gui(data, size);
1704 plugin_gui_lock->unlock();
1708 void MWindow::update_plugin_states()
1710 plugin_gui_lock->lock("MWindow::update_plugin_states");
1711 for(int i = 0; i < plugin_guis->total; i++)
1715 Plugin *src_plugin = plugin_guis->values[i]->plugin;
1716 PluginServer *src_plugingui = plugin_guis->values[i];
1718 // Search for plugin in EDL. Only the master EDL shows plugin GUIs.
1719 for(Track *track = edl->tracks->first;
1721 track = track->next)
1724 j < track->plugin_set.total && !result;
1727 PluginSet *plugin_set = track->plugin_set.values[j];
1728 for(Plugin *plugin = (Plugin*)plugin_set->first;
1730 plugin = (Plugin*)plugin->next)
1732 if(plugin == src_plugin &&
1733 !strcmp(plugin->title, src_plugingui->title)) result = 1;
1739 // Doesn't exist anymore
1742 hide_plugin(src_plugin, 0);
1746 plugin_gui_lock->unlock();
1750 void MWindow::update_plugin_titles()
1752 for(int i = 0; i < plugin_guis->total; i++)
1754 plugin_guis->values[i]->update_title();
1758 int MWindow::asset_to_edl(EDL *new_edl,
1760 RecordLabels *labels)
1762 //printf("MWindow::asset_to_edl 1\n");
1763 // new_edl->load_defaults(defaults);
1765 // Keep frame rate, sample rate, and output size unchanged.
1766 // These parameters would revert the project if VWindow displayed an asset
1767 // of different size than the project.
1768 if(new_asset->video_data)
1770 new_edl->session->video_tracks = new_asset->layers;
1771 // new_edl->session->frame_rate = new_asset->frame_rate;
1772 // new_edl->session->output_w = new_asset->width;
1773 // new_edl->session->output_h = new_asset->height;
1776 new_edl->session->video_tracks = 0;
1783 if(new_asset->audio_data)
1785 new_edl->session->audio_tracks = new_asset->channels;
1786 // new_edl->session->sample_rate = new_asset->sample_rate;
1789 new_edl->session->audio_tracks = 0;
1790 //printf("MWindow::asset_to_edl 2 %d %d\n", new_edl->session->video_tracks, new_edl->session->audio_tracks);
1792 new_edl->create_default_tracks();
1793 //printf("MWindow::asset_to_edl 2 %d %d\n", new_edl->session->video_tracks, new_edl->session->audio_tracks);
1795 // Disable drawing if the file format isn't fast enough.
1796 // MPEG is now faster than most other codecs.
1797 // if(new_asset->format == FILE_MPEG)
1799 // for(Track *current = new_edl->tracks->first;
1803 // if(current->data_type == TRACK_VIDEO) current->draw = 0;
1809 //printf("MWindow::asset_to_edl 3\n");
1810 new_edl->insert_asset(new_asset, 0, 0, labels);
1811 //printf("MWindow::asset_to_edl 3\n");
1813 // Align cursor on frames:: clip the new_edl to the minimum of the last joint frame.
1814 if(edl->session->cursor_on_frames)
1816 double edl_length = new_edl->tracks->total_length_framealigned(edl->session->frame_rate);
1817 new_edl->tracks->clear(edl_length, new_edl->tracks->total_length() + 100, 1);
1818 new_edl->tracks->loaded_lengths_to_tracklengths(1);
1824 char string[BCTEXTLEN];
1826 fs.extract_name(string, new_asset->path);
1827 //printf("MWindow::asset_to_edl 3\n");
1829 strcpy(new_edl->local_session->clip_title, string);
1830 //printf("MWindow::asset_to_edl 4 %s\n", string);
1836 // Reset everything after a load.
1837 void MWindow::update_project(int load_mode)
1840 edl->tracks->update_y_pixels(theme);
1843 gui->update(1, 1, 1, 1, 1, 1, 1);
1845 cwindow->update(0, 0, 1, 1, 1);
1848 if(load_mode == LOAD_REPLACE ||
1849 load_mode == LOAD_REPLACE_CONCATENATE)
1851 vwindow->change_source();
1858 cwindow->gui->lock_window("Mwindow::update_project");
1859 cwindow->gui->slider->set_position();
1860 cwindow->gui->timebar->update(1, 1);
1861 cwindow->gui->unlock_window();
1862 cwindow->playback_engine->que->send_command(CURRENT_FRAME,
1867 awindow->gui->async_update_assets();
1872 void MWindow::rebuild_indices()
1874 char source_filename[BCTEXTLEN], index_filename[BCTEXTLEN];
1876 for(int i = 0; i < session->drag_assets->total; i++)
1878 //printf("MWindow::rebuild_indices 1 %s\n", session->drag_assets->values[i]->path);
1880 IndexFile::get_index_filename(source_filename,
1881 preferences->index_directory,
1883 session->drag_assets->values[i]->path);
1884 remove(index_filename);
1885 // Schedule index build
1886 session->drag_assets->values[i]->index_status = INDEX_NOTTESTED;
1887 mainindexes->add_next_asset(0, session->drag_assets->values[i]);
1889 mainindexes->start_build();
1893 void MWindow::save_backup()
1896 edl->set_project_path(session->filename);
1897 edl->save_xml(plugindb,
1902 file.terminate_string();
1903 char path[BCTEXTLEN];
1905 strcpy(path, BACKUP_PATH);
1906 fs.complete_path(path);
1908 if(file.write_to_file(path))
1911 sprintf(string2, _("Couldn't open %s for writing."), BACKUP_PATH);
1912 gui->show_message(string2);
1917 int MWindow::create_aspect_ratio(float &w, float &h, int width, int height)
1920 if(!width || !height) return 1;
1921 float fraction = (float)width / height;
1923 for(denominator = 1;
1924 denominator < 100 &&
1925 fabs(fraction * denominator - (int)(fraction * denominator)) > .001;
1929 w = denominator * width / height;
1934 void MWindow::reset_caches()
1936 frame_cache->remove_all();
1937 wave_cache->remove_all();
1938 audio_cache->remove_all();
1939 video_cache->remove_all();
1940 if(cwindow->playback_engine && cwindow->playback_engine->audio_cache)
1941 cwindow->playback_engine->audio_cache->remove_all();
1942 if(cwindow->playback_engine && cwindow->playback_engine->video_cache)
1943 cwindow->playback_engine->video_cache->remove_all();
1944 if(vwindow->playback_engine && vwindow->playback_engine->audio_cache)
1945 vwindow->playback_engine->audio_cache->remove_all();
1946 if(vwindow->playback_engine && vwindow->playback_engine->video_cache)
1947 vwindow->playback_engine->video_cache->remove_all();
1950 void MWindow::remove_asset_from_caches(Asset *asset)
1952 frame_cache->remove_asset(asset);
1953 wave_cache->remove_asset(asset);
1954 audio_cache->delete_entry(asset);
1955 video_cache->delete_entry(asset);
1956 if(cwindow->playback_engine && cwindow->playback_engine->audio_cache)
1957 cwindow->playback_engine->audio_cache->delete_entry(asset);
1958 if(cwindow->playback_engine && cwindow->playback_engine->video_cache)
1959 cwindow->playback_engine->video_cache->delete_entry(asset);
1960 if(vwindow->playback_engine && vwindow->playback_engine->audio_cache)
1961 vwindow->playback_engine->audio_cache->delete_entry(asset);
1962 if(vwindow->playback_engine && vwindow->playback_engine->video_cache)
1963 vwindow->playback_engine->video_cache->delete_entry(asset);
1968 void MWindow::remove_assets_from_project(int push_undo)
1970 for(int i = 0; i < session->drag_assets->total; i++)
1972 Asset *asset = session->drag_assets->values[i];
1973 remove_asset_from_caches(asset);
1976 // Remove from VWindow.
1977 for(int i = 0; i < session->drag_clips->total; i++)
1979 if(session->drag_clips->values[i] == vwindow->get_edl())
1981 vwindow->gui->lock_window("MWindow::remove_assets_from_project 1");
1982 vwindow->remove_source();
1983 vwindow->gui->unlock_window();
1987 for(int i = 0; i < session->drag_assets->total; i++)
1989 if(session->drag_assets->values[i] == vwindow->get_asset())
1991 vwindow->gui->lock_window("MWindow::remove_assets_from_project 2");
1992 vwindow->remove_source();
1993 vwindow->gui->unlock_window();
1997 edl->remove_from_project(session->drag_assets);
1998 edl->remove_from_project(session->drag_clips);
2000 if(push_undo) undo->update_undo(_("remove assets"), LOAD_ALL);
2003 gui->lock_window("MWindow::remove_assets_from_project 3");
2011 gui->unlock_window();
2013 awindow->gui->async_update_assets();
2015 // Removes from playback here
2016 sync_parameters(CHANGE_ALL);
2019 void MWindow::remove_assets_from_disk()
2022 for(int i = 0; i < session->drag_assets->total; i++)
2024 remove(session->drag_assets->values[i]->path);
2027 remove_assets_from_project(1);
2030 void MWindow::dump_plugins()
2032 for(int i = 0; i < plugindb->total; i++)
2034 printf("audio=%d video=%d realtime=%d transition=%d theme=%d %s\n",
2035 plugindb->values[i]->audio,
2036 plugindb->values[i]->video,
2037 plugindb->values[i]->realtime,
2038 plugindb->values[i]->transition,
2039 plugindb->values[i]->theme,
2040 plugindb->values[i]->title);
2068 int MWindow::save_defaults()
2070 gui->save_defaults(defaults);
2071 edl->save_defaults(defaults);
2072 session->save_defaults(defaults);
2073 preferences->save_defaults(defaults);
2079 int MWindow::run_script(FileXML *script)
2081 int result = 0, result2 = 0;
2082 while(!result && !result2)
2084 result = script->read_tag();
2087 if(script->tag.title_is("new_project"))
2089 // Run new in immediate mode.
2090 // gui->mainmenu->new_project->run_script(script);
2093 if(script->tag.title_is("record"))
2095 // Run record as a thread. It is a terminal command.
2097 // Will read the complete scipt file without letting record read it if not
2103 printf("MWindow::run_script: Unrecognized command: %s\n",script->tag.get_title() );
2110 // ================================= synchronization
2113 int MWindow::interrupt_indexes()
2115 mainindexes->interrupt_build();
2121 void MWindow::next_time_format()
2123 switch(edl->session->time_format)
2125 case TIME_HMS: edl->session->time_format = TIME_HMSF; break;
2126 case TIME_HMSF: edl->session->time_format = TIME_SAMPLES; break;
2127 case TIME_SAMPLES: edl->session->time_format = TIME_SAMPLES_HEX; break;
2128 case TIME_SAMPLES_HEX: edl->session->time_format = TIME_FRAMES; break;
2129 case TIME_FRAMES: edl->session->time_format = TIME_FEET_FRAMES; break;
2130 case TIME_FEET_FRAMES: edl->session->time_format = TIME_SECONDS; break;
2131 case TIME_SECONDS: edl->session->time_format = TIME_HMS; break;
2134 time_format_common();
2137 void MWindow::prev_time_format()
2139 switch(edl->session->time_format)
2141 case TIME_HMS: edl->session->time_format = TIME_SECONDS; break;
2142 case TIME_SECONDS: edl->session->time_format = TIME_FEET_FRAMES; break;
2143 case TIME_FEET_FRAMES: edl->session->time_format = TIME_FRAMES; break;
2144 case TIME_FRAMES: edl->session->time_format = TIME_SAMPLES_HEX; break;
2145 case TIME_SAMPLES_HEX: edl->session->time_format = TIME_SAMPLES; break;
2146 case TIME_SAMPLES: edl->session->time_format = TIME_HMSF; break;
2147 case TIME_HMSF: edl->session->time_format = TIME_HMS; break;
2150 time_format_common();
2153 void MWindow::time_format_common()
2155 gui->lock_window("MWindow::next_time_format");
2156 gui->redraw_time_dependancies();
2157 char string[BCTEXTLEN], string2[BCTEXTLEN];
2158 sprintf(string, _("Using %s."), Units::print_time_format(edl->session->time_format, string2));
2159 gui->show_message(string);
2161 gui->unlock_window();
2165 int MWindow::set_filename(char *filename)
2167 strcpy(session->filename, filename);
2170 if(filename[0] == 0)
2172 gui->set_title(PROGRAM_NAME);
2177 char string[BCTEXTLEN], string2[BCTEXTLEN];
2178 dir.extract_name(string, filename);
2179 sprintf(string2, PROGRAM_NAME ": %s", string);
2180 gui->set_title(string2);
2193 int MWindow::set_loop_boundaries()
2195 double start = edl->local_session->get_selectionstart();
2196 double end = edl->local_session->get_selectionend();
2204 if(edl->tracks->total_length())
2207 end = edl->tracks->total_length();
2214 if(edl->local_session->loop_playback && start != end)
2216 edl->local_session->loop_start = start;
2217 edl->local_session->loop_end = end;
2228 int MWindow::reset_meters()
2230 cwindow->gui->lock_window("MWindow::reset_meters 1");
2231 cwindow->gui->meters->reset_meters();
2232 cwindow->gui->unlock_window();
2234 vwindow->gui->lock_window("MWindow::reset_meters 2");
2235 vwindow->gui->meters->reset_meters();
2236 vwindow->gui->unlock_window();
2238 lwindow->gui->lock_window("MWindow::reset_meters 3");
2239 lwindow->gui->panel->reset_meters();
2240 lwindow->gui->unlock_window();
2242 gui->lock_window("MWindow::reset_meters 4");
2243 gui->patchbay->reset_meters();
2244 gui->unlock_window();