r870: Merge 2.1:
[cinelerra_cv.git] / cinelerra / mwindow.C
blobbb40d76fe4257e5d496dc132420a70dada9f876a
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 "removethread.h"
60 #include "render.h"
61 #include "samplescroll.h"
62 #include "sighandler.h"
63 #include "splashgui.h"
64 #include "statusbar.h"
65 #include "theme.h"
66 #include "threadloader.h"
67 #include "timebar.h"
68 #include "tipwindow.h"
69 #include "trackcanvas.h"
70 #include "track.h"
71 #include "tracking.h"
72 #include "trackscroll.h"
73 #include "tracks.h"
74 #include "transition.h"
75 #include "transportque.h"
76 #include "vframe.h"
77 #include "videodevice.inc"
78 #include "videowindow.h"
79 #include "vplayback.h"
80 #include "vwindowgui.h"
81 #include "vwindow.h"
82 #include "wavecache.h"
83 #include "zoombar.h"
84 #include "exportedl.h"
86 #include <string.h>
90 extern "C"
96 // Hack for libdv to remove glib dependancy
98 // void
99 // g_log (const char    *log_domain,
100 //        int  log_level,
101 //        const char    *format,
102 //        ...)
103 // {
104 // }
105 // 
106 // void
107 // g_logv (const char    *log_domain,
108 //        int  log_level,
109 //        const char    *format,
110 //        ...)
111 // {
112 // }
113 // 
116 // Hack for XFree86 4.1.0
118 int atexit(void (*function)(void))
120         return 0;
129 MWindow::MWindow()
130  : Thread(1, 0, 0)
132         plugin_gui_lock = new Mutex("MWindow::plugin_gui_lock");
133         brender_lock = new Mutex("MWindow::brender_lock");
134         brender = 0;
135         session = 0;
136         channeldb_buz = new ChannelDB;
137         channeldb_v4l2jpeg = new ChannelDB;
138         dvb_input = 0;
139         dvb_input_lock = new Mutex("MWindow::dvb_input_lock");
142 MWindow::~MWindow()
144         brender_lock->lock("MWindow::~MWindow");
145         if(brender) delete brender;
146         brender = 0;
147         brender_lock->unlock();
148         delete brender_lock;
150         delete mainindexes;
152 SET_TRACE
153         clean_indexes();
154 SET_TRACE
156         save_defaults();
157 SET_TRACE
158 // Give up and go to a movie
159         exit(0);
161 SET_TRACE
162         delete mainprogress;
163         delete audio_cache;             // delete the cache after the assets
164         delete video_cache;             // delete the cache after the assets
165         delete frame_cache;
166         if(gui) delete gui;
167         delete undo;
168         delete preferences;
169         delete defaults;
170         delete render;
171 //      delete renderlist;
172         delete awindow;
173         delete vwindow;
174         delete cwindow;
175         delete lwindow;
176         plugin_guis->remove_all_objects();
177         delete plugin_guis;
178         delete plugin_gui_lock;
181 void MWindow::init_error()
183         new MainError(this);
186 void MWindow::create_defaults_path(char *string)
188 // set the .bcast path
189         FileSystem fs;
191         sprintf(string, "%s", BCASTDIR);
192         fs.complete_path(string);
193         if(!fs.is_dir(string)) 
194         {
195                 fs.create_dir(string); 
196         }
198 // load the defaults
199         strcat(string, "Cinelerra_rc");
202 void MWindow::init_defaults(BC_Hash* &defaults, char *config_path)
204         char path[BCTEXTLEN];
205 // Use user supplied path
206         if(config_path[0])
207         {
208                 strcpy(path, config_path);
209         }
210         else
211         {
212                 create_defaults_path(path);
213         }
215         defaults = new BC_Hash(path);
216         defaults->load();
219 void MWindow::init_plugin_path(Preferences *preferences, 
220         ArrayList<PluginServer*>* &plugindb,
221         FileSystem *fs,
222         SplashGUI *splash_window,
223         int *counter)
225         int result = 0;
226         PluginServer *newplugin;
228         if(!result)
229         {
230                 for(int i = 0; i < fs->dir_list.total; i++)
231                 {
232                         char path[BCTEXTLEN];
233                         strcpy(path, fs->dir_list.values[i]->path);
235 // File is a directory
236                         if(fs->is_dir(path))
237                         {
238                                 continue;
239                         }
240                         else
241                         {
242 // Try to query the plugin
243                                 fs->complete_path(path);
244 //printf("MWindow::init_plugin_path %s\n", path);
245                                 PluginServer *new_plugin = new PluginServer(path);
246                                 int result = new_plugin->open_plugin(1, preferences, 0, 0, -1);
248                                 if(!result)
249                                 {
250                                         plugindb->append(new_plugin);
251                                         new_plugin->close_plugin();
252                                         if(splash_window)
253                                                 splash_window->operation->update(_(new_plugin->title));
254                                 }
255                                 else
256                                 if(result == PLUGINSERVER_IS_LAD)
257                                 {
258                                         delete new_plugin;
259 // Open LAD subplugins
260                                         int id = 0;
261                                         do
262                                         {
263                                                 new_plugin = new PluginServer(path);
264                                                 result = new_plugin->open_plugin(1,
265                                                         preferences,
266                                                         0,
267                                                         0,
268                                                         id);
269                                                 id++;
270                                                 if(!result)
271                                                 {
272                                                         plugindb->append(new_plugin);
273                                                         new_plugin->close_plugin();
274                                                         if(splash_window)
275                                                                 splash_window->operation->update(_(new_plugin->title));
276                                                         else
277                                                         {
278                                                         }
279                                                 }
280                                         }while(!result);
281                                 }
282                                 else
283                                 {
284 // Plugin failed to open
285                                         delete new_plugin;
286                                 }
287                         }
289                         if(splash_window) splash_window->progress->update((*counter)++);
290                 }
291         }
294 void MWindow::init_plugins(Preferences *preferences, 
295         ArrayList<PluginServer*>* &plugindb,
296         SplashGUI *splash_window)
298         plugindb = new ArrayList<PluginServer*>;
302         FileSystem cinelerra_fs;
303         ArrayList<FileSystem*> lad_fs;
304         int result = 0;
306 // Get directories
307         cinelerra_fs.set_filter("[*.plugin][*.so]");
308         result = cinelerra_fs.update(preferences->global_plugin_dir);
310         if(result)
311         {
312                 fprintf(stderr, 
313                         _("MWindow::init_plugins: couldn't open %s directory\n"),
314                         preferences->global_plugin_dir);
315         }
317 // Parse LAD environment variable
318         char *env = getenv("LADSPA_PATH");
319         if(env)
320         {
321                 char string[BCTEXTLEN];
322                 char *ptr1 = env;
323                 while(ptr1)
324                 {
325                         char *ptr = strchr(ptr1, ':');
326                         char *end;
327                         if(ptr)
328                         {
329                                 end = ptr;
330                         }
331                         else
332                         {
333                                 end = env + strlen(env);
334                         }
336                         if(end > ptr1)
337                         {
338                                 int len = end - ptr1;
339                                 memcpy(string, ptr1, len);
340                                 string[len] = 0;
343                                 FileSystem *fs = new FileSystem;
344                                 lad_fs.append(fs);
345                                 fs->set_filter("*.so");
346                                 result = fs->update(string);
348                                 if(result)
349                                 {
350                                         fprintf(stderr, 
351                                                 _("MWindow::init_plugins: couldn't open %s directory\n"),
352                                                 string);
353                                 }
354                         }
356                         if(ptr)
357                                 ptr1 = ptr + 1;
358                         else
359                                 ptr1 = ptr;
360                 };
361         }
363         int total = cinelerra_fs.total_files();
364         int counter = 0;
365         for(int i = 0; i < lad_fs.total; i++)
366                 total += lad_fs.values[i]->total_files();
367         if(splash_window) splash_window->progress->update_length(total);
370 // Cinelerra
371 #ifndef DO_STATIC
372         init_plugin_path(preferences,
373                 plugindb,
374                 &cinelerra_fs,
375                 splash_window,
376                 &counter);
377 #else
378 // Call automatically generated routine to get plugins
379 #endif
381 // LAD
382         for(int i = 0; i < lad_fs.total; i++)
383                 init_plugin_path(preferences,
384                         plugindb,
385                         lad_fs.values[i],
386                         splash_window,
387                         &counter);
389         lad_fs.remove_all_objects();
392 void MWindow::delete_plugins()
394         for(int i = 0; i < plugindb->total; i++)
395         {
396                 delete plugindb->values[i];
397         }
398         delete plugindb;
401 void MWindow::create_plugindb(int do_audio, 
402                 int do_video, 
403                 int is_realtime, 
404                 int is_transition,
405                 int is_theme,
406                 ArrayList<PluginServer*> &plugindb)
408 // Get plugins
409         for(int i = 0; i < this->plugindb->total; i++)
410         {
411                 PluginServer *current = this->plugindb->values[i];
413                 if(current->audio == do_audio &&
414                         current->video == do_video &&
415                         (current->realtime == is_realtime || is_realtime < 0) &&
416                         current->transition == is_transition &&
417                         current->theme == is_theme)
418                         plugindb.append(current);
419         }
421 // Alphabetize list by title
422         int done = 0;
423         while(!done)
424         {
425                 done = 1;
426                 
427                 for(int i = 0; i < plugindb.total - 1; i++)
428                 {
429                         PluginServer *value1 = plugindb.values[i];
430                         PluginServer *value2 = plugindb.values[i + 1];
431                         if(strcmp(_(value1->title), _(value2->title)) > 0)
432                         {
433                                 done = 0;
434                                 plugindb.values[i] = value2;
435                                 plugindb.values[i + 1] = value1;
436                         }
437                 }
438         }
441 PluginServer* MWindow::scan_plugindb(char *title,
442                 int data_type)
444         if(data_type < 0)
445         {
446                 printf("MWindow::scan_plugindb data_type < 0\n");
447                 return 0;
448         }
450         for(int i = 0; i < plugindb->total; i++)
451         {
452                 PluginServer *server = plugindb->values[i];
453                 if(!strcasecmp(server->title, title) &&
454                 ((data_type == TRACK_AUDIO && server->audio) ||
455                 (data_type == TRACK_VIDEO && server->video))) 
456                         return plugindb->values[i];
457         }
458         return 0;
461 void MWindow::init_preferences()
463         preferences = new Preferences;
464         preferences->load_defaults(defaults);
465         session = new MainSession(this);
466         session->load_defaults(defaults);
469 void MWindow::clean_indexes()
471         FileSystem fs;
472         int total_excess;
473         long oldest;
474         int oldest_item = -1;
475         int result;
476         char string[BCTEXTLEN];
477         char string2[BCTEXTLEN];
479 // Delete extra indexes
480         fs.set_filter("*.idx");
481         fs.complete_path(preferences->index_directory);
482         fs.update(preferences->index_directory);
483 //printf("MWindow::clean_indexes 1 %d\n", fs.dir_list.total);
485 // Eliminate directories
486         result = 1;
487         while(result)
488         {
489                 result = 0;
490                 for(int i = 0; i < fs.dir_list.total && !result; i++)
491                 {
492                         fs.join_names(string, preferences->index_directory, fs.dir_list.values[i]->name);
493                         if(fs.is_dir(string))
494                         {
495                                 delete fs.dir_list.values[i];
496                                 fs.dir_list.remove_number(i);
497                                 result = 1;
498                         }
499                 }
500         }
501         total_excess = fs.dir_list.total - preferences->index_count;
503 //printf("MWindow::clean_indexes 2 %d\n", fs.dir_list.total);
504         while(total_excess > 0)
505         {
506 // Get oldest
507                 for(int i = 0; i < fs.dir_list.total; i++)
508                 {
509                         fs.join_names(string, preferences->index_directory, fs.dir_list.values[i]->name);
511                         if(i == 0 || fs.get_date(string) <= oldest)
512                         {
513                                 oldest = fs.get_date(string);
514                                 oldest_item = i;
515                         }
516                 }
518                 if(oldest_item >= 0)
519                 {
520 // Remove index file
521                         fs.join_names(string, 
522                                 preferences->index_directory, 
523                                 fs.dir_list.values[oldest_item]->name);
524 //printf("MWindow::clean_indexes 1 %s\n", string);
525                         if(remove(string))
526                                 perror("delete_indexes");
527                         delete fs.dir_list.values[oldest_item];
528                         fs.dir_list.remove_number(oldest_item);
530 // Remove table of contents if it exists
531                         strcpy(string2, string);
532                         char *ptr = strrchr(string2, '.');
533                         if(ptr)
534                         {
535 //printf("MWindow::clean_indexes 2 %s\n", string2);
536                                 sprintf(ptr, ".toc");
537                                 remove(string2);
538                         }
539                 }
541                 total_excess--;
542         }
545 void MWindow::init_awindow()
547         awindow = new AWindow(this);
548         awindow->create_objects();
551 void MWindow::init_gwindow()
553         gwindow = new GWindow(this);
554         gwindow->create_objects();
557 void MWindow::init_tipwindow()
559         twindow = new TipWindow(this);
560         twindow->start();
563 void MWindow::init_theme()
565         theme = 0;
567 // Replace blond theme with SUV since it doesn't work
568         if(!strcasecmp(preferences->theme, "Blond"))
569                 strcpy(preferences->theme, DEFAULT_THEME);
571         for(int i = 0; i < plugindb->total; i++)
572         {
573                 if(plugindb->values[i]->theme &&
574                         !strcasecmp(preferences->theme, plugindb->values[i]->title))
575                 {
576                         PluginServer plugin = *plugindb->values[i];
577                         plugin.open_plugin(0, preferences, 0, 0, -1);
578                         theme = plugin.new_theme();
579                         theme->mwindow = this;
580                         strcpy(theme->path, plugin.path);
581                         plugin.close_plugin();
582                 }
583         }
585         if(!theme)
586         {
587                 fprintf(stderr, _("MWindow::init_theme: theme %s not found.\n"), preferences->theme);
588                 exit(1);
589         }
591 // Load images which may have been forgotten
592         theme->Theme::initialize();
593 // Load user images
594         theme->initialize();
595 // Create menus with user colors
596         theme->build_menus();
597         init_menus();
599         theme->check_used();
602 void MWindow::init_3d()
604         playback_3d = new Playback3D(this);
605         playback_3d->create_objects();
608 void MWindow::init_edl()
610         edl = new EDL;
611         edl->create_objects();
612     edl->load_defaults(defaults);
613         edl->create_default_tracks();
614         edl->tracks->update_y_pixels(theme);
617 void MWindow::init_compositor()
619         cwindow = new CWindow(this);
620     cwindow->create_objects();
623 void MWindow::init_levelwindow()
625         lwindow = new LevelWindow(this);
626         lwindow->create_objects();
629 void MWindow::init_viewer()
631         vwindow = new VWindow(this);
632         vwindow->load_defaults();
633         vwindow->create_objects();
636 void MWindow::init_cache()
638         audio_cache = new CICache(preferences, plugindb);
639         video_cache = new CICache(preferences, plugindb);
640         frame_cache = new FrameCache;
641         wave_cache = new WaveCache;
644 void MWindow::init_channeldb()
646         channeldb_buz->load("channeldb_buz");
647         channeldb_v4l2jpeg->load("channeldb_v4l2jpeg");
650 void MWindow::init_menus()
652         char string[BCTEXTLEN];
654         // Color Models
655         cmodel_to_text(string, BC_RGB888);
656         colormodels.append(new ColormodelItem(string, BC_RGB888));
657         cmodel_to_text(string, BC_RGBA8888);
658         colormodels.append(new ColormodelItem(string, BC_RGBA8888));
659 //      cmodel_to_text(string, BC_RGB161616);
660 //      colormodels.append(new ColormodelItem(string, BC_RGB161616));
661 //      cmodel_to_text(string, BC_RGBA16161616);
662 //      colormodels.append(new ColormodelItem(string, BC_RGBA16161616));
663         cmodel_to_text(string, BC_RGB_FLOAT);
664         colormodels.append(new ColormodelItem(string, BC_RGB_FLOAT));
665         cmodel_to_text(string, BC_RGBA_FLOAT);
666         colormodels.append(new ColormodelItem(string, BC_RGBA_FLOAT));
667         cmodel_to_text(string, BC_YUV888);
668         colormodels.append(new ColormodelItem(string, BC_YUV888));
669         cmodel_to_text(string, BC_YUVA8888);
670         colormodels.append(new ColormodelItem(string, BC_YUVA8888));
671 //      cmodel_to_text(string, BC_YUV161616);
672 //      colormodels.append(new ColormodelItem(string, BC_YUV161616));
673 //      cmodel_to_text(string, BC_YUVA16161616);
674 //      colormodels.append(new ColormodelItem(string, BC_YUVA16161616));
676 #define ILACEPROJECTMODELISTADD(x) ilacemode_to_text(string, x); \
677                            interlace_project_modes.append(new InterlacemodeItem(string, x));
679 #define ILACEASSETMODELISTADD(x) ilacemode_to_text(string, x); \
680                            interlace_asset_modes.append(new InterlacemodeItem(string, x));
682 #define ILACEFIXMETHODLISTADD(x) ilacefixmethod_to_text(string, x); \
683                            interlace_asset_fixmethods.append(new InterlacefixmethodItem(string, x));
685         // Interlacing Modes
686         ILACEASSETMODELISTADD(BC_ILACE_MODE_UNDETECTED); // Not included in the list for the project options.
688         ILACEASSETMODELISTADD(BC_ILACE_MODE_TOP_FIRST);
689         ILACEPROJECTMODELISTADD(BC_ILACE_MODE_TOP_FIRST);
691         ILACEASSETMODELISTADD(BC_ILACE_MODE_BOTTOM_FIRST);
692         ILACEPROJECTMODELISTADD(BC_ILACE_MODE_BOTTOM_FIRST);
694         ILACEASSETMODELISTADD(BC_ILACE_MODE_NOTINTERLACED);
695         ILACEPROJECTMODELISTADD(BC_ILACE_MODE_NOTINTERLACED);
697         // Interlacing Fixing Methods
698         ILACEFIXMETHODLISTADD(BC_ILACE_FIXMETHOD_NONE);
699         ILACEFIXMETHODLISTADD(BC_ILACE_FIXMETHOD_UPONE);
700         ILACEFIXMETHODLISTADD(BC_ILACE_FIXMETHOD_DOWNONE);
703 void MWindow::init_indexes()
705         mainindexes = new MainIndexes(this);
706         mainindexes->start_loop();
709 void MWindow::init_gui()
711         gui = new MWindowGUI(this);
712         gui->create_objects();
713         gui->load_defaults(defaults);
716 void MWindow::init_signals()
718         sighandler = new SigHandler;
719         sighandler->initialize();
720 ENABLE_BUFFER
723 void MWindow::init_render()
725         render = new Render(this);
726 //      renderlist = new Render(this);
727         batch_render = new BatchRenderThread(this);
730 void MWindow::init_exportedl()
732         exportedl = new ExportEDL(this);
735 void MWindow::init_brender()
737         if(preferences->use_brender && !brender)
738         {
739                 brender_lock->lock("MWindow::init_brender 1");
740                 brender = new BRender(this);
741                 brender->initialize();
742                 session->brender_end = 0;
743                 brender_lock->unlock();
744         }
745         else
746         if(!preferences->use_brender && brender)
747         {
748                 brender_lock->lock("MWindow::init_brender 2");
749                 delete brender;
750                 brender = 0;
751                 session->brender_end = 0;
752                 brender_lock->unlock();
753         }
754         if(brender) brender->restart(edl);
757 void MWindow::restart_brender()
759 //printf("MWindow::restart_brender 1\n");
760         if(brender) brender->restart(edl);
763 void MWindow::stop_brender()
765         if(brender) brender->stop();
768 int MWindow::brender_available(int position)
770         int result = 0;
771         brender_lock->lock("MWindow::brender_available 1");
772         if(brender)
773         {
774                 if(brender->map_valid)
775                 {
776                         brender->map_lock->lock("MWindow::brender_available 2");
777                         if(position < brender->map_size &&
778                                 position >= 0)
779                         {
780 //printf("MWindow::brender_available 1 %d %d\n", position, brender->map[position]);
781                                 if(brender->map[position] == BRender::RENDERED)
782                                         result = 1;
783                         }
784                         brender->map_lock->unlock();
785                 }
786         }
787         brender_lock->unlock();
788         return result;
791 void MWindow::set_brender_start()
793         edl->session->brender_start = edl->local_session->get_selectionstart();
794         restart_brender();
795         gui->canvas->draw_overlays();
796         gui->canvas->flash();
801 int MWindow::load_filenames(ArrayList<char*> *filenames, 
802         int load_mode,
803         int update_filename,
804         char *reel_name,
805         int reel_number,
806         int overwrite_reel)
808 SET_TRACE
809         ArrayList<EDL*> new_edls;
810         ArrayList<Asset*> new_assets;
811         ArrayList<File*> new_files;
813         save_defaults();
814         gui->start_hourglass();
816 // Need to stop playback since tracking depends on the EDL not getting
817 // deleted.
818         cwindow->playback_engine->que->send_command(STOP,
819                 CHANGE_NONE, 
820                 0,
821                 0);
822         vwindow->playback_engine->que->send_command(STOP,
823                 CHANGE_NONE, 
824                 0,
825                 0);
826         cwindow->playback_engine->interrupt_playback(0);
827         vwindow->playback_engine->interrupt_playback(0);
831 // Define new_edls and new_assets to load
832         int result = 0;
833         for(int i = 0; i < filenames->total; i++)
834         {
835 // Get type of file
836                 File *new_file = new File;
837                 Asset *new_asset = new Asset(filenames->values[i]);
838                 EDL *new_edl = new EDL;
839                 char string[BCTEXTLEN];
841 // Set reel name and number for the asset
842 // If the user wants to overwrite the last used reel number for the clip,
843 // we have to rebuild the index for the file
845                 if(overwrite_reel)
846                 {
847                         char source_filename[BCTEXTLEN];
848                         char index_filename[BCTEXTLEN];
849                         
850                         strcpy(new_asset->reel_name, reel_name);
851                         new_asset->reel_number = reel_number;
853                         IndexFile::get_index_filename(source_filename,
854                                 preferences->index_directory,
855                                 index_filename,
856                                 new_asset->path);
857                         remove(index_filename);
858                         new_asset->index_status = INDEX_NOTTESTED;
859                 }
860                 
861                 new_edl->create_objects();
862                 new_edl->copy_session(edl);
864                 sprintf(string, "Loading %s", new_asset->path);
865                 gui->show_message(string);
866 SET_TRACE
867                 result = new_file->open_file(preferences, new_asset, 1, 0, 0, 0);
868 SET_TRACE
870                 switch(result)
871                 {
872 // Convert media file to EDL
873                         case FILE_OK:
874 // Warn about odd image dimensions
875                                 if(new_asset->video_data &&
876                                         ((new_asset->width % 2) ||
877                                         (new_asset->height % 2)))
878                                 {
879                                         char string[BCTEXTLEN];
880                                         sprintf(string, "%s's resolution is %dx%d.\nImages with odd dimensions may not decode properly.",
881                                                 new_asset->path,
882                                                 new_asset->width,
883                                                 new_asset->height);
884                                         MainError::show_error(string);
885                                 }
888                                 if(load_mode != LOAD_RESOURCESONLY)
889                                 {
890 SET_TRACE
891                                         asset_to_edl(new_edl, new_asset);
892 SET_TRACE
893                                         new_edls.append(new_edl);
894 SET_TRACE
895                                         Garbage::delete_object(new_asset);
896                                         new_asset = 0;
897 SET_TRACE
898                                 }
899                                 else
900                                 {
901                                         new_assets.append(new_asset);
902                                 }
904 // Set filename to nothing for assets since save EDL would overwrite them.
905                                 if(load_mode == LOAD_REPLACE || 
906                                         load_mode == LOAD_REPLACE_CONCATENATE)
907                                 {
908                                         set_filename("");
909 // Reset timeline position
910                                         new_edl->local_session->view_start = 0;
911                                         new_edl->local_session->track_start = 0;
912                                 }
914                                 result = 0;
915                                 break;
917 // File not found
918                         case FILE_NOT_FOUND:
919                                 sprintf(string, _("Failed to open %s"), new_asset->path);
920                                 gui->show_message(string, theme->message_error);
921                                 result = 1;
922                                 break;
924 // Unknown format
925                         case FILE_UNRECOGNIZED_CODEC:
926                         {
927 // Test index file
928                                 IndexFile indexfile(this);
929                                 result = indexfile.open_index(this, new_asset);
930                                 if(!result)
931                                 {
932                                         indexfile.close_index();
933                                 }
935 // Test existing EDLs
936                                 if(result)
937                                 {
938                                         for(int j = 0; j < new_edls.total + 1; j++)
939                                         {
940                                                 Asset *old_asset;
941                                                 if(j == new_edls.total)
942                                                 {
943                                                         if(old_asset = edl->assets->get_asset(new_asset->path))
944                                                         {
945                                                                 *new_asset = *old_asset;
946                                                                 result = 0;
947                                                         }
948                                                 }
949                                                 else
950                                                 {
951                                                         if(old_asset = new_edls.values[j]->assets->get_asset(new_asset->path))
952                                                         {
953                                                                 *new_asset = *old_asset;
954                                                                 result = 0;
955                                                         }
956                                                 }
957                                         }
958                                 }
960 // Prompt user
961                                 if(result)
962                                 {
963                                         char string[BCTEXTLEN];
964                                         FileSystem fs;
965                                         fs.extract_name(string, new_asset->path);
967                                         strcat(string, _("'s format couldn't be determined."));
968                                         new_asset->audio_data = 1;
969                                         new_asset->format = FILE_PCM;
970                                         new_asset->channels = defaults->get("AUDIO_CHANNELS", 2);
971                                         new_asset->sample_rate = defaults->get("SAMPLE_RATE", 44100);
972                                         new_asset->bits = defaults->get("AUDIO_BITS", 16);
973                                         new_asset->byte_order = defaults->get("BYTE_ORDER", 1);
974                                         new_asset->signed_ = defaults->get("SIGNED_", 1);
975                                         new_asset->header = defaults->get("HEADER", 0);
977                                         FileFormat fwindow(this);
978                                         fwindow.create_objects(new_asset, string);
979                                         result = fwindow.run_window();
981                                         defaults->update("AUDIO_CHANNELS", new_asset->channels);
982                                         defaults->update("SAMPLE_RATE", new_asset->sample_rate);
983                                         defaults->update("AUDIO_BITS", new_asset->bits);
984                                         defaults->update("BYTE_ORDER", new_asset->byte_order);
985                                         defaults->update("SIGNED_", new_asset->signed_);
986                                         defaults->update("HEADER", new_asset->header);
987                                         save_defaults();
988                                 }
990 // Append to list
991                                 if(!result)
992                                 {
993 // Recalculate length
994                                         delete new_file;
995                                         new_file = new File;
996                                         result = new_file->open_file(preferences, new_asset, 1, 0, 0, 0);
998                                         if(load_mode != LOAD_RESOURCESONLY)
999                                         {
1000                                                 asset_to_edl(new_edl, new_asset);
1001                                                 new_edls.append(new_edl);
1002                                                 Garbage::delete_object(new_asset);
1003                                                 new_asset = 0;
1004                                         }
1005                                         else
1006                                         {
1007                                                 new_assets.append(new_asset);
1008                                         }
1009                                 }
1010                                 else
1011                                 {
1012                                         result = 1;
1013                                 }
1014                                 break;
1015                         }
1017                         case FILE_IS_XML:
1018                         {
1019                                 FileXML xml_file;
1020                                 xml_file.read_from_file(filenames->values[i]);
1021 // Load EDL for pasting
1022                                 new_edl->load_xml(plugindb, &xml_file, LOAD_ALL);
1023                                 test_plugins(new_edl, filenames->values[i]);
1025 // We don't want a valid reel name/number for projects
1026                                 strcpy(new_asset->reel_name, "");
1027                                 reel_number = -1;
1029                                 if(load_mode == LOAD_REPLACE || 
1030                                         load_mode == LOAD_REPLACE_CONCATENATE)
1031                                 {
1032                                         strcpy(session->filename, filenames->values[i]);
1033                                         strcpy(new_edl->local_session->clip_title, filenames->values[i]);
1034                                         if(update_filename)
1035                                                 set_filename(new_edl->local_session->clip_title);
1036                                 }
1038                                 new_edls.append(new_edl);
1039                                 result = 0;
1040                                 break;
1041                         }
1042                 }
1044 SET_TRACE
1045                 if(result)
1046                 {
1047                         delete new_edl;
1048                         Garbage::delete_object(new_asset);
1049                         new_edl = 0;
1050                         new_asset = 0;
1051                 }
1052 SET_TRACE
1054 // Store for testing index
1055                 new_files.append(new_file);
1056 SET_TRACE
1057         }
1061         if(!result) gui->statusbar->default_message();
1070 // Paste them.
1071 // Don't back up here.
1072         if(new_edls.total)
1073         {
1074 // For pasting, clear the active region
1075                 if(load_mode == LOAD_PASTE)
1076                 {
1077                         double start = edl->local_session->get_selectionstart();
1078                         double end = edl->local_session->get_selectionend();
1079                         if(!EQUIV(start, end))
1080                                 edl->clear(start, 
1081                                         end,
1082                                         edl->session->labels_follow_edits,
1083                                         edl->session->plugins_follow_edits);
1084                 }
1086                 paste_edls(&new_edls, 
1087                         load_mode,
1088                         0,
1089                         -1,
1090                         edl->session->labels_follow_edits, 
1091                         edl->session->plugins_follow_edits);
1092         }
1099 // Add new assets to EDL and schedule assets for index building.
1100 // Used for loading resources only.
1101         if(new_assets.total)
1102         {
1103                 for(int i = 0; i < new_assets.total; i++)
1104                 {
1105                         Asset *new_asset = new_assets.values[i];
1106                         File *new_file = 0;
1107                         File *index_file = 0;
1108                         int got_it = 0;
1109                         for(int j = 0; j < new_files.total; j++)
1110                         {
1111                                 new_file = new_files.values[j];
1112                                 if(!strcmp(new_file->asset->path,
1113                                         new_asset->path))
1114                                 {
1115                                         got_it = 1;
1116                                         break;
1117                                 }
1118                         }
1120                         mainindexes->add_next_asset(got_it ? new_file : 0, 
1121                                 new_asset);
1122                         edl->assets->update(new_asset);
1124                 }
1127 // Start examining next batch of index files
1128                 mainindexes->start_build();
1129         }
1132         update_project(load_mode);
1133 SET_TRACE
1137         new_edls.remove_all_objects();
1138 SET_TRACE
1139         for(int i = 0; i < new_assets.total; i++)
1140                 Garbage::delete_object(new_assets.values[i]);
1141 SET_TRACE
1142         new_assets.remove_all();
1143 SET_TRACE
1144         new_files.remove_all_objects();
1146 SET_TRACE
1147         undo->update_undo(_("load"), LOAD_ALL, 0);
1150 SET_TRACE
1151         gui->stop_hourglass();
1152 SET_TRACE
1154         return 0;
1160 void MWindow::test_plugins(EDL *new_edl, char *path)
1162         char string[BCTEXTLEN];
1163 // Do a check weather plugins exist
1164         for(Track *track = new_edl->tracks->first; track; track = track->next)
1165         {
1166                 for(int k = 0; k < track->plugin_set.total; k++)
1167                 {
1168                         PluginSet *plugin_set = track->plugin_set.values[k];
1169                         for(Plugin *plugin = (Plugin*)plugin_set->first; 
1170                         plugin; 
1171                         plugin = (Plugin*)plugin->next)
1172                         {
1173                                 if(plugin->plugin_type == PLUGIN_STANDALONE)
1174                                 {
1175                                         // ok we need to find it in plugindb
1176                                         int plugin_found = 0;
1177                                         for(int j = 0; j < plugindb->total; j++)
1178                                         {
1179                                                 PluginServer *server = plugindb->values[j];
1180                                                 if(!strcasecmp(server->title, plugin->title) &&
1181                                                         ((track->data_type == TRACK_AUDIO && server->audio) ||
1182                                                         (track->data_type == TRACK_VIDEO && server->video)) &&
1183                                                         (!server->transition))
1184                                                         plugin_found = 1;
1185                                         }
1186                                         if (!plugin_found) 
1187                                         {
1188                                                 sprintf(string, 
1189                                                         "The effect '%s' in file '%s' is not part of your installation of Cinelerra.\n"
1190                                                         "The project won't be rendered as it was meant and Cinelerra might crash.\n",
1191                                                         plugin->title, 
1192                                                         path); 
1193                                                 MainError::show_error(string);
1194                                         }
1195                                 }
1196                         }
1197                 }
1198                 for(Edit *edit = (Edit*)track->edits->first; 
1199                 edit; 
1200                 edit = (Edit*)edit->next)
1201                 {
1202                         if (edit->transition)
1203                         {
1204                                 // ok we need to find transition in plugindb
1205                                 int transition_found = 0;
1206                                 for(int j = 0; j < plugindb->total; j++)
1207                                 {
1208                                         PluginServer *server = plugindb->values[j];
1209                                         if(!strcasecmp(server->title, edit->transition->title) &&
1210                                                 ((track->data_type == TRACK_AUDIO && server->audio) ||
1211                                                 (track->data_type == TRACK_VIDEO && server->video)) &&
1212                                                 (server->transition))
1213                                                 transition_found = 1;
1214                                 }
1215                                 if (!transition_found) 
1216                                 {
1217                                         sprintf(string, 
1218                                                 "The transition '%s' in file '%s' is not part of your installation of Cinelerra.\n"
1219                                                 "The project won't be rendered as it was meant and Cinelerra might crash.\n",
1220                                                 edit->transition->title, 
1221                                                 path); 
1222                                         MainError::show_error(string);
1223                                 }
1224                         }
1225                 }
1226         }
1230 void MWindow::init_shm()
1232 // Fix shared memory
1233         FILE *fd = fopen("/proc/sys/kernel/shmmax", "w");
1234         if(fd)
1235         {
1236                 fprintf(fd, "0x7fffffff");
1237                 fclose(fd);
1238         }
1239         fd = 0;
1241         fd = fopen("/proc/sys/kernel/shmmax", "r");
1242         if(!fd)
1243         {
1244                 MainError::show_error("MWindow::init_shm: couldn't open /proc/sys/kernel/shmmax for reading.\n");
1245                 return;
1246         }
1248         int64_t result = 0;
1249         fscanf(fd, "%lld", &result);
1250         fclose(fd);
1251         fd = 0;
1252         if(result < 0x7fffffff)
1253         {
1254                 char string[BCTEXTLEN];
1255                 sprintf(string, "MWindow::init_shm: /proc/sys/kernel/shmmax is 0x%llx.\n"
1256                         "It should be at least 0x7fffffff for Cinelerra.\n",
1257                         result);
1258                 MainError::show_error(string);
1259         }
1264 void MWindow::create_objects(int want_gui, 
1265         int want_new,
1266         char *config_path)
1268         char string[BCTEXTLEN];
1269         FileSystem fs;
1270         edl = 0;
1274         init_3d();
1275         remove_thread = new RemoveThread;
1276         remove_thread->create_objects();
1277         show_splash();
1279 // For some reason, init_signals must come after show_splash or the signals won't
1280 // get trapped.
1281         init_signals();
1283         init_error();
1285 SET_TRACE
1287         init_defaults(defaults, config_path);
1288 SET_TRACE
1289         init_preferences();
1290 SET_TRACE
1291         init_plugins(preferences, plugindb, splash_window);
1292         if(splash_window) splash_window->operation->update(_("Initializing GUI"));
1293 SET_TRACE
1294         init_theme();
1295 // Default project created here
1296 SET_TRACE
1297         init_edl();
1299 SET_TRACE
1300         init_awindow();
1301 SET_TRACE
1302         init_compositor();
1303 SET_TRACE
1304         init_levelwindow();
1305 SET_TRACE
1306         init_viewer();
1307 SET_TRACE
1308         init_cache();
1309 SET_TRACE
1310         init_indexes();
1311 SET_TRACE
1312         init_channeldb();
1313 SET_TRACE
1315         init_gui();
1316         init_gwindow();
1317 SET_TRACE
1318         init_render();
1319         init_brender();
1320         init_exportedl();
1321         mainprogress = new MainProgress(this, gui);
1322         undo = new MainUndo(this);
1324         plugin_guis = new ArrayList<PluginServer*>;
1326 SET_TRACE
1327         if(session->show_vwindow) vwindow->gui->show_window();
1328         if(session->show_cwindow) cwindow->gui->show_window();
1329         if(session->show_awindow) awindow->gui->show_window();
1330         if(session->show_lwindow) lwindow->gui->show_window();
1331         if(session->show_gwindow) gwindow->gui->show_window();
1332 SET_TRACE
1335         gui->mainmenu->load_defaults(defaults);
1336 SET_TRACE
1337         gui->mainmenu->update_toggles(0);
1338 SET_TRACE
1339         gui->patchbay->update();
1340 SET_TRACE
1341         gui->canvas->draw();
1342 SET_TRACE
1343         gui->cursor->draw(1);
1344 SET_TRACE
1345         gui->show_window();
1346         gui->raise_window();
1348         if(preferences->use_tipwindow)
1349                 init_tipwindow();
1350                 
1351 SET_TRACE
1353         hide_splash();
1354 SET_TRACE
1355         init_shm();
1359 void MWindow::show_splash()
1361 #include "data/heroine_logo12_png.h"
1362         VFrame *frame = new VFrame(heroine_logo12_png);
1363         BC_DisplayInfo display_info;
1364         splash_window = new SplashGUI(frame, 
1365                 display_info.get_root_w() / 2 - frame->get_w() / 2,
1366                 display_info.get_root_h() / 2 - frame->get_h() / 2);
1367         splash_window->create_objects();
1370 void MWindow::hide_splash()
1372         if(splash_window)
1373                 delete splash_window;
1374         splash_window = 0;
1378 void MWindow::start()
1380 ENABLE_BUFFER
1381         vwindow->start();
1382         awindow->start();
1383         cwindow->start();
1384         lwindow->start();
1385         gwindow->start();
1386         Thread::start();
1387         playback_3d->start();
1390 void MWindow::run()
1392         gui->run_window();
1395 void MWindow::show_vwindow()
1397         session->show_vwindow = 1;
1398         vwindow->gui->lock_window("MWindow::show_vwindow");
1399         vwindow->gui->show_window();
1400         vwindow->gui->raise_window();
1401         vwindow->gui->flush();
1402         vwindow->gui->unlock_window();
1403         gui->mainmenu->show_vwindow->set_checked(1);
1406 void MWindow::show_awindow()
1408         session->show_awindow = 1;
1409         awindow->gui->lock_window("MWindow::show_awindow");
1410         awindow->gui->show_window();
1411         awindow->gui->raise_window();
1412         awindow->gui->flush();
1413         awindow->gui->unlock_window();
1414         gui->mainmenu->show_awindow->set_checked(1);
1417 void MWindow::show_cwindow()
1419         session->show_cwindow = 1;
1420         cwindow->show_window();
1421         gui->mainmenu->show_cwindow->set_checked(1);
1424 void MWindow::show_gwindow()
1426         session->show_gwindow = 1;
1428         gwindow->gui->lock_window("MWindow::show_gwindow");
1429         gwindow->gui->show_window();
1430         gwindow->gui->raise_window();
1431         gwindow->gui->flush();
1432         gwindow->gui->unlock_window();
1434         gui->mainmenu->show_gwindow->set_checked(1);
1437 void MWindow::show_lwindow()
1439         session->show_lwindow = 1;
1440         lwindow->gui->lock_window("MWindow::show_lwindow");
1441         lwindow->gui->show_window();
1442         lwindow->gui->raise_window();
1443         lwindow->gui->flush();
1444         lwindow->gui->unlock_window();
1445         gui->mainmenu->show_lwindow->set_checked(1);
1448 void MWindow::tile_windows()
1450         session->default_window_positions();
1451         gui->default_positions();
1454 void MWindow::toggle_loop_playback()
1456         edl->local_session->loop_playback = !edl->local_session->loop_playback;
1457         set_loop_boundaries();
1458         save_backup();
1460         gui->canvas->draw_overlays();
1461         gui->canvas->flash();
1462         sync_parameters(CHANGE_PARAMS);
1465 void MWindow::set_titles(int value)
1467         edl->session->show_titles = value;
1468         trackmovement(edl->local_session->track_start);
1471 void MWindow::set_auto_keyframes(int value)
1473         gui->lock_window("MWindow::set_auto_keyframes");
1474         edl->session->auto_keyframes = value;
1475         gui->mbuttons->edit_panel->keyframe->update(value);
1476         gui->flush();
1477         gui->unlock_window();
1478         cwindow->gui->lock_window("MWindow::set_auto_keyframes");
1479         cwindow->gui->edit_panel->keyframe->update(value);
1480         cwindow->gui->flush();
1481         cwindow->gui->unlock_window();
1484 int MWindow::set_editing_mode(int new_editing_mode)
1486         gui->lock_window("MWindow::set_editing_mode");
1487         edl->session->editing_mode = new_editing_mode;
1488         gui->mbuttons->edit_panel->editing_mode = edl->session->editing_mode;
1489         gui->mbuttons->edit_panel->update();
1490         gui->canvas->update_cursor();
1491         gui->unlock_window();
1492         cwindow->gui->lock_window("MWindow::set_editing_mode");
1493         cwindow->gui->edit_panel->update();
1494         cwindow->gui->edit_panel->editing_mode = edl->session->editing_mode;
1495         cwindow->gui->unlock_window();
1496         return 0;
1500 void MWindow::sync_parameters(int change_type)
1503 // Sync engines which are playing back
1504         if(cwindow->playback_engine->is_playing_back)
1505         {
1506                 if(change_type == CHANGE_PARAMS)
1507                 {
1508 // TODO: block keyframes until synchronization is done
1509                         cwindow->playback_engine->sync_parameters(edl);
1510                 }
1511                 else
1512 // Stop and restart
1513                 {
1514                         int command = cwindow->playback_engine->command->command;
1515                         cwindow->playback_engine->que->send_command(STOP,
1516                                 CHANGE_NONE, 
1517                                 0,
1518                                 0);
1519 // Waiting for tracking to finish would make the restart position more
1520 // accurate but it can't lock the window to stop tracking for some reason.
1521 // Not waiting for tracking gives a faster response but restart position is
1522 // only as accurate as the last tracking update.
1523                         cwindow->playback_engine->interrupt_playback(0);
1524                         cwindow->playback_engine->que->send_command(command,
1525                                         change_type, 
1526                                         edl,
1527                                         1,
1528                                         0);
1529                 }
1530         }
1531         else
1532         {
1533                 cwindow->playback_engine->que->send_command(CURRENT_FRAME, 
1534                                                         change_type,
1535                                                         edl,
1536                                                         1);
1537         }
1540 void MWindow::age_caches()
1542         int64_t prev_memory_usage;
1543         int64_t memory_usage;
1544         int result = 0;
1545         do
1546         {
1547                 memory_usage = audio_cache->get_memory_usage(1) +
1548                         video_cache->get_memory_usage(1) +
1549                         frame_cache->get_memory_usage() +
1550                         wave_cache->get_memory_usage();
1552                 if(memory_usage > preferences->cache_size)
1553                 {
1554                         int target = 1;
1555                         int oldest1 = audio_cache->get_oldest();
1556                         int oldest2 = video_cache->get_oldest();
1557                         if(oldest2 < oldest1) target = 2;
1558                         int oldest3 = frame_cache->get_oldest();
1559                         if(oldest3 < oldest1 && oldest3 < oldest2) target = 3;
1560                         int oldest4 = wave_cache->get_oldest();
1561                         if(oldest4 < oldest3 && oldest4 < oldest2 && oldest4 < oldest1) target = 4;
1562                         switch(target)
1563                         {
1564                                 case 1: audio_cache->delete_oldest(); break;
1565                                 case 2: video_cache->delete_oldest(); break;
1566                                 case 3: frame_cache->delete_oldest(); break;
1567                                 case 4: wave_cache->delete_oldest(); break;
1568                         }
1569                 }
1570                 prev_memory_usage = memory_usage;
1571                 memory_usage = audio_cache->get_memory_usage(1) +
1572                         video_cache->get_memory_usage(1) +
1573                         frame_cache->get_memory_usage() +
1574                         wave_cache->get_memory_usage();
1575         }while(!result && 
1576                 prev_memory_usage != memory_usage && 
1577                 memory_usage > preferences->cache_size);
1580 void MWindow::show_plugin(Plugin *plugin)
1582         int done = 0;
1583 //printf("MWindow::show_plugin 1\n");
1584         plugin_gui_lock->lock("MWindow::show_plugin");
1585         for(int i = 0; i < plugin_guis->total; i++)
1586         {
1587 // Pointer comparison
1588                 if(plugin_guis->values[i]->plugin == plugin)
1589                 {
1590                         plugin_guis->values[i]->raise_window();
1591                         done = 1;
1592                         break;
1593                 }
1594         }
1596 //printf("MWindow::show_plugin 1\n");
1597         if(!done)
1598         {
1599                 if(!plugin->track)
1600                 {
1601                         printf("MWindow::show_plugin track not defined.\n");
1602                 }
1603                 PluginServer *server = scan_plugindb(plugin->title,
1604                         plugin->track->data_type);
1606 //printf("MWindow::show_plugin %p %d\n", server, server->uses_gui);
1607                 if(server && server->uses_gui)
1608                 {
1609                         PluginServer *gui = plugin_guis->append(new PluginServer(*server));
1610 // Needs mwindow to do GUI
1611                         gui->set_mwindow(this);
1612                         gui->open_plugin(0, preferences, edl, plugin, -1);
1613                         gui->show_gui();
1614                         plugin->show = 1;
1615                 }
1616         }
1617         plugin_gui_lock->unlock();
1618 //printf("MWindow::show_plugin 2\n");
1621 void MWindow::hide_plugin(Plugin *plugin, int lock)
1623         plugin->show = 0;
1624         gui->lock_window("MWindow::hide_plugin");
1625         gui->update(0, 1, 0, 0, 0, 0, 0);
1626         gui->unlock_window();
1628         if(lock) plugin_gui_lock->lock("MWindow::hide_plugin");
1629         for(int i = 0; i < plugin_guis->total; i++)
1630         {
1631                 if(plugin_guis->values[i]->plugin == plugin)
1632                 {
1633                         PluginServer *ptr = plugin_guis->values[i];
1634                         plugin_guis->remove(ptr);
1635                         if(lock) plugin_gui_lock->unlock();
1636 // Last command executed in client side close
1637                         delete ptr;
1638                         return;
1639                 }
1640         }
1641         if(lock) plugin_gui_lock->unlock();
1645 void MWindow::hide_plugins()
1647         plugin_gui_lock->lock("MWindow::hide_plugins");
1648         plugin_guis->remove_all_objects();
1649         plugin_gui_lock->unlock();
1652 void MWindow::update_plugin_guis()
1654         plugin_gui_lock->lock("MWindow::update_plugin_guis");
1656         for(int i = 0; i < plugin_guis->total; i++)
1657         {
1658                 plugin_guis->values[i]->update_gui();
1659         }
1660         plugin_gui_lock->unlock();
1663 int MWindow::plugin_gui_open(Plugin *plugin)
1665         int result = 0;
1666         plugin_gui_lock->lock("MWindow::plugin_gui_open");
1667         for(int i = 0; i < plugin_guis->total; i++)
1668         {
1669                 if(plugin_guis->values[i]->plugin->identical_location(plugin))
1670                 {
1671                         result = 1;
1672                         break;
1673                 }
1674         }
1675         plugin_gui_lock->unlock();
1676         return result;
1679 void MWindow::render_plugin_gui(void *data, Plugin *plugin)
1681         plugin_gui_lock->lock("MWindow::render_plugin_gui");
1682         for(int i = 0; i < plugin_guis->total; i++)
1683         {
1684                 if(plugin_guis->values[i]->plugin->identical_location(plugin))
1685                 {
1686                         plugin_guis->values[i]->render_gui(data);
1687                         break;
1688                 }
1689         }
1690         plugin_gui_lock->unlock();
1693 void MWindow::render_plugin_gui(void *data, int size, Plugin *plugin)
1695         plugin_gui_lock->lock("MWindow::render_plugin_gui");
1696         for(int i = 0; i < plugin_guis->total; i++)
1697         {
1698                 if(plugin_guis->values[i]->plugin->identical_location(plugin))
1699                 {
1700                         plugin_guis->values[i]->render_gui(data, size);
1701                         break;
1702                 }
1703         }
1704         plugin_gui_lock->unlock();
1708 void MWindow::update_plugin_states()
1710         plugin_gui_lock->lock("MWindow::update_plugin_states");
1711         for(int i = 0; i < plugin_guis->total; i++)
1712         {
1713                 int result = 0;
1714 // Get a plugin GUI
1715                 Plugin *src_plugin = plugin_guis->values[i]->plugin;
1716                 PluginServer *src_plugingui = plugin_guis->values[i];
1718 // Search for plugin in EDL.  Only the master EDL shows plugin GUIs.
1719                 for(Track *track = edl->tracks->first; 
1720                         track && !result; 
1721                         track = track->next)
1722                 {
1723                         for(int j = 0; 
1724                                 j < track->plugin_set.total && !result; 
1725                                 j++)
1726                         {
1727                                 PluginSet *plugin_set = track->plugin_set.values[j];
1728                                 for(Plugin *plugin = (Plugin*)plugin_set->first; 
1729                                         plugin && !result; 
1730                                         plugin = (Plugin*)plugin->next)
1731                                 {
1732                                         if(plugin == src_plugin &&
1733                                                 !strcmp(plugin->title, src_plugingui->title)) result = 1;
1734                                 }
1735                         }
1736                 }
1739 // Doesn't exist anymore
1740                 if(!result)
1741                 {
1742                         hide_plugin(src_plugin, 0);
1743                         i--;
1744                 }
1745         }
1746         plugin_gui_lock->unlock();
1750 void MWindow::update_plugin_titles()
1752         for(int i = 0; i < plugin_guis->total; i++)
1753         {
1754                 plugin_guis->values[i]->update_title();
1755         }
1758 int MWindow::asset_to_edl(EDL *new_edl, 
1759         Asset *new_asset, 
1760         RecordLabels *labels)
1762 //printf("MWindow::asset_to_edl 1\n");
1763 //      new_edl->load_defaults(defaults);
1765 // Keep frame rate, sample rate, and output size unchanged.
1766 // These parameters would revert the project if VWindow displayed an asset
1767 // of different size than the project.
1768         if(new_asset->video_data)
1769         {
1770                 new_edl->session->video_tracks = new_asset->layers;
1771 //              new_edl->session->frame_rate = new_asset->frame_rate;
1772 //              new_edl->session->output_w = new_asset->width;
1773 //              new_edl->session->output_h = new_asset->height;
1774         }
1775         else
1776                 new_edl->session->video_tracks = 0;
1783         if(new_asset->audio_data)
1784         {
1785                 new_edl->session->audio_tracks = new_asset->channels;
1786 //              new_edl->session->sample_rate = new_asset->sample_rate;
1787         }
1788         else
1789                 new_edl->session->audio_tracks = 0;
1790 //printf("MWindow::asset_to_edl 2 %d %d\n", new_edl->session->video_tracks, new_edl->session->audio_tracks);
1792         new_edl->create_default_tracks();
1793 //printf("MWindow::asset_to_edl 2 %d %d\n", new_edl->session->video_tracks, new_edl->session->audio_tracks);
1795 // Disable drawing if the file format isn't fast enough.
1796 // MPEG is now faster than most other codecs.
1797 //      if(new_asset->format == FILE_MPEG)
1798 //      {
1799 //              for(Track *current = new_edl->tracks->first;
1800 //                      current;
1801 //                      current = NEXT)
1802 //              {
1803 //                      if(current->data_type == TRACK_VIDEO) current->draw = 0;
1804 //              }
1805 //      }
1809 //printf("MWindow::asset_to_edl 3\n");
1810         new_edl->insert_asset(new_asset, 0, 0, labels);
1811 //printf("MWindow::asset_to_edl 3\n");
1817         char string[BCTEXTLEN];
1818         FileSystem fs;
1819         fs.extract_name(string, new_asset->path);
1820 //printf("MWindow::asset_to_edl 3\n");
1822         strcpy(new_edl->local_session->clip_title, string);
1823 //printf("MWindow::asset_to_edl 4 %s\n", string);
1825 //      new_edl->dump();
1826         return 0;
1829 // Reset everything after a load.
1830 void MWindow::update_project(int load_mode)
1832         restart_brender();
1833         edl->tracks->update_y_pixels(theme);
1836         gui->update(1, 1, 1, 1, 1, 1, 1);
1838         cwindow->update(0, 0, 1, 1, 1);
1841         if(load_mode == LOAD_REPLACE ||
1842                 load_mode == LOAD_REPLACE_CONCATENATE)
1843         {
1844                 vwindow->change_source();
1845         }
1846         else
1847         {
1848                 vwindow->update(1);
1849         }
1851         cwindow->gui->slider->set_position();
1852         cwindow->gui->timebar->update(1, 1);
1853         cwindow->playback_engine->que->send_command(CURRENT_FRAME, 
1854                 CHANGE_ALL,
1855                 edl,
1856                 1);
1858         awindow->gui->lock_window("MWindow::update_project");
1859         awindow->gui->update_assets();
1860         awindow->gui->flush();
1861         awindow->gui->unlock_window();
1862         gui->flush();
1866 void MWindow::rebuild_indices()
1868         char source_filename[BCTEXTLEN], index_filename[BCTEXTLEN];
1870         for(int i = 0; i < session->drag_assets->total; i++)
1871         {
1872 //printf("MWindow::rebuild_indices 1 %s\n", session->drag_assets->values[i]->path);
1873 // Erase file
1874                 IndexFile::get_index_filename(source_filename, 
1875                         preferences->index_directory,
1876                         index_filename, 
1877                         session->drag_assets->values[i]->path);
1878                 remove(index_filename);
1879 // Schedule index build
1880                 session->drag_assets->values[i]->index_status = INDEX_NOTTESTED;
1881                 mainindexes->add_next_asset(0, session->drag_assets->values[i]);
1882         }
1883         mainindexes->start_build();
1887 void MWindow::save_backup()
1889         FileXML file;
1890         edl->set_project_path(session->filename);
1891         edl->save_xml(plugindb, 
1892                 &file, 
1893                 BACKUP_PATH,
1894                 0,
1895                 0);
1896         file.terminate_string();
1897         char path[BCTEXTLEN];
1898         FileSystem fs;
1899         strcpy(path, BACKUP_PATH);
1900         fs.complete_path(path);
1902         if(file.write_to_file(path))
1903         {
1904                 char string2[256];
1905                 sprintf(string2, _("Couldn't open %s for writing."), BACKUP_PATH);
1906                 gui->show_message(string2);
1907         }
1911 int MWindow::create_aspect_ratio(float &w, float &h, int width, int height)
1913         int denominator;
1914         if(!width || !height) return 1;
1915         float fraction = (float)width / height;
1917         for(denominator = 1; 
1918                 denominator < 100 && 
1919                         fabs(fraction * denominator - (int)(fraction * denominator)) > .001; 
1920                 denominator++)
1921                 ;
1923         w = denominator * width / height;
1924         h = denominator;
1925         return 0;
1928 void MWindow::reset_caches()
1930         frame_cache->remove_all();
1931         wave_cache->remove_all();
1932         audio_cache->remove_all();
1933         video_cache->remove_all();
1934         if(cwindow->playback_engine && cwindow->playback_engine->audio_cache)
1935                 cwindow->playback_engine->audio_cache->remove_all();
1936         if(cwindow->playback_engine && cwindow->playback_engine->video_cache)
1937                 cwindow->playback_engine->video_cache->remove_all();
1938         if(vwindow->playback_engine && vwindow->playback_engine->audio_cache)
1939                 vwindow->playback_engine->audio_cache->remove_all();
1940         if(vwindow->playback_engine && vwindow->playback_engine->video_cache)
1941                 vwindow->playback_engine->video_cache->remove_all();
1944 void MWindow::remove_asset_from_caches(Asset *asset)
1946         frame_cache->remove_asset(asset);
1947         wave_cache->remove_asset(asset);
1948         audio_cache->delete_entry(asset);
1949         video_cache->delete_entry(asset);
1950         if(cwindow->playback_engine && cwindow->playback_engine->audio_cache)
1951                 cwindow->playback_engine->audio_cache->delete_entry(asset);
1952         if(cwindow->playback_engine && cwindow->playback_engine->video_cache)
1953                 cwindow->playback_engine->video_cache->delete_entry(asset);
1954         if(vwindow->playback_engine && vwindow->playback_engine->audio_cache)
1955                 vwindow->playback_engine->audio_cache->delete_entry(asset);
1956         if(vwindow->playback_engine && vwindow->playback_engine->video_cache)
1957                 vwindow->playback_engine->video_cache->delete_entry(asset);
1962 void MWindow::remove_assets_from_project(int push_undo)
1964         for(int i = 0; i < session->drag_assets->total; i++)
1965         {
1966                 Asset *asset = session->drag_assets->values[i];
1967                 remove_asset_from_caches(asset);
1968         }
1970 // Remove from VWindow.
1971         for(int i = 0; i < session->drag_clips->total; i++)
1972         {
1973                 if(session->drag_clips->values[i] == vwindow->get_edl())
1974                 {
1975                         vwindow->gui->lock_window("MWindow::remove_assets_from_project 1");
1976                         vwindow->remove_source();
1977                         vwindow->gui->unlock_window();
1978                 }
1979         }
1980         
1981         for(int i = 0; i < session->drag_assets->total; i++)
1982         {
1983                 if(session->drag_assets->values[i] == vwindow->get_asset())
1984                 {
1985                         vwindow->gui->lock_window("MWindow::remove_assets_from_project 2");
1986                         vwindow->remove_source();
1987                         vwindow->gui->unlock_window();
1988                 }
1989         }
1990         
1991         edl->remove_from_project(session->drag_assets);
1992         edl->remove_from_project(session->drag_clips);
1993         save_backup();
1994         if(push_undo) undo->update_undo(_("remove assets"), LOAD_ALL);
1995         restart_brender();
1997         gui->lock_window("MWindow::remove_assets_from_project 3");
1998         gui->update(1,
1999                 1,
2000                 1,
2001                 1,
2002                 0, 
2003                 1,
2004                 0);
2005         gui->unlock_window();
2007         awindow->gui->lock_window("MWindow::remove_assets_from_project 4");
2008         awindow->gui->update_assets();
2009         awindow->gui->flush();
2010         awindow->gui->unlock_window();
2012 // Removes from playback here
2013         sync_parameters(CHANGE_ALL);
2016 void MWindow::remove_assets_from_disk()
2018 // Remove from disk
2019         for(int i = 0; i < session->drag_assets->total; i++)
2020         {
2021                 remove(session->drag_assets->values[i]->path);
2022         }
2024         remove_assets_from_project(1);
2027 void MWindow::dump_plugins()
2029         for(int i = 0; i < plugindb->total; i++)
2030         {
2031                 printf("audio=%d video=%d realtime=%d transition=%d theme=%d %s\n",
2032                         plugindb->values[i]->audio,
2033                         plugindb->values[i]->video,
2034                         plugindb->values[i]->realtime,
2035                         plugindb->values[i]->transition,
2036                         plugindb->values[i]->theme,
2037                         plugindb->values[i]->title);
2038         }
2065 int MWindow::save_defaults()
2067         gui->save_defaults(defaults);
2068         edl->save_defaults(defaults);
2069         session->save_defaults(defaults);
2070         preferences->save_defaults(defaults);
2072         defaults->save();
2073         return 0;
2076 int MWindow::run_script(FileXML *script)
2078         int result = 0, result2 = 0;
2079         while(!result && !result2)
2080         {
2081                 result = script->read_tag();
2082                 if(!result)
2083                 {
2084                         if(script->tag.title_is("new_project"))
2085                         {
2086 // Run new in immediate mode.
2087 //                              gui->mainmenu->new_project->run_script(script);
2088                         }
2089                         else
2090                         if(script->tag.title_is("record"))
2091                         {
2092 // Run record as a thread.  It is a terminal command.
2093                                 ;
2094 // Will read the complete scipt file without letting record read it if not
2095 // terminated.
2096                                 result2 = 1;
2097                         }
2098                         else
2099                         {
2100                                 printf("MWindow::run_script: Unrecognized command: %s\n",script->tag.get_title() );
2101                         }
2102                 }
2103         }
2104         return result2;
2107 // ================================= synchronization
2110 int MWindow::interrupt_indexes()
2112         mainindexes->interrupt_build();
2113         return 0; 
2118 void MWindow::next_time_format()
2120         switch(edl->session->time_format)
2121         {
2122                 case TIME_HMS: edl->session->time_format = TIME_HMSF; break;
2123                 case TIME_HMSF: edl->session->time_format = TIME_SAMPLES; break;
2124                 case TIME_SAMPLES: edl->session->time_format = TIME_SAMPLES_HEX; break;
2125                 case TIME_SAMPLES_HEX: edl->session->time_format = TIME_FRAMES; break;
2126                 case TIME_FRAMES: edl->session->time_format = TIME_FEET_FRAMES; break;
2127                 case TIME_FEET_FRAMES: edl->session->time_format = TIME_SECONDS; break;
2128                 case TIME_SECONDS: edl->session->time_format = TIME_HMS; break;
2129         }
2131         time_format_common();
2134 void MWindow::prev_time_format()
2136         switch(edl->session->time_format)
2137         {
2138                 case TIME_HMS: edl->session->time_format = TIME_SECONDS; break;
2139                 case TIME_SECONDS: edl->session->time_format = TIME_FEET_FRAMES; break;
2140                 case TIME_FEET_FRAMES: edl->session->time_format = TIME_FRAMES; break;
2141                 case TIME_FRAMES: edl->session->time_format = TIME_SAMPLES_HEX; break;
2142                 case TIME_SAMPLES_HEX: edl->session->time_format = TIME_SAMPLES; break;
2143                 case TIME_SAMPLES: edl->session->time_format = TIME_HMSF; break;
2144                 case TIME_HMSF: edl->session->time_format = TIME_HMS; break;
2145         }
2147         time_format_common();
2150 void MWindow::time_format_common()
2152         gui->lock_window("MWindow::next_time_format");
2153         gui->redraw_time_dependancies();
2154         char string[BCTEXTLEN], string2[BCTEXTLEN];
2155         sprintf(string, _("Using %s."), Units::print_time_format(edl->session->time_format, string2));
2156         gui->show_message(string);
2157         gui->flush();
2158         gui->unlock_window();
2162 int MWindow::set_filename(char *filename)
2164         strcpy(session->filename, filename);
2165         if(gui)
2166         {
2167                 if(filename[0] == 0)
2168                 {
2169                         gui->set_title(PROGRAM_NAME);
2170                 }
2171                 else
2172                 {
2173                         FileSystem dir;
2174                         char string[BCTEXTLEN], string2[BCTEXTLEN];
2175                         dir.extract_name(string, filename);
2176                         sprintf(string2, PROGRAM_NAME ": %s", string);
2177                         gui->set_title(string2);
2178                 }
2179         }
2180         return 0; 
2190 int MWindow::set_loop_boundaries()
2192         double start = edl->local_session->get_selectionstart();
2193         double end = edl->local_session->get_selectionend();
2194         
2195         if(start != 
2196                 end) 
2197         {
2198                 ;
2199         }
2200         else
2201         if(edl->tracks->total_length())
2202         {
2203                 start = 0;
2204                 end = edl->tracks->total_length();
2205         }
2206         else
2207         {
2208                 start = end = 0;
2209         }
2211         if(edl->local_session->loop_playback && start != end)
2212         {
2213                 edl->local_session->loop_start = start;
2214                 edl->local_session->loop_end = end;
2215         }
2216         return 0; 
2225 int MWindow::reset_meters()
2227         cwindow->gui->lock_window("MWindow::reset_meters 1");
2228         cwindow->gui->meters->reset_meters();
2229         cwindow->gui->unlock_window();
2231         vwindow->gui->lock_window("MWindow::reset_meters 2");
2232         vwindow->gui->meters->reset_meters();
2233         vwindow->gui->unlock_window();
2235         lwindow->gui->lock_window("MWindow::reset_meters 3");
2236         lwindow->gui->panel->reset_meters();
2237         lwindow->gui->unlock_window();
2239         gui->lock_window("MWindow::reset_meters 4");
2240         gui->patchbay->reset_meters();
2241         gui->unlock_window();
2242         return 0;