r863: Merge 2.1:
[cinelerra_cv/ct.git] / cinelerra / mwindow.C
blob9000219efb729f4f5b8249020138594dfd7bdca8
1 #include "asset.h"
2 #include "assets.h"
3 #include "awindowgui.h"
4 #include "awindow.h"
5 #include "batchrender.h"
6 #include "bcdisplayinfo.h"
7 #include "bcsignals.h"
8 #include "brender.h"
9 #include "cache.h"
10 #include "channel.h"
11 #include "channeldb.h"
12 #include "clip.h"
13 #include "colormodels.h"
14 #include "cplayback.h"
15 #include "ctimebar.h"
16 #include "cwindowgui.h"
17 #include "cwindow.h"
18 #include "bchash.h"
19 #include "devicedvbinput.inc"
20 #include "editpanel.h"
21 #include "edl.h"
22 #include "edlsession.h"
23 #include "errorbox.h"
24 #include "fileformat.h"
25 #include "file.h"
26 #include "filesystem.h"
27 #include "filexml.h"
28 #include "framecache.h"
29 #include "gwindow.h"
30 #include "gwindowgui.h"
31 #include "indexfile.h"
32 #include "interlacemodes.h"
33 #include "language.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"
41 #include "mainmenu.h"
42 #include "mainprogress.h"
43 #include "mainsession.h"
44 #include "mainundo.h"
45 #include "mbuttons.h"
46 #include "mutex.h"
47 #include "mwindowgui.h"
48 #include "mwindow.h"
49 #include "new.h"
50 #include "patchbay.h"
51 #include "playback3d.h"
52 #include "playbackengine.h"
53 #include "plugin.h"
54 #include "pluginserver.h"
55 #include "pluginset.h"
56 #include "preferences.h"
57 #include "record.h"
58 #include "recordlabel.h"
59 #include "render.h"
60 #include "samplescroll.h"
61 #include "sighandler.h"
62 #include "splashgui.h"
63 #include "statusbar.h"
64 #include "theme.h"
65 #include "threadloader.h"
66 #include "timebar.h"
67 #include "tipwindow.h"
68 #include "trackcanvas.h"
69 #include "track.h"
70 #include "tracking.h"
71 #include "trackscroll.h"
72 #include "tracks.h"
73 #include "transition.h"
74 #include "transportque.h"
75 #include "vframe.h"
76 #include "videodevice.inc"
77 #include "videowindow.h"
78 #include "vplayback.h"
79 #include "vwindowgui.h"
80 #include "vwindow.h"
81 #include "wavecache.h"
82 #include "zoombar.h"
83 #include "exportedl.h"
85 #include <string.h>
89 extern "C"
95 // Hack for libdv to remove glib dependancy
97 // void
98 // g_log (const char    *log_domain,
99 //        int  log_level,
100 //        const char    *format,
101 //        ...)
102 // {
103 // }
104 // 
105 // void
106 // g_logv (const char    *log_domain,
107 //        int  log_level,
108 //        const char    *format,
109 //        ...)
110 // {
111 // }
112 // 
115 // Hack for XFree86 4.1.0
117 int atexit(void (*function)(void))
119         return 0;
128 MWindow::MWindow()
129  : Thread(1, 0, 0)
131         plugin_gui_lock = new Mutex("MWindow::plugin_gui_lock");
132         brender_lock = new Mutex("MWindow::brender_lock");
133         brender = 0;
134         session = 0;
135         channeldb_buz = new ChannelDB;
136         channeldb_v4l2jpeg = new ChannelDB;
137         dvb_input = 0;
138         dvb_input_lock = new Mutex("MWindow::dvb_input_lock");
141 MWindow::~MWindow()
143         brender_lock->lock("MWindow::~MWindow");
144         if(brender) delete brender;
145         brender = 0;
146         brender_lock->unlock();
147         delete brender_lock;
149         delete mainindexes;
151 SET_TRACE
152         clean_indexes();
153 SET_TRACE
155         save_defaults();
156 SET_TRACE
157 // Give up and go to a movie
158         exit(0);
160 SET_TRACE
161         delete mainprogress;
162         delete audio_cache;             // delete the cache after the assets
163         delete video_cache;             // delete the cache after the assets
164         delete frame_cache;
165         if(gui) delete gui;
166         delete undo;
167         delete preferences;
168         delete defaults;
169         delete render;
170 //      delete renderlist;
171         delete awindow;
172         delete vwindow;
173         delete cwindow;
174         delete lwindow;
175         plugin_guis->remove_all_objects();
176         delete plugin_guis;
177         delete plugin_gui_lock;
180 void MWindow::init_error()
182         new MainError(this);
185 void MWindow::create_defaults_path(char *string)
187 // set the .bcast path
188         FileSystem fs;
190         sprintf(string, "%s", BCASTDIR);
191         fs.complete_path(string);
192         if(!fs.is_dir(string)) 
193         {
194                 fs.create_dir(string); 
195         }
197 // load the defaults
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
205         if(config_path[0])
206         {
207                 strcpy(path, config_path);
208         }
209         else
210         {
211                 create_defaults_path(path);
212         }
214         defaults = new BC_Hash(path);
215         defaults->load();
218 void MWindow::init_plugin_path(Preferences *preferences, 
219         ArrayList<PluginServer*>* &plugindb,
220         FileSystem *fs,
221         SplashGUI *splash_window,
222         int *counter)
224         int result = 0;
225         PluginServer *newplugin;
227         if(!result)
228         {
229                 for(int i = 0; i < fs->dir_list.total; i++)
230                 {
231                         char path[BCTEXTLEN];
232                         strcpy(path, fs->dir_list.values[i]->path);
234 // File is a directory
235                         if(fs->is_dir(path))
236                         {
237                                 continue;
238                         }
239                         else
240                         {
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);
247                                 if(!result)
248                                 {
249                                         plugindb->append(new_plugin);
250                                         new_plugin->close_plugin();
251                                         if(splash_window)
252                                                 splash_window->operation->update(_(new_plugin->title));
253                                 }
254                                 else
255                                 if(result == PLUGINSERVER_IS_LAD)
256                                 {
257                                         delete new_plugin;
258 // Open LAD subplugins
259                                         int id = 0;
260                                         do
261                                         {
262                                                 new_plugin = new PluginServer(path);
263                                                 result = new_plugin->open_plugin(1,
264                                                         preferences,
265                                                         0,
266                                                         0,
267                                                         id);
268                                                 id++;
269                                                 if(!result)
270                                                 {
271                                                         plugindb->append(new_plugin);
272                                                         new_plugin->close_plugin();
273                                                         if(splash_window)
274                                                                 splash_window->operation->update(_(new_plugin->title));
275                                                         else
276                                                         {
277                                                         }
278                                                 }
279                                         }while(!result);
280                                 }
281                                 else
282                                 {
283 // Plugin failed to open
284                                         delete new_plugin;
285                                 }
286                         }
288                         if(splash_window) splash_window->progress->update((*counter)++);
289                 }
290         }
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;
303         int result = 0;
305 // Get directories
306         cinelerra_fs.set_filter("[*.plugin][*.so]");
307         result = cinelerra_fs.update(preferences->global_plugin_dir);
309         if(result)
310         {
311                 fprintf(stderr, 
312                         _("MWindow::init_plugins: couldn't open %s directory\n"),
313                         preferences->global_plugin_dir);
314         }
316 // Parse LAD environment variable
317         char *env = getenv("LADSPA_PATH");
318         if(env)
319         {
320                 char string[BCTEXTLEN];
321                 char *ptr1 = env;
322                 while(ptr1)
323                 {
324                         char *ptr = strchr(ptr1, ':');
325                         char *end;
326                         if(ptr)
327                         {
328                                 end = ptr;
329                         }
330                         else
331                         {
332                                 end = env + strlen(env);
333                         }
335                         if(end > ptr1)
336                         {
337                                 int len = end - ptr1;
338                                 memcpy(string, ptr1, len);
339                                 string[len] = 0;
342                                 FileSystem *fs = new FileSystem;
343                                 lad_fs.append(fs);
344                                 fs->set_filter("*.so");
345                                 result = fs->update(string);
347                                 if(result)
348                                 {
349                                         fprintf(stderr, 
350                                                 _("MWindow::init_plugins: couldn't open %s directory\n"),
351                                                 string);
352                                 }
353                         }
355                         if(ptr)
356                                 ptr1 = ptr + 1;
357                         else
358                                 ptr1 = ptr;
359                 };
360         }
362         int total = cinelerra_fs.total_files();
363         int counter = 0;
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);
369 // Cinelerra
370 #ifndef DO_STATIC
371         init_plugin_path(preferences,
372                 plugindb,
373                 &cinelerra_fs,
374                 splash_window,
375                 &counter);
376 #else
377 // Call automatically generated routine to get plugins
378 #endif
380 // LAD
381         for(int i = 0; i < lad_fs.total; i++)
382                 init_plugin_path(preferences,
383                         plugindb,
384                         lad_fs.values[i],
385                         splash_window,
386                         &counter);
388         lad_fs.remove_all_objects();
391 void MWindow::delete_plugins()
393         for(int i = 0; i < plugindb->total; i++)
394         {
395                 delete plugindb->values[i];
396         }
397         delete plugindb;
400 void MWindow::create_plugindb(int do_audio, 
401                 int do_video, 
402                 int is_realtime, 
403                 int is_transition,
404                 int is_theme,
405                 ArrayList<PluginServer*> &plugindb)
407 // Get plugins
408         for(int i = 0; i < this->plugindb->total; i++)
409         {
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);
418         }
420 // Alphabetize list by title
421         int done = 0;
422         while(!done)
423         {
424                 done = 1;
425                 
426                 for(int i = 0; i < plugindb.total - 1; i++)
427                 {
428                         PluginServer *value1 = plugindb.values[i];
429                         PluginServer *value2 = plugindb.values[i + 1];
430                         if(strcmp(_(value1->title), _(value2->title)) > 0)
431                         {
432                                 done = 0;
433                                 plugindb.values[i] = value2;
434                                 plugindb.values[i + 1] = value1;
435                         }
436                 }
437         }
440 PluginServer* MWindow::scan_plugindb(char *title,
441                 int data_type)
443         if(data_type < 0)
444         {
445                 printf("MWindow::scan_plugindb data_type < 0\n");
446                 return 0;
447         }
449         for(int i = 0; i < plugindb->total; i++)
450         {
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];
456         }
457         return 0;
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()
470         FileSystem fs;
471         int total_excess;
472         long oldest;
473         int oldest_item = -1;
474         int result;
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
485         result = 1;
486         while(result)
487         {
488                 result = 0;
489                 for(int i = 0; i < fs.dir_list.total && !result; i++)
490                 {
491                         fs.join_names(string, preferences->index_directory, fs.dir_list.values[i]->name);
492                         if(fs.is_dir(string))
493                         {
494                                 delete fs.dir_list.values[i];
495                                 fs.dir_list.remove_number(i);
496                                 result = 1;
497                         }
498                 }
499         }
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)
504         {
505 // Get oldest
506                 for(int i = 0; i < fs.dir_list.total; i++)
507                 {
508                         fs.join_names(string, preferences->index_directory, fs.dir_list.values[i]->name);
510                         if(i == 0 || fs.get_date(string) <= oldest)
511                         {
512                                 oldest = fs.get_date(string);
513                                 oldest_item = i;
514                         }
515                 }
517                 if(oldest_item >= 0)
518                 {
519 // Remove index file
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);
524                         if(remove(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, '.');
532                         if(ptr)
533                         {
534 //printf("MWindow::clean_indexes 2 %s\n", string2);
535                                 sprintf(ptr, ".toc");
536                                 remove(string2);
537                         }
538                 }
540                 total_excess--;
541         }
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);
559         twindow->start();
562 void MWindow::init_theme()
564         theme = 0;
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++)
571         {
572                 if(plugindb->values[i]->theme &&
573                         !strcasecmp(preferences->theme, plugindb->values[i]->title))
574                 {
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();
581                 }
582         }
584         if(!theme)
585         {
586                 fprintf(stderr, _("MWindow::init_theme: theme %s not found.\n"), preferences->theme);
587                 exit(1);
588         }
590 // Load images which may have been forgotten
591         theme->Theme::initialize();
592 // Load user images
593         theme->initialize();
594 // Create menus with user colors
595         theme->build_menus();
596         init_menus();
598         theme->check_used();
601 void MWindow::init_3d()
603         playback_3d = new Playback3D(this);
604         playback_3d->create_objects();
607 void MWindow::init_edl()
609         edl = new 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];
653         // Color Models
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));
684         // Interlacing Modes
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();
719 ENABLE_BUFFER
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)
737         {
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();
743         }
744         else
745         if(!preferences->use_brender && brender)
746         {
747                 brender_lock->lock("MWindow::init_brender 2");
748                 delete brender;
749                 brender = 0;
750                 session->brender_end = 0;
751                 brender_lock->unlock();
752         }
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)
769         int result = 0;
770         brender_lock->lock("MWindow::brender_available 1");
771         if(brender)
772         {
773                 if(brender->map_valid)
774                 {
775                         brender->map_lock->lock("MWindow::brender_available 2");
776                         if(position < brender->map_size &&
777                                 position >= 0)
778                         {
779 //printf("MWindow::brender_available 1 %d %d\n", position, brender->map[position]);
780                                 if(brender->map[position] == BRender::RENDERED)
781                                         result = 1;
782                         }
783                         brender->map_lock->unlock();
784                 }
785         }
786         brender_lock->unlock();
787         return result;
790 void MWindow::set_brender_start()
792         edl->session->brender_start = edl->local_session->get_selectionstart();
793         restart_brender();
794         gui->canvas->draw_overlays();
795         gui->canvas->flash();
800 int MWindow::load_filenames(ArrayList<char*> *filenames, 
801         int load_mode,
802         int update_filename,
803         char *reel_name,
804         int reel_number,
805         int overwrite_reel)
807 SET_TRACE
808         ArrayList<EDL*> new_edls;
809         ArrayList<Asset*> new_assets;
810         ArrayList<File*> new_files;
812         save_defaults();
813         gui->start_hourglass();
815 // Need to stop playback since tracking depends on the EDL not getting
816 // deleted.
817         cwindow->playback_engine->que->send_command(STOP,
818                 CHANGE_NONE, 
819                 0,
820                 0);
821         vwindow->playback_engine->que->send_command(STOP,
822                 CHANGE_NONE, 
823                 0,
824                 0);
825         cwindow->playback_engine->interrupt_playback(0);
826         vwindow->playback_engine->interrupt_playback(0);
830 // Define new_edls and new_assets to load
831         int result = 0;
832         for(int i = 0; i < filenames->total; i++)
833         {
834 // Get type of file
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
844                 if(overwrite_reel)
845                 {
846                         char source_filename[BCTEXTLEN];
847                         char index_filename[BCTEXTLEN];
848                         
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,
854                                 index_filename,
855                                 new_asset->path);
856                         remove(index_filename);
857                         new_asset->index_status = INDEX_NOTTESTED;
858                 }
859                 
860                 new_edl->create_objects();
861                 new_edl->copy_session(edl);
863                 sprintf(string, "Loading %s", new_asset->path);
864                 gui->show_message(string);
865 SET_TRACE
866                 result = new_file->open_file(preferences, new_asset, 1, 0, 0, 0);
867 SET_TRACE
869                 switch(result)
870                 {
871 // Convert media file to EDL
872                         case FILE_OK:
873 // Warn about odd image dimensions
874                                 if(new_asset->video_data &&
875                                         ((new_asset->width % 2) ||
876                                         (new_asset->height % 2)))
877                                 {
878                                         char string[BCTEXTLEN];
879                                         sprintf(string, "%s's resolution is %dx%d.\nImages with odd dimensions may not decode properly.",
880                                                 new_asset->path,
881                                                 new_asset->width,
882                                                 new_asset->height);
883                                         MainError::show_error(string);
884                                 }
887                                 if(load_mode != LOAD_RESOURCESONLY)
888                                 {
889 SET_TRACE
890                                         asset_to_edl(new_edl, new_asset);
891 SET_TRACE
892                                         new_edls.append(new_edl);
893 SET_TRACE
894                                         Garbage::delete_object(new_asset);
895                                         new_asset = 0;
896 SET_TRACE
897                                 }
898                                 else
899                                 {
900                                         new_assets.append(new_asset);
901                                 }
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)
906                                 {
907                                         set_filename("");
908 // Reset timeline position
909                                         new_edl->local_session->view_start = 0;
910                                         new_edl->local_session->track_start = 0;
911                                 }
913                                 result = 0;
914                                 break;
916 // File not found
917                         case FILE_NOT_FOUND:
918                                 sprintf(string, _("Failed to open %s"), new_asset->path);
919                                 gui->show_message(string, theme->message_error);
920                                 result = 1;
921                                 break;
923 // Unknown format
924                         case FILE_UNRECOGNIZED_CODEC:
925                         {
926 // Test index file
927                                 IndexFile indexfile(this);
928                                 result = indexfile.open_index(this, new_asset);
929                                 if(!result)
930                                 {
931                                         indexfile.close_index();
932                                 }
934 // Test existing EDLs
935                                 if(result)
936                                 {
937                                         for(int j = 0; j < new_edls.total + 1; j++)
938                                         {
939                                                 Asset *old_asset;
940                                                 if(j == new_edls.total)
941                                                 {
942                                                         if(old_asset = edl->assets->get_asset(new_asset->path))
943                                                         {
944                                                                 *new_asset = *old_asset;
945                                                                 result = 0;
946                                                         }
947                                                 }
948                                                 else
949                                                 {
950                                                         if(old_asset = new_edls.values[j]->assets->get_asset(new_asset->path))
951                                                         {
952                                                                 *new_asset = *old_asset;
953                                                                 result = 0;
954                                                         }
955                                                 }
956                                         }
957                                 }
959 // Prompt user
960                                 if(result)
961                                 {
962                                         char string[BCTEXTLEN];
963                                         FileSystem fs;
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);
986                                         save_defaults();
987                                 }
989 // Append to list
990                                 if(!result)
991                                 {
992 // Recalculate length
993                                         delete new_file;
994                                         new_file = new File;
995                                         result = new_file->open_file(preferences, new_asset, 1, 0, 0, 0);
997                                         if(load_mode != LOAD_RESOURCESONLY)
998                                         {
999                                                 asset_to_edl(new_edl, new_asset);
1000                                                 new_edls.append(new_edl);
1001                                                 Garbage::delete_object(new_asset);
1002                                                 new_asset = 0;
1003                                         }
1004                                         else
1005                                         {
1006                                                 new_assets.append(new_asset);
1007                                         }
1008                                 }
1009                                 else
1010                                 {
1011                                         result = 1;
1012                                 }
1013                                 break;
1014                         }
1016                         case FILE_IS_XML:
1017                         {
1018                                 FileXML xml_file;
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, "");
1026                                 reel_number = -1;
1028                                 if(load_mode == LOAD_REPLACE || 
1029                                         load_mode == LOAD_REPLACE_CONCATENATE)
1030                                 {
1031                                         strcpy(session->filename, filenames->values[i]);
1032                                         strcpy(new_edl->local_session->clip_title, filenames->values[i]);
1033                                         if(update_filename)
1034                                                 set_filename(new_edl->local_session->clip_title);
1035                                 }
1037                                 new_edls.append(new_edl);
1038                                 result = 0;
1039                                 break;
1040                         }
1041                 }
1043 SET_TRACE
1044                 if(result)
1045                 {
1046                         delete new_edl;
1047                         Garbage::delete_object(new_asset);
1048                         new_edl = 0;
1049                         new_asset = 0;
1050                 }
1051 SET_TRACE
1053 // Store for testing index
1054                 new_files.append(new_file);
1055 SET_TRACE
1056         }
1060         if(!result) gui->statusbar->default_message();
1069 // Paste them.
1070 // Don't back up here.
1071         if(new_edls.total)
1072         {
1073 // For pasting, clear the active region
1074                 if(load_mode == LOAD_PASTE)
1075                 {
1076                         double start = edl->local_session->get_selectionstart();
1077                         double end = edl->local_session->get_selectionend();
1078                         if(!EQUIV(start, end))
1079                                 edl->clear(start, 
1080                                         end,
1081                                         edl->session->labels_follow_edits,
1082                                         edl->session->plugins_follow_edits);
1083                 }
1085                 paste_edls(&new_edls, 
1086                         load_mode,
1087                         0,
1088                         -1,
1089                         edl->session->labels_follow_edits, 
1090                         edl->session->plugins_follow_edits);
1091         }
1098 // Add new assets to EDL and schedule assets for index building.
1099 // Used for loading resources only.
1100         if(new_assets.total)
1101         {
1102                 for(int i = 0; i < new_assets.total; i++)
1103                 {
1104                         Asset *new_asset = new_assets.values[i];
1105                         File *new_file = 0;
1106                         File *index_file = 0;
1107                         int got_it = 0;
1108                         for(int j = 0; j < new_files.total; j++)
1109                         {
1110                                 new_file = new_files.values[j];
1111                                 if(!strcmp(new_file->asset->path,
1112                                         new_asset->path))
1113                                 {
1114                                         got_it = 1;
1115                                         break;
1116                                 }
1117                         }
1119                         mainindexes->add_next_asset(got_it ? new_file : 0, 
1120                                 new_asset);
1121                         edl->assets->update(new_asset);
1123                 }
1126 // Start examining next batch of index files
1127                 mainindexes->start_build();
1128         }
1131         update_project(load_mode);
1132 SET_TRACE
1136         new_edls.remove_all_objects();
1137 SET_TRACE
1138         for(int i = 0; i < new_assets.total; i++)
1139                 Garbage::delete_object(new_assets.values[i]);
1140 SET_TRACE
1141         new_assets.remove_all();
1142 SET_TRACE
1143         new_files.remove_all_objects();
1145 SET_TRACE
1146         undo->update_undo(_("load"), LOAD_ALL, 0);
1149 SET_TRACE
1150         gui->stop_hourglass();
1151 SET_TRACE
1153         return 0;
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)
1164         {
1165                 for(int k = 0; k < track->plugin_set.total; k++)
1166                 {
1167                         PluginSet *plugin_set = track->plugin_set.values[k];
1168                         for(Plugin *plugin = (Plugin*)plugin_set->first; 
1169                         plugin; 
1170                         plugin = (Plugin*)plugin->next)
1171                         {
1172                                 if(plugin->plugin_type == PLUGIN_STANDALONE)
1173                                 {
1174                                         // ok we need to find it in plugindb
1175                                         int plugin_found = 0;
1176                                         for(int j = 0; j < plugindb->total; j++)
1177                                         {
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))
1183                                                         plugin_found = 1;
1184                                         }
1185                                         if (!plugin_found) 
1186                                         {
1187                                                 sprintf(string, 
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",
1190                                                         plugin->title, 
1191                                                         path); 
1192                                                 MainError::show_error(string);
1193                                         }
1194                                 }
1195                         }
1196                 }
1197                 for(Edit *edit = (Edit*)track->edits->first; 
1198                 edit; 
1199                 edit = (Edit*)edit->next)
1200                 {
1201                         if (edit->transition)
1202                         {
1203                                 // ok we need to find transition in plugindb
1204                                 int transition_found = 0;
1205                                 for(int j = 0; j < plugindb->total; j++)
1206                                 {
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;
1213                                 }
1214                                 if (!transition_found) 
1215                                 {
1216                                         sprintf(string, 
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, 
1220                                                 path); 
1221                                         MainError::show_error(string);
1222                                 }
1223                         }
1224                 }
1225         }
1232 void MWindow::create_objects(int want_gui, 
1233         int want_new,
1234         char *config_path)
1236         char string[BCTEXTLEN];
1237         FileSystem fs;
1238         edl = 0;
1242         init_3d();
1243         show_splash();
1245 // For some reason, init_signals must come after show_splash or the signals won't
1246 // get trapped.
1247         init_signals();
1249         init_error();
1251 SET_TRACE
1253         init_defaults(defaults, config_path);
1254 SET_TRACE
1255         init_preferences();
1256 SET_TRACE
1257         init_plugins(preferences, plugindb, splash_window);
1258         if(splash_window) splash_window->operation->update(_("Initializing GUI"));
1259 SET_TRACE
1260         init_theme();
1261 // Default project created here
1262 SET_TRACE
1263         init_edl();
1265 SET_TRACE
1266         init_awindow();
1267 SET_TRACE
1268         init_compositor();
1269 SET_TRACE
1270         init_levelwindow();
1271 SET_TRACE
1272         init_viewer();
1273 SET_TRACE
1274         init_cache();
1275 SET_TRACE
1276         init_indexes();
1277 SET_TRACE
1278         init_channeldb();
1279 SET_TRACE
1281         init_gui();
1282         init_gwindow();
1283 SET_TRACE
1284         init_render();
1285         init_brender();
1286         init_exportedl();
1287         mainprogress = new MainProgress(this, gui);
1288         undo = new MainUndo(this);
1290         plugin_guis = new ArrayList<PluginServer*>;
1292 SET_TRACE
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();
1298 SET_TRACE
1301         gui->mainmenu->load_defaults(defaults);
1302 SET_TRACE
1303         gui->mainmenu->update_toggles(0);
1304 SET_TRACE
1305         gui->patchbay->update();
1306 SET_TRACE
1307         gui->canvas->draw();
1308 SET_TRACE
1309         gui->cursor->draw(1);
1310 SET_TRACE
1311         gui->show_window();
1312         gui->raise_window();
1314         if(preferences->use_tipwindow)
1315                 init_tipwindow();
1316                 
1317 SET_TRACE
1319         hide_splash();
1320 SET_TRACE
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()
1337         if(splash_window)
1338                 delete splash_window;
1339         splash_window = 0;
1343 void MWindow::start()
1345 ENABLE_BUFFER
1346         vwindow->start();
1347         awindow->start();
1348         cwindow->start();
1349         lwindow->start();
1350         gwindow->start();
1351         Thread::start();
1352         playback_3d->start();
1355 void MWindow::run()
1357         gui->run_window();
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();
1423         save_backup();
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);
1441         gui->flush();
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();
1461         return 0;
1465 void MWindow::sync_parameters(int change_type)
1468 // Sync engines which are playing back
1469         if(cwindow->playback_engine->is_playing_back)
1470         {
1471                 if(change_type == CHANGE_PARAMS)
1472                 {
1473 // TODO: block keyframes until synchronization is done
1474                         cwindow->playback_engine->sync_parameters(edl);
1475                 }
1476                 else
1477 // Stop and restart
1478                 {
1479                         int command = cwindow->playback_engine->command->command;
1480                         cwindow->playback_engine->que->send_command(STOP,
1481                                 CHANGE_NONE, 
1482                                 0,
1483                                 0);
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,
1490                                         change_type, 
1491                                         edl,
1492                                         1,
1493                                         0);
1494                 }
1495         }
1496         else
1497         {
1498                 cwindow->playback_engine->que->send_command(CURRENT_FRAME, 
1499                                                         change_type,
1500                                                         edl,
1501                                                         1);
1502         }
1505 void MWindow::age_caches()
1507         int64_t prev_memory_usage;
1508         int64_t memory_usage;
1509         int result = 0;
1510         do
1511         {
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)
1518                 {
1519                         int target = 1;
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;
1527                         switch(target)
1528                         {
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;
1533                         }
1534                 }
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();
1540         }while(!result && 
1541                 prev_memory_usage != memory_usage && 
1542                 memory_usage > preferences->cache_size);
1545 void MWindow::show_plugin(Plugin *plugin)
1547         int done = 0;
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++)
1551         {
1552 // Pointer comparison
1553                 if(plugin_guis->values[i]->plugin == plugin)
1554                 {
1555                         plugin_guis->values[i]->raise_window();
1556                         done = 1;
1557                         break;
1558                 }
1559         }
1561 //printf("MWindow::show_plugin 1\n");
1562         if(!done)
1563         {
1564                 if(!plugin->track)
1565                 {
1566                         printf("MWindow::show_plugin track not defined.\n");
1567                 }
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)
1573                 {
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);
1578                         gui->show_gui();
1579                         plugin->show = 1;
1580                 }
1581         }
1582         plugin_gui_lock->unlock();
1583 //printf("MWindow::show_plugin 2\n");
1586 void MWindow::hide_plugin(Plugin *plugin, int lock)
1588         plugin->show = 0;
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++)
1595         {
1596                 if(plugin_guis->values[i]->plugin == plugin)
1597                 {
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
1602                         delete ptr;
1603                         return;
1604                 }
1605         }
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++)
1622         {
1623                 plugin_guis->values[i]->update_gui();
1624         }
1625         plugin_gui_lock->unlock();
1628 int MWindow::plugin_gui_open(Plugin *plugin)
1630         int result = 0;
1631         plugin_gui_lock->lock("MWindow::plugin_gui_open");
1632         for(int i = 0; i < plugin_guis->total; i++)
1633         {
1634                 if(plugin_guis->values[i]->plugin->identical_location(plugin))
1635                 {
1636                         result = 1;
1637                         break;
1638                 }
1639         }
1640         plugin_gui_lock->unlock();
1641         return result;
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++)
1648         {
1649                 if(plugin_guis->values[i]->plugin->identical_location(plugin))
1650                 {
1651                         plugin_guis->values[i]->render_gui(data);
1652                         break;
1653                 }
1654         }
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++)
1662         {
1663                 if(plugin_guis->values[i]->plugin->identical_location(plugin))
1664                 {
1665                         plugin_guis->values[i]->render_gui(data, size);
1666                         break;
1667                 }
1668         }
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++)
1677         {
1678                 int result = 0;
1679 // Get a plugin GUI
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; 
1685                         track && !result; 
1686                         track = track->next)
1687                 {
1688                         for(int j = 0; 
1689                                 j < track->plugin_set.total && !result; 
1690                                 j++)
1691                         {
1692                                 PluginSet *plugin_set = track->plugin_set.values[j];
1693                                 for(Plugin *plugin = (Plugin*)plugin_set->first; 
1694                                         plugin && !result; 
1695                                         plugin = (Plugin*)plugin->next)
1696                                 {
1697                                         if(plugin == src_plugin &&
1698                                                 !strcmp(plugin->title, src_plugingui->title)) result = 1;
1699                                 }
1700                         }
1701                 }
1704 // Doesn't exist anymore
1705                 if(!result)
1706                 {
1707                         hide_plugin(src_plugin, 0);
1708                         i--;
1709                 }
1710         }
1711         plugin_gui_lock->unlock();
1715 void MWindow::update_plugin_titles()
1717         for(int i = 0; i < plugin_guis->total; i++)
1718         {
1719                 plugin_guis->values[i]->update_title();
1720         }
1723 int MWindow::asset_to_edl(EDL *new_edl, 
1724         Asset *new_asset, 
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)
1734         {
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;
1739         }
1740         else
1741                 new_edl->session->video_tracks = 0;
1748         if(new_asset->audio_data)
1749         {
1750                 new_edl->session->audio_tracks = new_asset->channels;
1751 //              new_edl->session->sample_rate = new_asset->sample_rate;
1752         }
1753         else
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)
1763 //      {
1764 //              for(Track *current = new_edl->tracks->first;
1765 //                      current;
1766 //                      current = NEXT)
1767 //              {
1768 //                      if(current->data_type == TRACK_VIDEO) current->draw = 0;
1769 //              }
1770 //      }
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];
1783         FileSystem fs;
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);
1790 //      new_edl->dump();
1791         return 0;
1794 // Reset everything after a load.
1795 void MWindow::update_project(int load_mode)
1797         restart_brender();
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)
1808         {
1809                 vwindow->change_source();
1810         }
1811         else
1812         {
1813                 vwindow->update(1);
1814         }
1816         cwindow->gui->slider->set_position();
1817         cwindow->gui->timebar->update(1, 1);
1818         cwindow->playback_engine->que->send_command(CURRENT_FRAME, 
1819                 CHANGE_ALL,
1820                 edl,
1821                 1);
1823         awindow->gui->lock_window("MWindow::update_project");
1824         awindow->gui->update_assets();
1825         awindow->gui->flush();
1826         awindow->gui->unlock_window();
1827         gui->flush();
1831 void MWindow::rebuild_indices()
1833         char source_filename[BCTEXTLEN], index_filename[BCTEXTLEN];
1835         for(int i = 0; i < session->drag_assets->total; i++)
1836         {
1837 //printf("MWindow::rebuild_indices 1 %s\n", session->drag_assets->values[i]->path);
1838 // Erase file
1839                 IndexFile::get_index_filename(source_filename, 
1840                         preferences->index_directory,
1841                         index_filename, 
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]);
1847         }
1848         mainindexes->start_build();
1852 void MWindow::save_backup()
1854         FileXML file;
1855         edl->set_project_path(session->filename);
1856         edl->save_xml(plugindb, 
1857                 &file, 
1858                 BACKUP_PATH,
1859                 0,
1860                 0);
1861         file.terminate_string();
1862         char path[BCTEXTLEN];
1863         FileSystem fs;
1864         strcpy(path, BACKUP_PATH);
1865         fs.complete_path(path);
1867         if(file.write_to_file(path))
1868         {
1869                 char string2[256];
1870                 sprintf(string2, _("Couldn't open %s for writing."), BACKUP_PATH);
1871                 gui->show_message(string2);
1872         }
1876 int MWindow::create_aspect_ratio(float &w, float &h, int width, int height)
1878         int denominator;
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; 
1885                 denominator++)
1886                 ;
1888         w = denominator * width / height;
1889         h = denominator;
1890         return 0;
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++)
1930         {
1931                 Asset *asset = session->drag_assets->values[i];
1932                 remove_asset_from_caches(asset);
1933         }
1935 // Remove from VWindow.
1936         for(int i = 0; i < session->drag_clips->total; i++)
1937         {
1938                 if(session->drag_clips->values[i] == vwindow->get_edl())
1939                 {
1940                         vwindow->gui->lock_window("MWindow::remove_assets_from_project 1");
1941                         vwindow->remove_source();
1942                         vwindow->gui->unlock_window();
1943                 }
1944         }
1945         
1946         for(int i = 0; i < session->drag_assets->total; i++)
1947         {
1948                 if(session->drag_assets->values[i] == vwindow->get_asset())
1949                 {
1950                         vwindow->gui->lock_window("MWindow::remove_assets_from_project 2");
1951                         vwindow->remove_source();
1952                         vwindow->gui->unlock_window();
1953                 }
1954         }
1955         
1956         edl->remove_from_project(session->drag_assets);
1957         edl->remove_from_project(session->drag_clips);
1958         save_backup();
1959         if(push_undo) undo->update_undo(_("remove assets"), LOAD_ALL);
1960         restart_brender();
1962         gui->lock_window("MWindow::remove_assets_from_project 3");
1963         gui->update(1,
1964                 1,
1965                 1,
1966                 1,
1967                 0, 
1968                 1,
1969                 0);
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()
1983 // Remove from disk
1984         for(int i = 0; i < session->drag_assets->total; i++)
1985         {
1986                 remove(session->drag_assets->values[i]->path);
1987         }
1989         remove_assets_from_project(1);
1992 void MWindow::dump_plugins()
1994         for(int i = 0; i < plugindb->total; i++)
1995         {
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);
2003         }
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);
2037         defaults->save();
2038         return 0;
2041 int MWindow::run_script(FileXML *script)
2043         int result = 0, result2 = 0;
2044         while(!result && !result2)
2045         {
2046                 result = script->read_tag();
2047                 if(!result)
2048                 {
2049                         if(script->tag.title_is("new_project"))
2050                         {
2051 // Run new in immediate mode.
2052 //                              gui->mainmenu->new_project->run_script(script);
2053                         }
2054                         else
2055                         if(script->tag.title_is("record"))
2056                         {
2057 // Run record as a thread.  It is a terminal command.
2058                                 ;
2059 // Will read the complete scipt file without letting record read it if not
2060 // terminated.
2061                                 result2 = 1;
2062                         }
2063                         else
2064                         {
2065                                 printf("MWindow::run_script: Unrecognized command: %s\n",script->tag.get_title() );
2066                         }
2067                 }
2068         }
2069         return result2;
2072 // ================================= synchronization
2075 int MWindow::interrupt_indexes()
2077         mainindexes->interrupt_build();
2078         return 0; 
2083 void MWindow::next_time_format()
2085         switch(edl->session->time_format)
2086         {
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;
2094         }
2096         time_format_common();
2099 void MWindow::prev_time_format()
2101         switch(edl->session->time_format)
2102         {
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;
2110         }
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);
2122         gui->flush();
2123         gui->unlock_window();
2127 int MWindow::set_filename(char *filename)
2129         strcpy(session->filename, filename);
2130         if(gui)
2131         {
2132                 if(filename[0] == 0)
2133                 {
2134                         gui->set_title(PROGRAM_NAME);
2135                 }
2136                 else
2137                 {
2138                         FileSystem dir;
2139                         char string[BCTEXTLEN], string2[BCTEXTLEN];
2140                         dir.extract_name(string, filename);
2141                         sprintf(string2, PROGRAM_NAME ": %s", string);
2142                         gui->set_title(string2);
2143                 }
2144         }
2145         return 0; 
2155 int MWindow::set_loop_boundaries()
2157         double start = edl->local_session->get_selectionstart();
2158         double end = edl->local_session->get_selectionend();
2159         
2160         if(start != 
2161                 end) 
2162         {
2163                 ;
2164         }
2165         else
2166         if(edl->tracks->total_length())
2167         {
2168                 start = 0;
2169                 end = edl->tracks->total_length();
2170         }
2171         else
2172         {
2173                 start = end = 0;
2174         }
2176         if(edl->local_session->loop_playback && start != end)
2177         {
2178                 edl->local_session->loop_start = start;
2179                 edl->local_session->loop_end = end;
2180         }
2181         return 0; 
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();
2207         return 0;