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"
60 #include "samplescroll.h"
61 #include "sighandler.h"
62 #include "splashgui.h"
63 #include "statusbar.h"
65 #include "threadloader.h"
67 #include "tipwindow.h"
68 #include "trackcanvas.h"
71 #include "trackscroll.h"
73 #include "transition.h"
74 #include "transportque.h"
76 #include "videodevice.inc"
77 #include "videowindow.h"
78 #include "vplayback.h"
79 #include "vwindowgui.h"
81 #include "wavecache.h"
83 #include "exportedl.h"
95 // Hack for libdv to remove glib dependancy
98 // g_log (const char *log_domain,
100 // const char *format,
106 // g_logv (const char *log_domain,
108 // const char *format,
115 // Hack for XFree86 4.1.0
117 int atexit(void (*function)(void))
131 plugin_gui_lock = new Mutex("MWindow::plugin_gui_lock");
132 brender_lock = new Mutex("MWindow::brender_lock");
135 channeldb_buz = new ChannelDB;
136 channeldb_v4l2jpeg = new ChannelDB;
138 dvb_input_lock = new Mutex("MWindow::dvb_input_lock");
143 brender_lock->lock("MWindow::~MWindow");
144 if(brender) delete brender;
146 brender_lock->unlock();
157 // Give up and go to a movie
162 delete audio_cache; // delete the cache after the assets
163 delete video_cache; // delete the cache after the assets
170 // delete renderlist;
175 plugin_guis->remove_all_objects();
177 delete plugin_gui_lock;
180 void MWindow::init_error()
185 void MWindow::create_defaults_path(char *string)
187 // set the .bcast path
190 sprintf(string, "%s", BCASTDIR);
191 fs.complete_path(string);
192 if(!fs.is_dir(string))
194 fs.create_dir(string);
198 strcat(string, "Cinelerra_rc");
201 void MWindow::init_defaults(BC_Hash* &defaults, char *config_path)
203 char path[BCTEXTLEN];
204 // Use user supplied path
207 strcpy(path, config_path);
211 create_defaults_path(path);
214 defaults = new BC_Hash(path);
218 void MWindow::init_plugin_path(Preferences *preferences,
219 ArrayList<PluginServer*>* &plugindb,
221 SplashGUI *splash_window,
225 PluginServer *newplugin;
229 for(int i = 0; i < fs->dir_list.total; i++)
231 char path[BCTEXTLEN];
232 strcpy(path, fs->dir_list.values[i]->path);
234 // File is a directory
241 // Try to query the plugin
242 fs->complete_path(path);
243 //printf("MWindow::init_plugin_path %s\n", path);
244 PluginServer *new_plugin = new PluginServer(path);
245 int result = new_plugin->open_plugin(1, preferences, 0, 0, -1);
249 plugindb->append(new_plugin);
250 new_plugin->close_plugin();
252 splash_window->operation->update(_(new_plugin->title));
255 if(result == PLUGINSERVER_IS_LAD)
258 // Open LAD subplugins
262 new_plugin = new PluginServer(path);
263 result = new_plugin->open_plugin(1,
271 plugindb->append(new_plugin);
272 new_plugin->close_plugin();
274 splash_window->operation->update(_(new_plugin->title));
283 // Plugin failed to open
288 if(splash_window) splash_window->progress->update((*counter)++);
293 void MWindow::init_plugins(Preferences *preferences,
294 ArrayList<PluginServer*>* &plugindb,
295 SplashGUI *splash_window)
297 plugindb = new ArrayList<PluginServer*>;
301 FileSystem cinelerra_fs;
302 ArrayList<FileSystem*> lad_fs;
306 cinelerra_fs.set_filter("[*.plugin][*.so]");
307 result = cinelerra_fs.update(preferences->global_plugin_dir);
312 _("MWindow::init_plugins: couldn't open %s directory\n"),
313 preferences->global_plugin_dir);
316 // Parse LAD environment variable
317 char *env = getenv("LADSPA_PATH");
320 char string[BCTEXTLEN];
324 char *ptr = strchr(ptr1, ':');
332 end = env + strlen(env);
337 int len = end - ptr1;
338 memcpy(string, ptr1, len);
342 FileSystem *fs = new FileSystem;
344 fs->set_filter("*.so");
345 result = fs->update(string);
350 _("MWindow::init_plugins: couldn't open %s directory\n"),
362 int total = cinelerra_fs.total_files();
364 for(int i = 0; i < lad_fs.total; i++)
365 total += lad_fs.values[i]->total_files();
366 if(splash_window) splash_window->progress->update_length(total);
371 init_plugin_path(preferences,
377 // Call automatically generated routine to get plugins
381 for(int i = 0; i < lad_fs.total; i++)
382 init_plugin_path(preferences,
388 lad_fs.remove_all_objects();
391 void MWindow::delete_plugins()
393 for(int i = 0; i < plugindb->total; i++)
395 delete plugindb->values[i];
400 void MWindow::create_plugindb(int do_audio,
405 ArrayList<PluginServer*> &plugindb)
408 for(int i = 0; i < this->plugindb->total; i++)
410 PluginServer *current = this->plugindb->values[i];
412 if(current->audio == do_audio &&
413 current->video == do_video &&
414 (current->realtime == is_realtime || is_realtime < 0) &&
415 current->transition == is_transition &&
416 current->theme == is_theme)
417 plugindb.append(current);
420 // Alphabetize list by title
426 for(int i = 0; i < plugindb.total - 1; i++)
428 PluginServer *value1 = plugindb.values[i];
429 PluginServer *value2 = plugindb.values[i + 1];
430 if(strcmp(_(value1->title), _(value2->title)) > 0)
433 plugindb.values[i] = value2;
434 plugindb.values[i + 1] = value1;
440 PluginServer* MWindow::scan_plugindb(char *title,
445 printf("MWindow::scan_plugindb data_type < 0\n");
449 for(int i = 0; i < plugindb->total; i++)
451 PluginServer *server = plugindb->values[i];
452 if(!strcasecmp(server->title, title) &&
453 ((data_type == TRACK_AUDIO && server->audio) ||
454 (data_type == TRACK_VIDEO && server->video)))
455 return plugindb->values[i];
460 void MWindow::init_preferences()
462 preferences = new Preferences;
463 preferences->load_defaults(defaults);
464 session = new MainSession(this);
465 session->load_defaults(defaults);
468 void MWindow::clean_indexes()
473 int oldest_item = -1;
475 char string[BCTEXTLEN];
476 char string2[BCTEXTLEN];
478 // Delete extra indexes
479 fs.set_filter("*.idx");
480 fs.complete_path(preferences->index_directory);
481 fs.update(preferences->index_directory);
482 //printf("MWindow::clean_indexes 1 %d\n", fs.dir_list.total);
484 // Eliminate directories
489 for(int i = 0; i < fs.dir_list.total && !result; i++)
491 fs.join_names(string, preferences->index_directory, fs.dir_list.values[i]->name);
492 if(fs.is_dir(string))
494 delete fs.dir_list.values[i];
495 fs.dir_list.remove_number(i);
500 total_excess = fs.dir_list.total - preferences->index_count;
502 //printf("MWindow::clean_indexes 2 %d\n", fs.dir_list.total);
503 while(total_excess > 0)
506 for(int i = 0; i < fs.dir_list.total; i++)
508 fs.join_names(string, preferences->index_directory, fs.dir_list.values[i]->name);
510 if(i == 0 || fs.get_date(string) <= oldest)
512 oldest = fs.get_date(string);
520 fs.join_names(string,
521 preferences->index_directory,
522 fs.dir_list.values[oldest_item]->name);
523 //printf("MWindow::clean_indexes 1 %s\n", string);
525 perror("delete_indexes");
526 delete fs.dir_list.values[oldest_item];
527 fs.dir_list.remove_number(oldest_item);
529 // Remove table of contents if it exists
530 strcpy(string2, string);
531 char *ptr = strrchr(string2, '.');
534 //printf("MWindow::clean_indexes 2 %s\n", string2);
535 sprintf(ptr, ".toc");
544 void MWindow::init_awindow()
546 awindow = new AWindow(this);
547 awindow->create_objects();
550 void MWindow::init_gwindow()
552 gwindow = new GWindow(this);
553 gwindow->create_objects();
556 void MWindow::init_tipwindow()
558 twindow = new TipWindow(this);
562 void MWindow::init_theme()
566 // Replace blond theme with SUV since it doesn't work
567 if(!strcasecmp(preferences->theme, "Blond"))
568 strcpy(preferences->theme, DEFAULT_THEME);
570 for(int i = 0; i < plugindb->total; i++)
572 if(plugindb->values[i]->theme &&
573 !strcasecmp(preferences->theme, plugindb->values[i]->title))
575 PluginServer plugin = *plugindb->values[i];
576 plugin.open_plugin(0, preferences, 0, 0, -1);
577 theme = plugin.new_theme();
578 theme->mwindow = this;
579 strcpy(theme->path, plugin.path);
580 plugin.close_plugin();
586 fprintf(stderr, _("MWindow::init_theme: theme %s not found.\n"), preferences->theme);
590 // Load images which may have been forgotten
591 theme->Theme::initialize();
594 // Create menus with user colors
595 theme->build_menus();
601 void MWindow::init_3d()
603 playback_3d = new Playback3D(this);
604 playback_3d->create_objects();
607 void MWindow::init_edl()
610 edl->create_objects();
611 edl->load_defaults(defaults);
612 edl->create_default_tracks();
613 edl->tracks->update_y_pixels(theme);
616 void MWindow::init_compositor()
618 cwindow = new CWindow(this);
619 cwindow->create_objects();
622 void MWindow::init_levelwindow()
624 lwindow = new LevelWindow(this);
625 lwindow->create_objects();
628 void MWindow::init_viewer()
630 vwindow = new VWindow(this);
631 vwindow->load_defaults();
632 vwindow->create_objects();
635 void MWindow::init_cache()
637 audio_cache = new CICache(preferences, plugindb);
638 video_cache = new CICache(preferences, plugindb);
639 frame_cache = new FrameCache;
640 wave_cache = new WaveCache;
643 void MWindow::init_channeldb()
645 channeldb_buz->load("channeldb_buz");
646 channeldb_v4l2jpeg->load("channeldb_v4l2jpeg");
649 void MWindow::init_menus()
651 char string[BCTEXTLEN];
654 cmodel_to_text(string, BC_RGB888);
655 colormodels.append(new ColormodelItem(string, BC_RGB888));
656 cmodel_to_text(string, BC_RGBA8888);
657 colormodels.append(new ColormodelItem(string, BC_RGBA8888));
658 // cmodel_to_text(string, BC_RGB161616);
659 // colormodels.append(new ColormodelItem(string, BC_RGB161616));
660 // cmodel_to_text(string, BC_RGBA16161616);
661 // colormodels.append(new ColormodelItem(string, BC_RGBA16161616));
662 cmodel_to_text(string, BC_RGB_FLOAT);
663 colormodels.append(new ColormodelItem(string, BC_RGB_FLOAT));
664 cmodel_to_text(string, BC_RGBA_FLOAT);
665 colormodels.append(new ColormodelItem(string, BC_RGBA_FLOAT));
666 cmodel_to_text(string, BC_YUV888);
667 colormodels.append(new ColormodelItem(string, BC_YUV888));
668 cmodel_to_text(string, BC_YUVA8888);
669 colormodels.append(new ColormodelItem(string, BC_YUVA8888));
670 // cmodel_to_text(string, BC_YUV161616);
671 // colormodels.append(new ColormodelItem(string, BC_YUV161616));
672 // cmodel_to_text(string, BC_YUVA16161616);
673 // colormodels.append(new ColormodelItem(string, BC_YUVA16161616));
675 #define ILACEPROJECTMODELISTADD(x) ilacemode_to_text(string, x); \
676 interlace_project_modes.append(new InterlacemodeItem(string, x));
678 #define ILACEASSETMODELISTADD(x) ilacemode_to_text(string, x); \
679 interlace_asset_modes.append(new InterlacemodeItem(string, x));
681 #define ILACEFIXMETHODLISTADD(x) ilacefixmethod_to_text(string, x); \
682 interlace_asset_fixmethods.append(new InterlacefixmethodItem(string, x));
685 ILACEASSETMODELISTADD(BC_ILACE_MODE_UNDETECTED); // Not included in the list for the project options.
687 ILACEASSETMODELISTADD(BC_ILACE_MODE_TOP_FIRST);
688 ILACEPROJECTMODELISTADD(BC_ILACE_MODE_TOP_FIRST);
690 ILACEASSETMODELISTADD(BC_ILACE_MODE_BOTTOM_FIRST);
691 ILACEPROJECTMODELISTADD(BC_ILACE_MODE_BOTTOM_FIRST);
693 ILACEASSETMODELISTADD(BC_ILACE_MODE_NOTINTERLACED);
694 ILACEPROJECTMODELISTADD(BC_ILACE_MODE_NOTINTERLACED);
696 // Interlacing Fixing Methods
697 ILACEFIXMETHODLISTADD(BC_ILACE_FIXMETHOD_NONE);
698 ILACEFIXMETHODLISTADD(BC_ILACE_FIXMETHOD_UPONE);
699 ILACEFIXMETHODLISTADD(BC_ILACE_FIXMETHOD_DOWNONE);
702 void MWindow::init_indexes()
704 mainindexes = new MainIndexes(this);
705 mainindexes->start_loop();
708 void MWindow::init_gui()
710 gui = new MWindowGUI(this);
711 gui->create_objects();
712 gui->load_defaults(defaults);
715 void MWindow::init_signals()
717 sighandler = new SigHandler;
718 sighandler->initialize();
722 void MWindow::init_render()
724 render = new Render(this);
725 // renderlist = new Render(this);
726 batch_render = new BatchRenderThread(this);
729 void MWindow::init_exportedl()
731 exportedl = new ExportEDL(this);
734 void MWindow::init_brender()
736 if(preferences->use_brender && !brender)
738 brender_lock->lock("MWindow::init_brender 1");
739 brender = new BRender(this);
740 brender->initialize();
741 session->brender_end = 0;
742 brender_lock->unlock();
745 if(!preferences->use_brender && brender)
747 brender_lock->lock("MWindow::init_brender 2");
750 session->brender_end = 0;
751 brender_lock->unlock();
753 if(brender) brender->restart(edl);
756 void MWindow::restart_brender()
758 //printf("MWindow::restart_brender 1\n");
759 if(brender) brender->restart(edl);
762 void MWindow::stop_brender()
764 if(brender) brender->stop();
767 int MWindow::brender_available(int position)
770 brender_lock->lock("MWindow::brender_available 1");
773 if(brender->map_valid)
775 brender->map_lock->lock("MWindow::brender_available 2");
776 if(position < brender->map_size &&
779 //printf("MWindow::brender_available 1 %d %d\n", position, brender->map[position]);
780 if(brender->map[position] == BRender::RENDERED)
783 brender->map_lock->unlock();
786 brender_lock->unlock();
790 void MWindow::set_brender_start()
792 edl->session->brender_start = edl->local_session->get_selectionstart();
794 gui->canvas->draw_overlays();
795 gui->canvas->flash();
800 int MWindow::load_filenames(ArrayList<char*> *filenames,
808 ArrayList<EDL*> new_edls;
809 ArrayList<Asset*> new_assets;
810 ArrayList<File*> new_files;
813 gui->start_hourglass();
815 // Need to stop playback since tracking depends on the EDL not getting
817 cwindow->playback_engine->que->send_command(STOP,
821 vwindow->playback_engine->que->send_command(STOP,
825 cwindow->playback_engine->interrupt_playback(0);
826 vwindow->playback_engine->interrupt_playback(0);
830 // Define new_edls and new_assets to load
832 for(int i = 0; i < filenames->total; i++)
835 File *new_file = new File;
836 Asset *new_asset = new Asset(filenames->values[i]);
837 EDL *new_edl = new EDL;
838 char string[BCTEXTLEN];
840 // Set reel name and number for the asset
841 // If the user wants to overwrite the last used reel number for the clip,
842 // we have to rebuild the index for the file
846 char source_filename[BCTEXTLEN];
847 char index_filename[BCTEXTLEN];
849 strcpy(new_asset->reel_name, reel_name);
850 new_asset->reel_number = reel_number;
852 IndexFile::get_index_filename(source_filename,
853 preferences->index_directory,
856 remove(index_filename);
857 new_asset->index_status = INDEX_NOTTESTED;
860 new_edl->create_objects();
861 new_edl->copy_session(edl);
863 sprintf(string, "Loading %s", new_asset->path);
864 gui->show_message(string);
866 result = new_file->open_file(preferences, new_asset, 1, 0, 0, 0);
871 // Convert media file to EDL
873 // Warn about odd image dimensions
874 if(new_asset->video_data &&
875 ((new_asset->width % 2) ||
876 (new_asset->height % 2)))
878 char string[BCTEXTLEN];
879 sprintf(string, "%s's resolution is %dx%d.\nImages with odd dimensions may not decode properly.",
883 MainError::show_error(string);
887 if(load_mode != LOAD_RESOURCESONLY)
890 asset_to_edl(new_edl, new_asset);
892 new_edls.append(new_edl);
894 Garbage::delete_object(new_asset);
900 new_assets.append(new_asset);
903 // Set filename to nothing for assets since save EDL would overwrite them.
904 if(load_mode == LOAD_REPLACE ||
905 load_mode == LOAD_REPLACE_CONCATENATE)
908 // Reset timeline position
909 new_edl->local_session->view_start = 0;
910 new_edl->local_session->track_start = 0;
918 sprintf(string, _("Failed to open %s"), new_asset->path);
919 gui->show_message(string, theme->message_error);
924 case FILE_UNRECOGNIZED_CODEC:
927 IndexFile indexfile(this);
928 result = indexfile.open_index(this, new_asset);
931 indexfile.close_index();
934 // Test existing EDLs
937 for(int j = 0; j < new_edls.total + 1; j++)
940 if(j == new_edls.total)
942 if(old_asset = edl->assets->get_asset(new_asset->path))
944 *new_asset = *old_asset;
950 if(old_asset = new_edls.values[j]->assets->get_asset(new_asset->path))
952 *new_asset = *old_asset;
962 char string[BCTEXTLEN];
964 fs.extract_name(string, new_asset->path);
966 strcat(string, _("'s format couldn't be determined."));
967 new_asset->audio_data = 1;
968 new_asset->format = FILE_PCM;
969 new_asset->channels = defaults->get("AUDIO_CHANNELS", 2);
970 new_asset->sample_rate = defaults->get("SAMPLE_RATE", 44100);
971 new_asset->bits = defaults->get("AUDIO_BITS", 16);
972 new_asset->byte_order = defaults->get("BYTE_ORDER", 1);
973 new_asset->signed_ = defaults->get("SIGNED_", 1);
974 new_asset->header = defaults->get("HEADER", 0);
976 FileFormat fwindow(this);
977 fwindow.create_objects(new_asset, string);
978 result = fwindow.run_window();
980 defaults->update("AUDIO_CHANNELS", new_asset->channels);
981 defaults->update("SAMPLE_RATE", new_asset->sample_rate);
982 defaults->update("AUDIO_BITS", new_asset->bits);
983 defaults->update("BYTE_ORDER", new_asset->byte_order);
984 defaults->update("SIGNED_", new_asset->signed_);
985 defaults->update("HEADER", new_asset->header);
992 // Recalculate length
995 result = new_file->open_file(preferences, new_asset, 1, 0, 0, 0);
997 if(load_mode != LOAD_RESOURCESONLY)
999 asset_to_edl(new_edl, new_asset);
1000 new_edls.append(new_edl);
1001 Garbage::delete_object(new_asset);
1006 new_assets.append(new_asset);
1019 xml_file.read_from_file(filenames->values[i]);
1020 // Load EDL for pasting
1021 new_edl->load_xml(plugindb, &xml_file, LOAD_ALL);
1022 test_plugins(new_edl, filenames->values[i]);
1024 // We don't want a valid reel name/number for projects
1025 strcpy(new_asset->reel_name, "");
1028 if(load_mode == LOAD_REPLACE ||
1029 load_mode == LOAD_REPLACE_CONCATENATE)
1031 strcpy(session->filename, filenames->values[i]);
1032 strcpy(new_edl->local_session->clip_title, filenames->values[i]);
1034 set_filename(new_edl->local_session->clip_title);
1037 new_edls.append(new_edl);
1047 Garbage::delete_object(new_asset);
1053 // Store for testing index
1054 new_files.append(new_file);
1060 if(!result) gui->statusbar->default_message();
1070 // Don't back up here.
1073 // For pasting, clear the active region
1074 if(load_mode == LOAD_PASTE)
1076 double start = edl->local_session->get_selectionstart();
1077 double end = edl->local_session->get_selectionend();
1078 if(!EQUIV(start, end))
1081 edl->session->labels_follow_edits,
1082 edl->session->plugins_follow_edits);
1085 paste_edls(&new_edls,
1089 edl->session->labels_follow_edits,
1090 edl->session->plugins_follow_edits);
1098 // Add new assets to EDL and schedule assets for index building.
1099 // Used for loading resources only.
1100 if(new_assets.total)
1102 for(int i = 0; i < new_assets.total; i++)
1104 Asset *new_asset = new_assets.values[i];
1106 File *index_file = 0;
1108 for(int j = 0; j < new_files.total; j++)
1110 new_file = new_files.values[j];
1111 if(!strcmp(new_file->asset->path,
1119 mainindexes->add_next_asset(got_it ? new_file : 0,
1121 edl->assets->update(new_asset);
1126 // Start examining next batch of index files
1127 mainindexes->start_build();
1131 update_project(load_mode);
1136 new_edls.remove_all_objects();
1138 for(int i = 0; i < new_assets.total; i++)
1139 Garbage::delete_object(new_assets.values[i]);
1141 new_assets.remove_all();
1143 new_files.remove_all_objects();
1146 undo->update_undo(_("load"), LOAD_ALL, 0);
1150 gui->stop_hourglass();
1159 void MWindow::test_plugins(EDL *new_edl, char *path)
1161 char string[BCTEXTLEN];
1162 // Do a check weather plugins exist
1163 for(Track *track = new_edl->tracks->first; track; track = track->next)
1165 for(int k = 0; k < track->plugin_set.total; k++)
1167 PluginSet *plugin_set = track->plugin_set.values[k];
1168 for(Plugin *plugin = (Plugin*)plugin_set->first;
1170 plugin = (Plugin*)plugin->next)
1172 if(plugin->plugin_type == PLUGIN_STANDALONE)
1174 // ok we need to find it in plugindb
1175 int plugin_found = 0;
1176 for(int j = 0; j < plugindb->total; j++)
1178 PluginServer *server = plugindb->values[j];
1179 if(!strcasecmp(server->title, plugin->title) &&
1180 ((track->data_type == TRACK_AUDIO && server->audio) ||
1181 (track->data_type == TRACK_VIDEO && server->video)) &&
1182 (!server->transition))
1188 "The effect '%s' in file '%s' is not part of your installation of Cinelerra.\n"
1189 "The project won't be rendered as it was meant and Cinelerra might crash.\n",
1192 MainError::show_error(string);
1197 for(Edit *edit = (Edit*)track->edits->first;
1199 edit = (Edit*)edit->next)
1201 if (edit->transition)
1203 // ok we need to find transition in plugindb
1204 int transition_found = 0;
1205 for(int j = 0; j < plugindb->total; j++)
1207 PluginServer *server = plugindb->values[j];
1208 if(!strcasecmp(server->title, edit->transition->title) &&
1209 ((track->data_type == TRACK_AUDIO && server->audio) ||
1210 (track->data_type == TRACK_VIDEO && server->video)) &&
1211 (server->transition))
1212 transition_found = 1;
1214 if (!transition_found)
1217 "The transition '%s' in file '%s' is not part of your installation of Cinelerra.\n"
1218 "The project won't be rendered as it was meant and Cinelerra might crash.\n",
1219 edit->transition->title,
1221 MainError::show_error(string);
1232 void MWindow::create_objects(int want_gui,
1236 char string[BCTEXTLEN];
1245 // For some reason, init_signals must come after show_splash or the signals won't
1253 init_defaults(defaults, config_path);
1257 init_plugins(preferences, plugindb, splash_window);
1258 if(splash_window) splash_window->operation->update(_("Initializing GUI"));
1261 // Default project created here
1287 mainprogress = new MainProgress(this, gui);
1288 undo = new MainUndo(this);
1290 plugin_guis = new ArrayList<PluginServer*>;
1293 if(session->show_vwindow) vwindow->gui->show_window();
1294 if(session->show_cwindow) cwindow->gui->show_window();
1295 if(session->show_awindow) awindow->gui->show_window();
1296 if(session->show_lwindow) lwindow->gui->show_window();
1297 if(session->show_gwindow) gwindow->gui->show_window();
1301 gui->mainmenu->load_defaults(defaults);
1303 gui->mainmenu->update_toggles(0);
1305 gui->patchbay->update();
1307 gui->canvas->draw();
1309 gui->cursor->draw(1);
1312 gui->raise_window();
1314 if(preferences->use_tipwindow)
1324 void MWindow::show_splash()
1326 #include "data/heroine_logo12_png.h"
1327 VFrame *frame = new VFrame(heroine_logo12_png);
1328 BC_DisplayInfo display_info;
1329 splash_window = new SplashGUI(frame,
1330 display_info.get_root_w() / 2 - frame->get_w() / 2,
1331 display_info.get_root_h() / 2 - frame->get_h() / 2);
1332 splash_window->create_objects();
1335 void MWindow::hide_splash()
1338 delete splash_window;
1343 void MWindow::start()
1352 playback_3d->start();
1360 void MWindow::show_vwindow()
1362 session->show_vwindow = 1;
1363 vwindow->gui->lock_window("MWindow::show_vwindow");
1364 vwindow->gui->show_window();
1365 vwindow->gui->raise_window();
1366 vwindow->gui->flush();
1367 vwindow->gui->unlock_window();
1368 gui->mainmenu->show_vwindow->set_checked(1);
1371 void MWindow::show_awindow()
1373 session->show_awindow = 1;
1374 awindow->gui->lock_window("MWindow::show_awindow");
1375 awindow->gui->show_window();
1376 awindow->gui->raise_window();
1377 awindow->gui->flush();
1378 awindow->gui->unlock_window();
1379 gui->mainmenu->show_awindow->set_checked(1);
1382 void MWindow::show_cwindow()
1384 session->show_cwindow = 1;
1385 cwindow->show_window();
1386 gui->mainmenu->show_cwindow->set_checked(1);
1389 void MWindow::show_gwindow()
1391 session->show_gwindow = 1;
1393 gwindow->gui->lock_window("MWindow::show_gwindow");
1394 gwindow->gui->show_window();
1395 gwindow->gui->raise_window();
1396 gwindow->gui->flush();
1397 gwindow->gui->unlock_window();
1399 gui->mainmenu->show_gwindow->set_checked(1);
1402 void MWindow::show_lwindow()
1404 session->show_lwindow = 1;
1405 lwindow->gui->lock_window("MWindow::show_lwindow");
1406 lwindow->gui->show_window();
1407 lwindow->gui->raise_window();
1408 lwindow->gui->flush();
1409 lwindow->gui->unlock_window();
1410 gui->mainmenu->show_lwindow->set_checked(1);
1413 void MWindow::tile_windows()
1415 session->default_window_positions();
1416 gui->default_positions();
1419 void MWindow::toggle_loop_playback()
1421 edl->local_session->loop_playback = !edl->local_session->loop_playback;
1422 set_loop_boundaries();
1425 gui->canvas->draw_overlays();
1426 gui->canvas->flash();
1427 sync_parameters(CHANGE_PARAMS);
1430 void MWindow::set_titles(int value)
1432 edl->session->show_titles = value;
1433 trackmovement(edl->local_session->track_start);
1436 void MWindow::set_auto_keyframes(int value)
1438 gui->lock_window("MWindow::set_auto_keyframes");
1439 edl->session->auto_keyframes = value;
1440 gui->mbuttons->edit_panel->keyframe->update(value);
1442 gui->unlock_window();
1443 cwindow->gui->lock_window("MWindow::set_auto_keyframes");
1444 cwindow->gui->edit_panel->keyframe->update(value);
1445 cwindow->gui->flush();
1446 cwindow->gui->unlock_window();
1449 int MWindow::set_editing_mode(int new_editing_mode)
1451 gui->lock_window("MWindow::set_editing_mode");
1452 edl->session->editing_mode = new_editing_mode;
1453 gui->mbuttons->edit_panel->editing_mode = edl->session->editing_mode;
1454 gui->mbuttons->edit_panel->update();
1455 gui->canvas->update_cursor();
1456 gui->unlock_window();
1457 cwindow->gui->lock_window("MWindow::set_editing_mode");
1458 cwindow->gui->edit_panel->update();
1459 cwindow->gui->edit_panel->editing_mode = edl->session->editing_mode;
1460 cwindow->gui->unlock_window();
1465 void MWindow::sync_parameters(int change_type)
1468 // Sync engines which are playing back
1469 if(cwindow->playback_engine->is_playing_back)
1471 if(change_type == CHANGE_PARAMS)
1473 // TODO: block keyframes until synchronization is done
1474 cwindow->playback_engine->sync_parameters(edl);
1479 int command = cwindow->playback_engine->command->command;
1480 cwindow->playback_engine->que->send_command(STOP,
1484 // Waiting for tracking to finish would make the restart position more
1485 // accurate but it can't lock the window to stop tracking for some reason.
1486 // Not waiting for tracking gives a faster response but restart position is
1487 // only as accurate as the last tracking update.
1488 cwindow->playback_engine->interrupt_playback(0);
1489 cwindow->playback_engine->que->send_command(command,
1498 cwindow->playback_engine->que->send_command(CURRENT_FRAME,
1505 void MWindow::age_caches()
1507 int64_t prev_memory_usage;
1508 int64_t memory_usage;
1512 memory_usage = audio_cache->get_memory_usage(1) +
1513 video_cache->get_memory_usage(1) +
1514 frame_cache->get_memory_usage() +
1515 wave_cache->get_memory_usage();
1517 if(memory_usage > preferences->cache_size)
1520 int oldest1 = audio_cache->get_oldest();
1521 int oldest2 = video_cache->get_oldest();
1522 if(oldest2 < oldest1) target = 2;
1523 int oldest3 = frame_cache->get_oldest();
1524 if(oldest3 < oldest1 && oldest3 < oldest2) target = 3;
1525 int oldest4 = wave_cache->get_oldest();
1526 if(oldest4 < oldest3 && oldest4 < oldest2 && oldest4 < oldest1) target = 4;
1529 case 1: audio_cache->delete_oldest(); break;
1530 case 2: video_cache->delete_oldest(); break;
1531 case 3: frame_cache->delete_oldest(); break;
1532 case 4: wave_cache->delete_oldest(); break;
1535 prev_memory_usage = memory_usage;
1536 memory_usage = audio_cache->get_memory_usage(1) +
1537 video_cache->get_memory_usage(1) +
1538 frame_cache->get_memory_usage() +
1539 wave_cache->get_memory_usage();
1541 prev_memory_usage != memory_usage &&
1542 memory_usage > preferences->cache_size);
1545 void MWindow::show_plugin(Plugin *plugin)
1548 //printf("MWindow::show_plugin 1\n");
1549 plugin_gui_lock->lock("MWindow::show_plugin");
1550 for(int i = 0; i < plugin_guis->total; i++)
1552 // Pointer comparison
1553 if(plugin_guis->values[i]->plugin == plugin)
1555 plugin_guis->values[i]->raise_window();
1561 //printf("MWindow::show_plugin 1\n");
1566 printf("MWindow::show_plugin track not defined.\n");
1568 PluginServer *server = scan_plugindb(plugin->title,
1569 plugin->track->data_type);
1571 //printf("MWindow::show_plugin %p %d\n", server, server->uses_gui);
1572 if(server && server->uses_gui)
1574 PluginServer *gui = plugin_guis->append(new PluginServer(*server));
1575 // Needs mwindow to do GUI
1576 gui->set_mwindow(this);
1577 gui->open_plugin(0, preferences, edl, plugin, -1);
1582 plugin_gui_lock->unlock();
1583 //printf("MWindow::show_plugin 2\n");
1586 void MWindow::hide_plugin(Plugin *plugin, int lock)
1589 gui->lock_window("MWindow::hide_plugin");
1590 gui->update(0, 1, 0, 0, 0, 0, 0);
1591 gui->unlock_window();
1593 if(lock) plugin_gui_lock->lock("MWindow::hide_plugin");
1594 for(int i = 0; i < plugin_guis->total; i++)
1596 if(plugin_guis->values[i]->plugin == plugin)
1598 PluginServer *ptr = plugin_guis->values[i];
1599 plugin_guis->remove(ptr);
1600 if(lock) plugin_gui_lock->unlock();
1601 // Last command executed in client side close
1606 if(lock) plugin_gui_lock->unlock();
1610 void MWindow::hide_plugins()
1612 plugin_gui_lock->lock("MWindow::hide_plugins");
1613 plugin_guis->remove_all_objects();
1614 plugin_gui_lock->unlock();
1617 void MWindow::update_plugin_guis()
1619 plugin_gui_lock->lock("MWindow::update_plugin_guis");
1621 for(int i = 0; i < plugin_guis->total; i++)
1623 plugin_guis->values[i]->update_gui();
1625 plugin_gui_lock->unlock();
1628 int MWindow::plugin_gui_open(Plugin *plugin)
1631 plugin_gui_lock->lock("MWindow::plugin_gui_open");
1632 for(int i = 0; i < plugin_guis->total; i++)
1634 if(plugin_guis->values[i]->plugin->identical_location(plugin))
1640 plugin_gui_lock->unlock();
1644 void MWindow::render_plugin_gui(void *data, Plugin *plugin)
1646 plugin_gui_lock->lock("MWindow::render_plugin_gui");
1647 for(int i = 0; i < plugin_guis->total; i++)
1649 if(plugin_guis->values[i]->plugin->identical_location(plugin))
1651 plugin_guis->values[i]->render_gui(data);
1655 plugin_gui_lock->unlock();
1658 void MWindow::render_plugin_gui(void *data, int size, Plugin *plugin)
1660 plugin_gui_lock->lock("MWindow::render_plugin_gui");
1661 for(int i = 0; i < plugin_guis->total; i++)
1663 if(plugin_guis->values[i]->plugin->identical_location(plugin))
1665 plugin_guis->values[i]->render_gui(data, size);
1669 plugin_gui_lock->unlock();
1673 void MWindow::update_plugin_states()
1675 plugin_gui_lock->lock("MWindow::update_plugin_states");
1676 for(int i = 0; i < plugin_guis->total; i++)
1680 Plugin *src_plugin = plugin_guis->values[i]->plugin;
1681 PluginServer *src_plugingui = plugin_guis->values[i];
1683 // Search for plugin in EDL. Only the master EDL shows plugin GUIs.
1684 for(Track *track = edl->tracks->first;
1686 track = track->next)
1689 j < track->plugin_set.total && !result;
1692 PluginSet *plugin_set = track->plugin_set.values[j];
1693 for(Plugin *plugin = (Plugin*)plugin_set->first;
1695 plugin = (Plugin*)plugin->next)
1697 if(plugin == src_plugin &&
1698 !strcmp(plugin->title, src_plugingui->title)) result = 1;
1704 // Doesn't exist anymore
1707 hide_plugin(src_plugin, 0);
1711 plugin_gui_lock->unlock();
1715 void MWindow::update_plugin_titles()
1717 for(int i = 0; i < plugin_guis->total; i++)
1719 plugin_guis->values[i]->update_title();
1723 int MWindow::asset_to_edl(EDL *new_edl,
1725 RecordLabels *labels)
1727 //printf("MWindow::asset_to_edl 1\n");
1728 // new_edl->load_defaults(defaults);
1730 // Keep frame rate, sample rate, and output size unchanged.
1731 // These parameters would revert the project if VWindow displayed an asset
1732 // of different size than the project.
1733 if(new_asset->video_data)
1735 new_edl->session->video_tracks = new_asset->layers;
1736 // new_edl->session->frame_rate = new_asset->frame_rate;
1737 // new_edl->session->output_w = new_asset->width;
1738 // new_edl->session->output_h = new_asset->height;
1741 new_edl->session->video_tracks = 0;
1748 if(new_asset->audio_data)
1750 new_edl->session->audio_tracks = new_asset->channels;
1751 // new_edl->session->sample_rate = new_asset->sample_rate;
1754 new_edl->session->audio_tracks = 0;
1755 //printf("MWindow::asset_to_edl 2 %d %d\n", new_edl->session->video_tracks, new_edl->session->audio_tracks);
1757 new_edl->create_default_tracks();
1758 //printf("MWindow::asset_to_edl 2 %d %d\n", new_edl->session->video_tracks, new_edl->session->audio_tracks);
1760 // Disable drawing if the file format isn't fast enough.
1761 // MPEG is now faster than most other codecs.
1762 // if(new_asset->format == FILE_MPEG)
1764 // for(Track *current = new_edl->tracks->first;
1768 // if(current->data_type == TRACK_VIDEO) current->draw = 0;
1774 //printf("MWindow::asset_to_edl 3\n");
1775 new_edl->insert_asset(new_asset, 0, 0, labels);
1776 //printf("MWindow::asset_to_edl 3\n");
1782 char string[BCTEXTLEN];
1784 fs.extract_name(string, new_asset->path);
1785 //printf("MWindow::asset_to_edl 3\n");
1787 strcpy(new_edl->local_session->clip_title, string);
1788 //printf("MWindow::asset_to_edl 4 %s\n", string);
1794 // Reset everything after a load.
1795 void MWindow::update_project(int load_mode)
1798 edl->tracks->update_y_pixels(theme);
1801 gui->update(1, 1, 1, 1, 1, 1, 1);
1803 cwindow->update(0, 0, 1, 1, 1);
1806 if(load_mode == LOAD_REPLACE ||
1807 load_mode == LOAD_REPLACE_CONCATENATE)
1809 vwindow->change_source();
1816 cwindow->gui->slider->set_position();
1817 cwindow->gui->timebar->update(1, 1);
1818 cwindow->playback_engine->que->send_command(CURRENT_FRAME,
1823 awindow->gui->lock_window("MWindow::update_project");
1824 awindow->gui->update_assets();
1825 awindow->gui->flush();
1826 awindow->gui->unlock_window();
1831 void MWindow::rebuild_indices()
1833 char source_filename[BCTEXTLEN], index_filename[BCTEXTLEN];
1835 for(int i = 0; i < session->drag_assets->total; i++)
1837 //printf("MWindow::rebuild_indices 1 %s\n", session->drag_assets->values[i]->path);
1839 IndexFile::get_index_filename(source_filename,
1840 preferences->index_directory,
1842 session->drag_assets->values[i]->path);
1843 remove(index_filename);
1844 // Schedule index build
1845 session->drag_assets->values[i]->index_status = INDEX_NOTTESTED;
1846 mainindexes->add_next_asset(0, session->drag_assets->values[i]);
1848 mainindexes->start_build();
1852 void MWindow::save_backup()
1855 edl->set_project_path(session->filename);
1856 edl->save_xml(plugindb,
1861 file.terminate_string();
1862 char path[BCTEXTLEN];
1864 strcpy(path, BACKUP_PATH);
1865 fs.complete_path(path);
1867 if(file.write_to_file(path))
1870 sprintf(string2, _("Couldn't open %s for writing."), BACKUP_PATH);
1871 gui->show_message(string2);
1876 int MWindow::create_aspect_ratio(float &w, float &h, int width, int height)
1879 if(!width || !height) return 1;
1880 float fraction = (float)width / height;
1882 for(denominator = 1;
1883 denominator < 100 &&
1884 fabs(fraction * denominator - (int)(fraction * denominator)) > .001;
1888 w = denominator * width / height;
1893 void MWindow::reset_caches()
1895 frame_cache->remove_all();
1896 wave_cache->remove_all();
1897 audio_cache->remove_all();
1898 video_cache->remove_all();
1899 if(cwindow->playback_engine && cwindow->playback_engine->audio_cache)
1900 cwindow->playback_engine->audio_cache->remove_all();
1901 if(cwindow->playback_engine && cwindow->playback_engine->video_cache)
1902 cwindow->playback_engine->video_cache->remove_all();
1903 if(vwindow->playback_engine && vwindow->playback_engine->audio_cache)
1904 vwindow->playback_engine->audio_cache->remove_all();
1905 if(vwindow->playback_engine && vwindow->playback_engine->video_cache)
1906 vwindow->playback_engine->video_cache->remove_all();
1909 void MWindow::remove_asset_from_caches(Asset *asset)
1911 frame_cache->remove_asset(asset);
1912 wave_cache->remove_asset(asset);
1913 audio_cache->delete_entry(asset);
1914 video_cache->delete_entry(asset);
1915 if(cwindow->playback_engine && cwindow->playback_engine->audio_cache)
1916 cwindow->playback_engine->audio_cache->delete_entry(asset);
1917 if(cwindow->playback_engine && cwindow->playback_engine->video_cache)
1918 cwindow->playback_engine->video_cache->delete_entry(asset);
1919 if(vwindow->playback_engine && vwindow->playback_engine->audio_cache)
1920 vwindow->playback_engine->audio_cache->delete_entry(asset);
1921 if(vwindow->playback_engine && vwindow->playback_engine->video_cache)
1922 vwindow->playback_engine->video_cache->delete_entry(asset);
1927 void MWindow::remove_assets_from_project(int push_undo)
1929 for(int i = 0; i < session->drag_assets->total; i++)
1931 Asset *asset = session->drag_assets->values[i];
1932 remove_asset_from_caches(asset);
1935 // Remove from VWindow.
1936 for(int i = 0; i < session->drag_clips->total; i++)
1938 if(session->drag_clips->values[i] == vwindow->get_edl())
1940 vwindow->gui->lock_window("MWindow::remove_assets_from_project 1");
1941 vwindow->remove_source();
1942 vwindow->gui->unlock_window();
1946 for(int i = 0; i < session->drag_assets->total; i++)
1948 if(session->drag_assets->values[i] == vwindow->get_asset())
1950 vwindow->gui->lock_window("MWindow::remove_assets_from_project 2");
1951 vwindow->remove_source();
1952 vwindow->gui->unlock_window();
1956 edl->remove_from_project(session->drag_assets);
1957 edl->remove_from_project(session->drag_clips);
1959 if(push_undo) undo->update_undo(_("remove assets"), LOAD_ALL);
1962 gui->lock_window("MWindow::remove_assets_from_project 3");
1970 gui->unlock_window();
1972 awindow->gui->lock_window("MWindow::remove_assets_from_project 4");
1973 awindow->gui->update_assets();
1974 awindow->gui->flush();
1975 awindow->gui->unlock_window();
1977 // Removes from playback here
1978 sync_parameters(CHANGE_ALL);
1981 void MWindow::remove_assets_from_disk()
1984 for(int i = 0; i < session->drag_assets->total; i++)
1986 remove(session->drag_assets->values[i]->path);
1989 remove_assets_from_project(1);
1992 void MWindow::dump_plugins()
1994 for(int i = 0; i < plugindb->total; i++)
1996 printf("audio=%d video=%d realtime=%d transition=%d theme=%d %s\n",
1997 plugindb->values[i]->audio,
1998 plugindb->values[i]->video,
1999 plugindb->values[i]->realtime,
2000 plugindb->values[i]->transition,
2001 plugindb->values[i]->theme,
2002 plugindb->values[i]->title);
2030 int MWindow::save_defaults()
2032 gui->save_defaults(defaults);
2033 edl->save_defaults(defaults);
2034 session->save_defaults(defaults);
2035 preferences->save_defaults(defaults);
2041 int MWindow::run_script(FileXML *script)
2043 int result = 0, result2 = 0;
2044 while(!result && !result2)
2046 result = script->read_tag();
2049 if(script->tag.title_is("new_project"))
2051 // Run new in immediate mode.
2052 // gui->mainmenu->new_project->run_script(script);
2055 if(script->tag.title_is("record"))
2057 // Run record as a thread. It is a terminal command.
2059 // Will read the complete scipt file without letting record read it if not
2065 printf("MWindow::run_script: Unrecognized command: %s\n",script->tag.get_title() );
2072 // ================================= synchronization
2075 int MWindow::interrupt_indexes()
2077 mainindexes->interrupt_build();
2083 void MWindow::next_time_format()
2085 switch(edl->session->time_format)
2087 case TIME_HMS: edl->session->time_format = TIME_HMSF; break;
2088 case TIME_HMSF: edl->session->time_format = TIME_SAMPLES; break;
2089 case TIME_SAMPLES: edl->session->time_format = TIME_SAMPLES_HEX; break;
2090 case TIME_SAMPLES_HEX: edl->session->time_format = TIME_FRAMES; break;
2091 case TIME_FRAMES: edl->session->time_format = TIME_FEET_FRAMES; break;
2092 case TIME_FEET_FRAMES: edl->session->time_format = TIME_SECONDS; break;
2093 case TIME_SECONDS: edl->session->time_format = TIME_HMS; break;
2096 time_format_common();
2099 void MWindow::prev_time_format()
2101 switch(edl->session->time_format)
2103 case TIME_HMS: edl->session->time_format = TIME_SECONDS; break;
2104 case TIME_SECONDS: edl->session->time_format = TIME_FEET_FRAMES; break;
2105 case TIME_FEET_FRAMES: edl->session->time_format = TIME_FRAMES; break;
2106 case TIME_FRAMES: edl->session->time_format = TIME_SAMPLES_HEX; break;
2107 case TIME_SAMPLES_HEX: edl->session->time_format = TIME_SAMPLES; break;
2108 case TIME_SAMPLES: edl->session->time_format = TIME_HMSF; break;
2109 case TIME_HMSF: edl->session->time_format = TIME_HMS; break;
2112 time_format_common();
2115 void MWindow::time_format_common()
2117 gui->lock_window("MWindow::next_time_format");
2118 gui->redraw_time_dependancies();
2119 char string[BCTEXTLEN], string2[BCTEXTLEN];
2120 sprintf(string, _("Using %s."), Units::print_time_format(edl->session->time_format, string2));
2121 gui->show_message(string);
2123 gui->unlock_window();
2127 int MWindow::set_filename(char *filename)
2129 strcpy(session->filename, filename);
2132 if(filename[0] == 0)
2134 gui->set_title(PROGRAM_NAME);
2139 char string[BCTEXTLEN], string2[BCTEXTLEN];
2140 dir.extract_name(string, filename);
2141 sprintf(string2, PROGRAM_NAME ": %s", string);
2142 gui->set_title(string2);
2155 int MWindow::set_loop_boundaries()
2157 double start = edl->local_session->get_selectionstart();
2158 double end = edl->local_session->get_selectionend();
2166 if(edl->tracks->total_length())
2169 end = edl->tracks->total_length();
2176 if(edl->local_session->loop_playback && start != end)
2178 edl->local_session->loop_start = start;
2179 edl->local_session->loop_end = end;
2190 int MWindow::reset_meters()
2192 cwindow->gui->lock_window("MWindow::reset_meters 1");
2193 cwindow->gui->meters->reset_meters();
2194 cwindow->gui->unlock_window();
2196 vwindow->gui->lock_window("MWindow::reset_meters 2");
2197 vwindow->gui->meters->reset_meters();
2198 vwindow->gui->unlock_window();
2200 lwindow->gui->lock_window("MWindow::reset_meters 3");
2201 lwindow->gui->panel->reset_meters();
2202 lwindow->gui->unlock_window();
2204 gui->lock_window("MWindow::reset_meters 4");
2205 gui->patchbay->reset_meters();
2206 gui->unlock_window();