cin_db Makefile tweak, awdw vicon stop draw lock rework,
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / mainmenu.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "assets.h"
23 #include "auto.h"
24 #include "batchrender.h"
25 #include "bcdisplayinfo.h"
26 #include "bchash.h"
27 #include "bcsignals.h"
28 #include "bdcreate.h"
29 #include "cache.h"
30 #include "channelinfo.h"
31 #include "convert.h"
32 #include "cplayback.h"
33 #include "cropvideo.h"
34 #include "cwindow.h"
35 #include "cwindowgui.h"
36 #include "dbwindow.h"
37 #include "dvdcreate.h"
38 #include "edl.h"
39 #include "edlsession.h"
40 #include "exportedl.h"
41 #include "file.h"
42 #include "filesystem.h"
43 #include "filexml.h"
44 #include "floatauto.h"
45 #include "keys.h"
46 #include "language.h"
47 #include "levelwindow.h"
48 #include "loadfile.h"
49 #include "localsession.h"
50 #include "mainclock.h"
51 #include "mainmenu.h"
52 #include "mainsession.h"
53 #include "mainundo.h"
54 #include "menuattacheffect.h"
55 #include "menuattachtransition.h"
56 #include "menuaeffects.h"
57 #include "menueditlength.h"
58 #include "menutransitionlength.h"
59 #include "menuveffects.h"
60 #include "mixersalign.h"
61 #include "mwindowgui.h"
62 #include "mwindow.h"
63 #include "new.h"
64 #include "patchbay.h"
65 #include "playbackengine.h"
66 #include "preferences.h"
67 #include "proxy.h"
68 #include "preferencesthread.h"
69 #include "quit.h"
70 #include "record.h"
71 #include "render.h"
72 #include "savefile.h"
73 #include "setformat.h"
74 #include "swindow.h"
75 #include "timebar.h"
76 #include "trackcanvas.h"
77 #include "tracks.h"
78 #include "transition.h"
79 #include "transportque.h"
80 #include "viewmenu.h"
81 #include "zoombar.h"
82 #include "zwindow.h"
83 #include "zwindowgui.h"
84
85 #include <string.h>
86
87
88 MainMenu::MainMenu(MWindow *mwindow, MWindowGUI *gui, int w)
89  : BC_MenuBar(0, 0, w)
90 {
91         this->gui = gui;
92         this->mwindow = mwindow;
93 }
94
95 MainMenu::~MainMenu()
96 {
97 }
98
99 void MainMenu::create_objects()
100 {
101         BC_Menu *viewmenu, *windowmenu, *settingsmenu, *trackmenu;
102         PreferencesMenuitem *preferences;
103
104         add_menu(filemenu = new BC_Menu(_("File")));
105         filemenu->add_item(new_project = new NewProject(mwindow));
106         new_project->create_objects();
107
108 // file loaders
109         filemenu->add_item(load_file = new Load(mwindow, this));
110         load_file->create_objects();
111         filemenu->add_item(load_recent = new LoadRecent(mwindow, this));
112         load_recent->create_objects();
113
114 // new and load can be undone so no need to prompt save
115         Save *save;                   //  affected by saveas
116         filemenu->add_item(save = new Save(mwindow));
117         SaveAs *saveas;
118         filemenu->add_item(saveas = new SaveAs(mwindow));
119         save->create_objects(saveas);
120         saveas->set_mainmenu(this);
121         SaveProject *save_project;
122         filemenu->add_item(save_project = new SaveProject(mwindow));
123
124         filemenu->add_item(record_menu_item = new RecordMenuItem(mwindow));
125 #ifdef HAVE_DVB
126         filemenu->add_item(new ChannelScan(mwindow));
127 #endif
128 #ifdef HAVE_COMMERCIAL
129         if( mwindow->has_commercials() )
130                 filemenu->add_item(new DbWindowScan(mwindow));
131 #endif
132         filemenu->add_item(new SubttlSWin(mwindow));
133
134         filemenu->add_item(render = new RenderItem(mwindow));
135         filemenu->add_item(new ExportEDLItem(mwindow));
136         filemenu->add_item(new BatchRenderMenuItem(mwindow));
137         filemenu->add_item(new CreateBD_MenuItem(mwindow));
138         filemenu->add_item(new CreateDVD_MenuItem(mwindow));
139         filemenu->add_item(new BC_MenuItem("-"));
140         filemenu->add_item(quit_program = new Quit(mwindow));
141         quit_program->create_objects(save);
142         filemenu->add_item(dump_menu = new MainDumpsMenu(mwindow));
143         dump_menu->create_objects();
144         filemenu->add_item(new LoadBackup(mwindow));
145         filemenu->add_item(new SaveBackup(mwindow));
146
147         BC_Menu *editmenu;
148         add_menu(editmenu = new BC_Menu(_("Edit")));
149         editmenu->add_item(undo = new Undo(mwindow));
150         editmenu->add_item(redo = new Redo(mwindow));
151         editmenu->add_item(new BC_MenuItem("-"));
152         editmenu->add_item(new Cut(mwindow));
153         editmenu->add_item(new Copy(mwindow));
154         editmenu->add_item(new Paste(mwindow));
155         editmenu->add_item(new PasteSilence(mwindow));
156         editmenu->add_item(clear_menu = new EditClearMenu(mwindow));
157         clear_menu->create_objects();
158         editmenu->add_item(new TrimSelection(mwindow));
159         editmenu->add_item(new SelectAll(mwindow));
160         editmenu->add_item(new BC_MenuItem("-"));
161         editmenu->add_item(new MenuEditShuffle(mwindow));
162         editmenu->add_item(new MenuEditReverse(mwindow));
163         editmenu->add_item(new MenuEditLength(mwindow));
164         editmenu->add_item(new MenuEditAlign(mwindow));
165         editmenu->add_item(new MenuTransitionLength(mwindow));
166         editmenu->add_item(new DetachTransitions(mwindow));
167         editmenu->add_item(new BC_MenuItem("-"));
168         editmenu->add_item(new CutCommercials(mwindow));
169         editmenu->add_item(new PasteSubttl(mwindow));
170
171         BC_Menu *keyframemenu;
172         add_menu(keyframemenu = new BC_Menu(_("Keyframes")));
173         keyframemenu->add_item(new CutKeyframes(mwindow));
174         keyframemenu->add_item(new CopyKeyframes(mwindow));
175         keyframemenu->add_item(new PasteKeyframes(mwindow));
176         keyframemenu->add_item(new ClearKeyframes(mwindow));
177         keyframemenu->add_item(new StraightenKeyframes(mwindow));
178         keyframemenu->add_item(new BendKeyframes(mwindow));
179         keyframemenu->add_item(keyframe_curve_type = new KeyframeCurveType(mwindow));
180         keyframe_curve_type->create_objects();
181         keyframe_curve_type->update(mwindow->edl->local_session->floatauto_type);
182         keyframemenu->add_item(new BC_MenuItem("-"));
183         keyframemenu->add_item(new CopyDefaultKeyframe(mwindow));
184         keyframemenu->add_item(new PasteDefaultKeyframe(mwindow));
185
186
187
188
189         add_menu(audiomenu = new BC_Menu(_("Audio")));
190         audiomenu->add_item(new AddAudioTrack(mwindow));
191         audiomenu->add_item(new DefaultATransition(mwindow));
192         audiomenu->add_item(new MapAudio1(mwindow));
193         audiomenu->add_item(new MapAudio2(mwindow));
194         audiomenu->add_item(new MenuAttachTransition(mwindow, TRACK_AUDIO));
195         audiomenu->add_item(new MenuAttachEffect(mwindow, TRACK_AUDIO));
196         audiomenu->add_item(aeffects = new MenuAEffects(mwindow));
197
198         add_menu(videomenu = new BC_Menu(_("Video")));
199         videomenu->add_item(new AddVideoTrack(mwindow));
200         videomenu->add_item(new DefaultVTransition(mwindow));
201         videomenu->add_item(new MenuAttachTransition(mwindow, TRACK_VIDEO));
202         videomenu->add_item(new MenuAttachEffect(mwindow, TRACK_VIDEO));
203         videomenu->add_item(veffects = new MenuVEffects(mwindow));
204
205         add_menu(trackmenu = new BC_Menu(_("Tracks")));
206         trackmenu->add_item(new MoveTracksUp(mwindow));
207         trackmenu->add_item(new MoveTracksDown(mwindow));
208         trackmenu->add_item(new DeleteTracks(mwindow));
209         trackmenu->add_item(new DeleteFirstTrack(mwindow));
210         trackmenu->add_item(new DeleteLastTrack(mwindow));
211         trackmenu->add_item(new ConcatenateTracks(mwindow));
212         trackmenu->add_item(new AlignTimecodes(mwindow));
213         trackmenu->add_item(new SwapTracksUp(mwindow));
214         trackmenu->add_item(new SwapTracksDown(mwindow));
215         AppendTracks *append_tracks;
216         trackmenu->add_item(append_tracks = new AppendTracks(mwindow));
217         append_tracks->create_objects();
218         trackmenu->add_item(new AddSubttlTrack(mwindow));
219
220         add_menu(settingsmenu = new BC_Menu(_("Settings")));
221
222         settingsmenu->add_item(new SetFormat(mwindow));
223         settingsmenu->add_item(preferences = new PreferencesMenuitem(mwindow));
224         ProxyMenuItem *proxy;
225         settingsmenu->add_item(proxy = new ProxyMenuItem(mwindow));
226         proxy->create_objects();
227         ConvertMenuItem *convert;
228         settingsmenu->add_item(convert = new ConvertMenuItem(mwindow));
229         convert->create_objects();
230         mwindow->preferences_thread = preferences->thread;
231         settingsmenu->add_item(cursor_on_frames = new CursorOnFrames(mwindow));
232         settingsmenu->add_item(labels_follow_edits = new LabelsFollowEdits(mwindow));
233         settingsmenu->add_item(plugins_follow_edits = new PluginsFollowEdits(mwindow));
234         settingsmenu->add_item(keyframes_follow_edits = new KeyframesFollowEdits(mwindow));
235         settingsmenu->add_item(typeless_keyframes = new TypelessKeyframes(mwindow));
236         settingsmenu->add_item(new BC_MenuItem("-"));
237         settingsmenu->add_item(new SaveSettingsNow(mwindow));
238         settingsmenu->add_item(loop_playback = new LoopPlayback(mwindow));
239         settingsmenu->add_item(brender_active = new SetBRenderActive(mwindow));
240 // set scrubbing speed
241 //      ScrubSpeed *scrub_speed;
242 //      settingsmenu->add_item(scrub_speed = new ScrubSpeed(mwindow));
243 //      if(mwindow->edl->session->scrub_speed == .5)
244 //              scrub_speed->set_text(_("Fast Shuttle"));
245
246
247
248
249
250
251         add_menu(viewmenu = new BC_Menu(_("View")));
252         viewmenu->add_item(show_assets = new ShowAssets(mwindow, "0"));
253         viewmenu->add_item(show_titles = new ShowTitles(mwindow, "1"));
254         viewmenu->add_item(show_transitions = new ShowTransitions(mwindow, "2"));
255         viewmenu->add_item(fade_automation = new ShowAutomation(mwindow, _("Fade"), "3", AUTOMATION_FADE));
256         viewmenu->add_item(mute_automation = new ShowAutomation(mwindow, _("Mute"), "4", AUTOMATION_MUTE));
257         viewmenu->add_item(mode_automation = new ShowAutomation(mwindow, _("Overlay mode"), "5", AUTOMATION_MODE));
258         viewmenu->add_item(pan_automation = new ShowAutomation(mwindow, _("Pan"), "6", AUTOMATION_PAN));
259         viewmenu->add_item(plugin_automation = new PluginAutomation(mwindow, "7"));
260         viewmenu->add_item(mask_automation = new ShowAutomation(mwindow, _("Mask"), "8", AUTOMATION_MASK));
261         viewmenu->add_item(speed_automation = new ShowAutomation(mwindow, _("Speed"), "9", AUTOMATION_SPEED));
262
263         camera_x = new ShowAutomation(mwindow, _("Camera X"), "Ctrl-Shift-X", AUTOMATION_CAMERA_X);
264         camera_x->set_ctrl();  camera_x->set_shift();   viewmenu->add_item(camera_x);
265         camera_y = new ShowAutomation(mwindow, _("Camera Y"), "Ctrl-Shift-Y", AUTOMATION_CAMERA_Y);
266         camera_y->set_ctrl();  camera_y->set_shift();   viewmenu->add_item(camera_y);
267         camera_z = new ShowAutomation(mwindow, _("Camera Z"), "Ctrl-Shift-Z", AUTOMATION_CAMERA_Z);
268         camera_z->set_ctrl();  camera_z->set_shift();  viewmenu->add_item(camera_z);
269         project_x = new ShowAutomation(mwindow, _("Projector X"), "Alt-Shift-X", AUTOMATION_PROJECTOR_X);
270         project_x->set_alt();  project_x->set_shift();  viewmenu->add_item(project_x);
271         project_y = new ShowAutomation(mwindow, _("Projector Y"), "Alt-Shift-Y", AUTOMATION_PROJECTOR_Y);
272         project_y->set_alt();  project_y->set_shift();  viewmenu->add_item(project_y);
273         project_z = new ShowAutomation(mwindow, _("Projector Z"), "Alt-Shift-Z", AUTOMATION_PROJECTOR_Z);
274         project_z->set_alt();  project_z->set_shift();  viewmenu->add_item(project_z);
275
276         add_menu(windowmenu = new BC_Menu(_("Window")));
277         windowmenu->add_item(show_vwindow = new ShowVWindow(mwindow));
278         windowmenu->add_item(show_awindow = new ShowAWindow(mwindow));
279         windowmenu->add_item(show_cwindow = new ShowCWindow(mwindow));
280         windowmenu->add_item(show_gwindow = new ShowGWindow(mwindow));
281         windowmenu->add_item(show_lwindow = new ShowLWindow(mwindow));
282         windowmenu->add_item(new BC_MenuItem("-"));
283         windowmenu->add_item(split_x = new SplitX(mwindow));
284         windowmenu->add_item(split_y = new SplitY(mwindow));
285         windowmenu->add_item(mixer_items = new MixerItems(mwindow));
286         mixer_items->create_objects();
287         windowmenu->add_item(new TileWindows(mwindow,_("Tile left"),0));
288         windowmenu->add_item(new TileWindows(mwindow,_("Tile right"),1));
289         windowmenu->add_item(new BC_MenuItem("-"));
290
291         windowmenu->add_item(new TileWindows(mwindow,_("Default positions"),-1,_("Ctrl-P"),'p'));
292         windowmenu->add_item(load_layout = new LoadLayout(mwindow, _("Load layout..."),LAYOUT_LOAD));
293         load_layout->create_objects();
294         windowmenu->add_item(save_layout = new LoadLayout(mwindow, _("Save layout..."),LAYOUT_SAVE));
295         save_layout->create_objects();
296 }
297
298 int MainMenu::load_defaults(BC_Hash *defaults)
299 {
300         init_loads(defaults);
301         init_aeffects(defaults);
302         init_veffects(defaults);
303         return 0;
304 }
305
306 void MainMenu::update_toggles(int use_lock)
307 {
308         if(use_lock) lock_window("MainMenu::update_toggles");
309         labels_follow_edits->set_checked(mwindow->edl->session->labels_follow_edits);
310         plugins_follow_edits->set_checked(mwindow->edl->session->plugins_follow_edits);
311         keyframes_follow_edits->set_checked(mwindow->edl->session->autos_follow_edits);
312         typeless_keyframes->set_checked(mwindow->edl->session->typeless_keyframes);
313         cursor_on_frames->set_checked(mwindow->edl->session->cursor_on_frames);
314         loop_playback->set_checked(mwindow->edl->local_session->loop_playback);
315
316         show_assets->set_checked(mwindow->edl->session->show_assets);
317         show_titles->set_checked(mwindow->edl->session->show_titles);
318         show_transitions->set_checked(mwindow->edl->session->auto_conf->transitions);
319         fade_automation->update_toggle();
320         mute_automation->update_toggle();
321         pan_automation->update_toggle();
322         camera_x->update_toggle();
323         camera_y->update_toggle();
324         camera_z->update_toggle();
325         project_x->update_toggle();
326         project_y->update_toggle();
327         project_z->update_toggle();
328         plugin_automation->set_checked(mwindow->edl->session->auto_conf->plugins);
329         mode_automation->update_toggle();
330         mask_automation->update_toggle();
331         speed_automation->update_toggle();
332         split_x->set_checked(mwindow->gui->pane[TOP_RIGHT_PANE] != 0);
333         split_y->set_checked(mwindow->gui->pane[BOTTOM_LEFT_PANE] != 0);
334
335         if(use_lock) mwindow->gui->unlock_window();
336 }
337
338 int MainMenu::save_defaults(BC_Hash *defaults)
339 {
340         save_loads(defaults);
341         save_aeffects(defaults);
342         save_veffects(defaults);
343         return 0;
344 }
345
346
347
348
349
350 int MainMenu::quit()
351 {
352         quit_program->handle_event();
353         return 0;
354 }
355
356
357
358
359
360 // ================================== load most recent
361
362 int MainMenu::init_aeffects(BC_Hash *defaults)
363 {
364         total_aeffects = defaults->get((char*)"TOTAL_AEFFECTS", 0);
365
366         char string[BCTEXTLEN], title[BCTEXTLEN];
367         if(total_aeffects) audiomenu->add_item(new BC_MenuItem("-"));
368
369         for(int i = 0; i < total_aeffects; i++)
370         {
371                 sprintf(string, "AEFFECTRECENT%d", i);
372                 defaults->get(string, title);
373                 audiomenu->add_item(aeffect[i] = new MenuAEffectItem(aeffects, title));
374         }
375         return 0;
376 }
377
378 int MainMenu::init_veffects(BC_Hash *defaults)
379 {
380         total_veffects = defaults->get((char*)"TOTAL_VEFFECTS", 0);
381
382         char string[BCTEXTLEN], title[BCTEXTLEN];
383         if(total_veffects) videomenu->add_item(new BC_MenuItem("-"));
384
385         for(int i = 0; i < total_veffects; i++)
386         {
387                 sprintf(string, "VEFFECTRECENT%d", i);
388                 defaults->get(string, title);
389                 videomenu->add_item(veffect[i] = new MenuVEffectItem(veffects, title));
390         }
391         return 0;
392 }
393
394 void MainMenu::init_loads(BC_Hash *defaults)
395 {
396 // total_loads for legacy xml
397         int total_loads = defaults->get((char*)"TOTAL_LOADS", 0);
398         int loads_total = defaults->get((char*)"LOADS_TOTAL", 0);
399         if( loads_total < total_loads ) loads_total = total_loads;
400
401         char string[BCTEXTLEN], path[BCTEXTLEN];
402         FileSystem dir;
403 //printf("MainMenu::init_loads 2\n");
404
405         for( int i=0; i<loads_total; ++i ) {
406                 sprintf(string, "LOADPREVIOUS%d", i);
407 //printf("MainMenu::init_loads 3\n");
408                 defaults->get(string, path);
409                 if( load.size() < TOTAL_LOADS )
410                         load.append(new LoadRecentItem(path));
411         }
412 }
413
414 // ============================ save most recent
415
416 int MainMenu::save_aeffects(BC_Hash *defaults)
417 {
418         defaults->update((char*)"TOTAL_AEFFECTS", total_aeffects);
419         char string[BCTEXTLEN];
420         for(int i = 0; i < total_aeffects; i++)
421         {
422                 sprintf(string, "AEFFECTRECENT%d", i);
423                 defaults->update(string, aeffect[i]->get_text());
424         }
425         return 0;
426 }
427
428 int MainMenu::save_veffects(BC_Hash *defaults)
429 {
430         defaults->update((char*)"TOTAL_VEFFECTS", total_veffects);
431         char string[BCTEXTLEN];
432         for(int i = 0; i < total_veffects; i++)
433         {
434                 sprintf(string, "VEFFECTRECENT%d", i);
435                 defaults->update(string, veffect[i]->get_text());
436         }
437         return 0;
438 }
439
440 int MainMenu::save_loads(BC_Hash *defaults)
441 {
442 // legacy to prevent segv, older code cant tolerate total_loads>10
443         int loads_total = load.size();
444         int total_loads = MIN(10, loads_total);
445         defaults->update((char*)"LOADS_TOTAL", loads_total);
446         defaults->update((char*)"TOTAL_LOADS", total_loads);
447         char string[BCTEXTLEN];
448         for( int i=0; i<loads_total; ++i ) {
449                 sprintf(string, "LOADPREVIOUS%d", i);
450                 defaults->update(string, load[i]->path);
451         }
452         return 0;
453 }
454
455 // =================================== add most recent
456
457 int MainMenu::add_aeffect(char *title)
458 {
459 // add bar for first effect
460         if(total_aeffects == 0)
461         {
462                 audiomenu->add_item(new BC_MenuItem("-"));
463         }
464
465 // test for existing copy of effect
466         for(int i = 0; i < total_aeffects; i++)
467         {
468                 if(!strcmp(aeffect[i]->get_text(), title))     // already exists
469                 {                                // swap for top effect
470                         for(int j = i; j > 0; j--)   // move preceeding effects down
471                         {
472                                 aeffect[j]->set_text(aeffect[j - 1]->get_text());
473                         }
474                         aeffect[0]->set_text(title);
475                         return 1;
476                 }
477         }
478
479 // add another blank effect
480         if(total_aeffects < TOTAL_EFFECTS)
481         {
482                 audiomenu->add_item(
483                         aeffect[total_aeffects] = new MenuAEffectItem(aeffects, (char*)""));
484                 total_aeffects++;
485         }
486
487 // cycle effect down
488         for(int i = total_aeffects - 1; i > 0; i--)
489         {
490         // set menu item text
491                 aeffect[i]->set_text(aeffect[i - 1]->get_text());
492         }
493
494 // set up the new effect
495         aeffect[0]->set_text(title);
496         return 0;
497 }
498
499 int MainMenu::add_veffect(char *title)
500 {
501 // add bar for first effect
502         if(total_veffects == 0)
503         {
504                 videomenu->add_item(new BC_MenuItem("-"));
505         }
506
507 // test for existing copy of effect
508         for(int i = 0; i < total_veffects; i++)
509         {
510                 if(!strcmp(veffect[i]->get_text(), title))     // already exists
511                 {                                // swap for top effect
512                         for(int j = i; j > 0; j--)   // move preceeding effects down
513                         {
514                                 veffect[j]->set_text(veffect[j - 1]->get_text());
515                         }
516                         veffect[0]->set_text(title);
517                         return 1;
518                 }
519         }
520
521 // add another blank effect
522         if(total_veffects < TOTAL_EFFECTS)
523         {
524                 videomenu->add_item(veffect[total_veffects] =
525                         new MenuVEffectItem(veffects, (char*)""));
526                 total_veffects++;
527         }
528
529 // cycle effect down
530         for(int i = total_veffects - 1; i > 0; i--)
531         {
532 // set menu item text
533                 veffect[i]->set_text(veffect[i - 1]->get_text());
534         }
535
536 // set up the new effect
537         veffect[0]->set_text(title);
538         return 0;
539 }
540
541 int MainMenu::add_load(char *path)
542 {
543         return load.add_load(path);
544 }
545
546
547
548 // ================================== menu items
549
550 MainDumpsSubMenu::MainDumpsSubMenu(BC_MenuItem *menu_item)
551  : BC_SubMenu()
552 {
553         this->menu_item = menu_item;
554 }
555 MainDumpsSubMenu::~MainDumpsSubMenu()
556 {
557 }
558
559
560 MainDumpsMenu::MainDumpsMenu(MWindow *mwindow)
561  : BC_MenuItem(_("Dumps..."))
562 {
563         this->mwindow = mwindow;
564         this->dumps_menu = 0;
565 }
566 MainDumpsMenu::~MainDumpsMenu()
567 {
568 }
569
570 void MainDumpsMenu::create_objects()
571 {
572         add_submenu(dumps_menu = new MainDumpsSubMenu(this));
573 //      dumps_menu->add_item(new DumpCICache(mwindow));
574         dumps_menu->add_item(new DumpEDL(mwindow));
575         dumps_menu->add_item(new DumpPlugins(mwindow));
576         dumps_menu->add_item(new DumpAssets(mwindow));
577         dumps_menu->add_item(new DumpUndo(mwindow));
578 };
579
580
581 DumpCICache::DumpCICache(MWindow *mwindow)
582  : BC_MenuItem(_("Dump CICache"))
583 { this->mwindow = mwindow; }
584
585 int DumpCICache::handle_event()
586 {
587 //      mwindow->cache->dump();
588         return 1;
589 }
590
591 DumpEDL::DumpEDL(MWindow *mwindow)
592  : BC_MenuItem(_("Dump EDL"))
593 {
594         this->mwindow = mwindow;
595 }
596
597 int DumpEDL::handle_event()
598 {
599         mwindow->dump_edl();
600         return 1;
601 }
602
603 DumpPlugins::DumpPlugins(MWindow *mwindow)
604  : BC_MenuItem(_("Dump Plugins"))
605 {
606         this->mwindow = mwindow;
607 }
608
609 int DumpPlugins::handle_event()
610 {
611         mwindow->dump_plugins();
612         return 1;
613 }
614
615 DumpAssets::DumpAssets(MWindow *mwindow)
616  : BC_MenuItem(_("Dump Assets"))
617 { this->mwindow = mwindow; }
618
619 int DumpAssets::handle_event()
620 {
621         mwindow->edl->assets->dump();
622         return 1;
623 }
624
625 DumpUndo::DumpUndo(MWindow *mwindow)
626  : BC_MenuItem(_("Dump Undo"))
627 {
628         this->mwindow = mwindow;
629 }
630
631 int DumpUndo::handle_event()
632 {
633         mwindow->dump_undo();
634         return 1;
635 }
636
637 // ================================================= edit
638
639 Undo::Undo(MWindow *mwindow) : BC_MenuItem(_("Undo"), "z", 'z')
640 {
641         this->mwindow = mwindow;
642 }
643 int Undo::handle_event()
644 {
645         if( mwindow->session->current_operation == NO_OPERATION )
646                 mwindow->undo_entry(mwindow->gui);
647         return 1;
648 }
649 int Undo::update_caption(const char *new_caption)
650 {
651         char string[BCTEXTLEN];
652         sprintf(string, _("Undo %s"), new_caption);
653         set_text(string);
654         return 0;
655 }
656
657
658 Redo::Redo(MWindow *mwindow) : BC_MenuItem(_("Redo"), _("Shift-Z"), 'Z')
659 {
660         set_shift(1);
661         this->mwindow = mwindow;
662 }
663
664 int Redo::handle_event()
665 {
666         if( mwindow->session->current_operation == NO_OPERATION )
667                 mwindow->redo_entry(mwindow->gui);
668         return 1;
669 }
670 int Redo::update_caption(const char *new_caption)
671 {
672         char string[BCTEXTLEN];
673         sprintf(string, _("Redo %s"), new_caption);
674         set_text(string);
675         return 0;
676 }
677
678 CutKeyframes::CutKeyframes(MWindow *mwindow)
679  : BC_MenuItem(_("Cut keyframes"), _("Shift-X"), 'X')
680 {
681         set_shift();
682         this->mwindow = mwindow;
683 }
684
685 int CutKeyframes::handle_event()
686 {
687         if( mwindow->session->current_operation == NO_OPERATION )
688                 mwindow->cut_automation();
689         return 1;
690 }
691
692 CopyKeyframes::CopyKeyframes(MWindow *mwindow)
693  : BC_MenuItem(_("Copy keyframes"), _("Shift-C"), 'C')
694 {
695         set_shift();
696         this->mwindow = mwindow;
697 }
698
699 int CopyKeyframes::handle_event()
700 {
701         if( mwindow->session->current_operation == NO_OPERATION )
702                 mwindow->copy_automation();
703         return 1;
704 }
705
706 PasteKeyframes::PasteKeyframes(MWindow *mwindow)
707  : BC_MenuItem(_("Paste keyframes"), _("Shift-V"), 'V')
708 {
709         set_shift();
710         this->mwindow = mwindow;
711 }
712
713 int PasteKeyframes::handle_event()
714 {
715         if( mwindow->session->current_operation == NO_OPERATION )
716                 mwindow->paste_automation();
717         return 1;
718 }
719
720 ClearKeyframes::ClearKeyframes(MWindow *mwindow)
721  : BC_MenuItem(_("Clear keyframes"), _("Shift-Del"), DELETE)
722 {
723         set_shift();
724         this->mwindow = mwindow;
725 }
726
727 int ClearKeyframes::handle_event()
728 {
729         if( mwindow->session->current_operation == NO_OPERATION )
730                 mwindow->clear_automation();
731         return 1;
732 }
733
734
735
736 StraightenKeyframes::StraightenKeyframes(MWindow *mwindow)
737  : BC_MenuItem(_("Change to linear"))
738 {
739         this->mwindow = mwindow;
740 }
741
742 int StraightenKeyframes::handle_event()
743 {
744         mwindow->set_automation_mode(FloatAuto::LINEAR);
745         return 1;
746 }
747
748
749
750
751 BendKeyframes::BendKeyframes(MWindow *mwindow)
752  : BC_MenuItem(_("Change to smooth"))
753 {
754         this->mwindow = mwindow;
755 }
756
757 int BendKeyframes::handle_event()
758 {
759         mwindow->set_automation_mode(FloatAuto::SMOOTH);
760         return 1;
761 }
762
763
764
765 KeyframeCurveType::KeyframeCurveType(MWindow *mwindow)
766  : BC_MenuItem(_("Create curve type..."))
767 {
768         this->mwindow = mwindow;
769         this->curve_menu = 0;
770 }
771 KeyframeCurveType::~KeyframeCurveType()
772 {
773 }
774
775 void KeyframeCurveType::create_objects()
776 {
777         add_submenu(curve_menu = new KeyframeCurveTypeMenu(this));
778         for( int i=FloatAuto::SMOOTH; i<=FloatAuto::FREE; ++i ) {
779                 KeyframeCurveTypeItem *curve_type_item = new KeyframeCurveTypeItem(i, this);
780                 curve_menu->add_submenuitem(curve_type_item);
781         }
782 }
783
784 void KeyframeCurveType::update(int curve_type)
785 {
786         for( int i=0; i<curve_menu->total_items(); ++i ) {
787                 KeyframeCurveTypeItem *curve_type_item = (KeyframeCurveTypeItem *)curve_menu->get_item(i);
788                 curve_type_item->set_checked(curve_type_item->type == curve_type);
789         }
790 }
791
792 int KeyframeCurveType::handle_event()
793 {
794         return 1;
795 }
796
797 KeyframeCurveTypeMenu::KeyframeCurveTypeMenu(KeyframeCurveType *menu_item)
798  : BC_SubMenu()
799 {
800         this->menu_item = menu_item;
801 }
802 KeyframeCurveTypeMenu::~KeyframeCurveTypeMenu()
803 {
804 }
805
806 KeyframeCurveTypeItem::KeyframeCurveTypeItem(int type, KeyframeCurveType *main_item)
807  : BC_MenuItem(FloatAuto::curve_name(type))
808 {
809         this->type = type;
810         this->main_item = main_item;
811 }
812 KeyframeCurveTypeItem::~KeyframeCurveTypeItem()
813 {
814 }
815
816 int KeyframeCurveTypeItem::handle_event()
817 {
818         main_item->update(type);
819         main_item->mwindow->set_keyframe_type(type);
820         return 1;
821 }
822
823
824 CutDefaultKeyframe::CutDefaultKeyframe(MWindow *mwindow)
825  : BC_MenuItem(_("Cut default keyframe"), _("Alt-x"), 'x')
826 {
827         set_alt();
828         this->mwindow = mwindow;
829 }
830
831 int CutDefaultKeyframe::handle_event()
832 {
833         if( mwindow->session->current_operation == NO_OPERATION )
834                 mwindow->cut_default_keyframe();
835         return 1;
836 }
837
838 CopyDefaultKeyframe::CopyDefaultKeyframe(MWindow *mwindow)
839  : BC_MenuItem(_("Copy default keyframe"), _("Alt-c"), 'c')
840 {
841         set_alt();
842         this->mwindow = mwindow;
843 }
844
845 int CopyDefaultKeyframe::handle_event()
846 {
847         if( mwindow->session->current_operation == NO_OPERATION )
848                 mwindow->copy_default_keyframe();
849         return 1;
850 }
851
852 PasteDefaultKeyframe::PasteDefaultKeyframe(MWindow *mwindow)
853  : BC_MenuItem(_("Paste default keyframe"), _("Alt-v"), 'v')
854 {
855         set_alt();
856         this->mwindow = mwindow;
857 }
858
859 int PasteDefaultKeyframe::handle_event()
860 {
861         if( mwindow->session->current_operation == NO_OPERATION )
862                 mwindow->paste_default_keyframe();
863         return 1;
864 }
865
866 ClearDefaultKeyframe::ClearDefaultKeyframe(MWindow *mwindow)
867  : BC_MenuItem(_("Clear default keyframe"), _("Alt-Del"), DELETE)
868 {
869         set_alt();
870         this->mwindow = mwindow;
871 }
872
873 int ClearDefaultKeyframe::handle_event()
874 {
875         if( mwindow->session->current_operation == NO_OPERATION )
876                 mwindow->clear_default_keyframe();
877         return 1;
878 }
879
880 Cut::Cut(MWindow *mwindow)
881  : BC_MenuItem(_("Split | Cut"), "x", 'x')
882 {
883         this->mwindow = mwindow;
884 }
885
886 int Cut::handle_event()
887 {
888         if( mwindow->session->current_operation == NO_OPERATION )
889                 mwindow->cut();
890         return 1;
891 }
892
893 Copy::Copy(MWindow *mwindow)
894  : BC_MenuItem(_("Copy"), "c", 'c')
895 {
896         this->mwindow = mwindow;
897 }
898
899 int Copy::handle_event()
900 {
901         if( mwindow->session->current_operation == NO_OPERATION )
902                 mwindow->copy();
903         return 1;
904 }
905
906 Paste::Paste(MWindow *mwindow)
907  : BC_MenuItem(_("Paste"), "v", 'v')
908 {
909         this->mwindow = mwindow;
910 }
911
912 int Paste::handle_event()
913 {
914         if( mwindow->session->current_operation == NO_OPERATION )
915                 mwindow->paste();
916         return 1;
917 }
918
919 EditClearSubMenu::EditClearSubMenu(BC_MenuItem *menu_item)
920  : BC_SubMenu()
921 {
922         this->menu_item = menu_item;
923 }
924 EditClearSubMenu::~EditClearSubMenu()
925 {
926 }
927
928 EditClearMenu::EditClearMenu(MWindow *mwindow)
929  : BC_MenuItem(_("Clear..."))
930 {
931         this->mwindow = mwindow;
932         this->clear_sub_menu = 0;
933 }
934 EditClearMenu::~EditClearMenu()
935 {
936 }
937
938 void EditClearMenu::create_objects()
939 {
940         add_submenu(clear_sub_menu = new EditClearSubMenu(this));
941         clear_sub_menu->add_item(new Clear(mwindow));
942         clear_sub_menu->add_item(new MuteSelection(mwindow));
943         clear_sub_menu->add_item(new ClearSelect(mwindow));
944         clear_sub_menu->add_item(new ClearLabels(mwindow));
945         clear_sub_menu->add_item(new ClearHardEdges(mwindow));
946 };
947
948 Clear::Clear(MWindow *mwindow)
949  : BC_MenuItem(_("Clear"), _("Del"), DELETE)
950 {
951         this->mwindow = mwindow;
952 }
953
954 int Clear::handle_event()
955 {
956         if( mwindow->session->current_operation == NO_OPERATION ) {
957                 mwindow->clear_entry();
958         }
959         return 1;
960 }
961
962 PasteSilence::PasteSilence(MWindow *mwindow)
963  : BC_MenuItem(_("Paste silence"), _("Shift-Space"), ' ')
964 {
965         this->mwindow = mwindow;
966         set_shift();
967 }
968
969 int PasteSilence::handle_event()
970 {
971         if( mwindow->session->current_operation == NO_OPERATION )
972                 mwindow->paste_silence();
973         return 1;
974 }
975
976 SelectAll::SelectAll(MWindow *mwindow)
977  : BC_MenuItem(_("Select All"), "a", 'a')
978 {
979         this->mwindow = mwindow;
980 }
981
982 int SelectAll::handle_event()
983 {
984         if( mwindow->session->current_operation == NO_OPERATION )
985                 mwindow->select_all();
986         return 1;
987 }
988
989 ClearHardEdges::ClearHardEdges(MWindow *mwindow) : BC_MenuItem(_("Clear Hard Edges"))
990 {
991         this->mwindow = mwindow;
992 }
993
994 int ClearHardEdges::handle_event()
995 {
996         mwindow->clear_hard_edges();
997         return 1;
998 }
999
1000 ClearLabels::ClearLabels(MWindow *mwindow) : BC_MenuItem(_("Clear labels"))
1001 {
1002         this->mwindow = mwindow;
1003 }
1004
1005 int ClearLabels::handle_event()
1006 {
1007         mwindow->clear_labels();
1008         return 1;
1009 }
1010
1011 ClearSelect::ClearSelect(MWindow *mwindow) : BC_MenuItem(_("Clear Select"),"Ctrl-Shift-A",'A')
1012 {
1013         set_ctrl(1);
1014         set_shift(1);
1015         this->mwindow = mwindow;
1016 }
1017
1018 int ClearSelect::handle_event()
1019 {
1020         mwindow->clear_select();
1021         return 1;
1022 }
1023
1024 CutCommercials::CutCommercials(MWindow *mwindow) : BC_MenuItem(_("Cut ads"))
1025 {
1026         this->mwindow = mwindow;
1027 }
1028
1029 int CutCommercials::handle_event()
1030 {
1031         mwindow->cut_commercials();
1032         return 1;
1033 }
1034
1035 DetachTransitions::DetachTransitions(MWindow *mwindow)
1036  : BC_MenuItem(_("Detach transitions"))
1037 {
1038         this->mwindow = mwindow;
1039 }
1040
1041 int DetachTransitions::handle_event()
1042 {
1043         mwindow->detach_transitions();
1044         return 1;
1045 }
1046
1047 MuteSelection::MuteSelection(MWindow *mwindow)
1048  : BC_MenuItem(_("Mute Region"), "m", 'm')
1049 {
1050         this->mwindow = mwindow;
1051 }
1052
1053 int MuteSelection::handle_event()
1054 {
1055         if( mwindow->session->current_operation == NO_OPERATION )
1056                 mwindow->mute_selection();
1057         return 1;
1058 }
1059
1060
1061 TrimSelection::TrimSelection(MWindow *mwindow)
1062  : BC_MenuItem(_("Trim Selection"))
1063 {
1064         this->mwindow = mwindow;
1065 }
1066
1067 int TrimSelection::handle_event()
1068 {
1069         mwindow->trim_selection();
1070         return 1;
1071 }
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084 // ============================================= audio
1085
1086 AddAudioTrack::AddAudioTrack(MWindow *mwindow)
1087  : BC_MenuItem(_("Add track"), "t", 't')
1088 {
1089         this->mwindow = mwindow;
1090 }
1091
1092 int AddAudioTrack::handle_event()
1093 {
1094         if( mwindow->session->current_operation == NO_OPERATION )
1095                 mwindow->add_audio_track_entry(0, 0);
1096         return 1;
1097 }
1098
1099 DeleteAudioTrack::DeleteAudioTrack(MWindow *mwindow)
1100  : BC_MenuItem(_("Delete track"))
1101 {
1102         this->mwindow = mwindow;
1103 }
1104
1105 int DeleteAudioTrack::handle_event()
1106 {
1107         return 1;
1108 }
1109
1110 DefaultATransition::DefaultATransition(MWindow *mwindow)
1111  : BC_MenuItem(_("Default Transition"), "u", 'u')
1112 {
1113         this->mwindow = mwindow;
1114 }
1115
1116 int DefaultATransition::handle_event()
1117 {
1118         if( mwindow->session->current_operation == NO_OPERATION )
1119                 mwindow->paste_audio_transition();
1120         return 1;
1121 }
1122
1123
1124 MapAudio1::MapAudio1(MWindow *mwindow)
1125  : BC_MenuItem(_("Map 1:1"))
1126 {
1127         this->mwindow = mwindow;
1128 }
1129
1130 int MapAudio1::handle_event()
1131 {
1132         mwindow->map_audio(MWindow::AUDIO_1_TO_1);
1133         return 1;
1134 }
1135
1136 MapAudio2::MapAudio2(MWindow *mwindow)
1137  : BC_MenuItem(_("Map 5.1:2"))
1138 {
1139         this->mwindow = mwindow;
1140 }
1141
1142 int MapAudio2::handle_event()
1143 {
1144         mwindow->map_audio(MWindow::AUDIO_5_1_TO_2);
1145         return 1;
1146 }
1147
1148
1149
1150
1151 // ============================================= video
1152
1153
1154 AddVideoTrack::AddVideoTrack(MWindow *mwindow)
1155  : BC_MenuItem(_("Add track"), _("Shift-T"), 'T')
1156 {
1157         set_shift();
1158         this->mwindow = mwindow;
1159 }
1160
1161 int AddVideoTrack::handle_event()
1162 {
1163         if( mwindow->session->current_operation == NO_OPERATION )
1164                 mwindow->add_video_track_entry(1, 0);
1165         return 1;
1166 }
1167
1168
1169 DeleteVideoTrack::DeleteVideoTrack(MWindow *mwindow)
1170  : BC_MenuItem(_("Delete track"))
1171 {
1172         this->mwindow = mwindow;
1173 }
1174
1175 int DeleteVideoTrack::handle_event()
1176 {
1177         return 1;
1178 }
1179
1180
1181
1182 ResetTranslation::ResetTranslation(MWindow *mwindow)
1183  : BC_MenuItem(_("Reset Translation"))
1184 {
1185         this->mwindow = mwindow;
1186 }
1187
1188 int ResetTranslation::handle_event()
1189 {
1190         return 1;
1191 }
1192
1193
1194
1195 DefaultVTransition::DefaultVTransition(MWindow *mwindow)
1196  : BC_MenuItem(_("Default Transition"), _("Shift-U"), 'U')
1197 {
1198         set_shift();
1199         this->mwindow = mwindow;
1200 }
1201
1202 int DefaultVTransition::handle_event()
1203 {
1204         if( mwindow->session->current_operation == NO_OPERATION )
1205                 mwindow->paste_video_transition();
1206         return 1;
1207 }
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222 // ============================================ settings
1223
1224 DeleteTracks::DeleteTracks(MWindow *mwindow)
1225  : BC_MenuItem(_("Delete tracks"))
1226 {
1227         this->mwindow = mwindow;
1228 }
1229
1230 int DeleteTracks::handle_event()
1231 {
1232         mwindow->delete_tracks();
1233         return 1;
1234 }
1235
1236 DeleteFirstTrack::DeleteFirstTrack(MWindow *mwindow)
1237  : BC_MenuItem(_("Delete first track"), "Shift-D", 'D')
1238 {
1239         set_shift(1);
1240         this->mwindow = mwindow;
1241 }
1242
1243 int DeleteFirstTrack::handle_event()
1244 {
1245         if( mwindow->session->current_operation == NO_OPERATION ) {
1246                 Track *track = mwindow->edl->tracks->first;
1247                 if( track ) mwindow->delete_track(track);
1248         }
1249         return 1;
1250 }
1251
1252 DeleteLastTrack::DeleteLastTrack(MWindow *mwindow)
1253  : BC_MenuItem(_("Delete last track"), "Ctrl-d", 'd')
1254 {
1255         set_ctrl(1);
1256         this->mwindow = mwindow;
1257 }
1258
1259 int DeleteLastTrack::handle_event()
1260 {
1261         if( mwindow->session->current_operation == NO_OPERATION ) {
1262                 Track *track = mwindow->edl->tracks->last;
1263                 if( track ) mwindow->delete_track(track);
1264         }
1265         return 1;
1266 }
1267
1268 MoveTracksUp::MoveTracksUp(MWindow *mwindow)
1269  : BC_MenuItem(_("Move tracks up"), _("Shift-Up"), UP)
1270 {
1271         this->mwindow = mwindow;
1272         set_shift();
1273 }
1274
1275 int MoveTracksUp::handle_event()
1276 {
1277         if( mwindow->session->current_operation == NO_OPERATION )
1278                 mwindow->move_tracks_up();
1279         return 1;
1280 }
1281
1282 MoveTracksDown::MoveTracksDown(MWindow *mwindow)
1283  : BC_MenuItem(_("Move tracks down"), _("Shift-Down"), DOWN)
1284 {
1285         set_shift(); this->mwindow = mwindow;
1286 }
1287
1288 int MoveTracksDown::handle_event()
1289 {
1290         if( mwindow->session->current_operation == NO_OPERATION )
1291                 mwindow->move_tracks_down();
1292         return 1;
1293 }
1294
1295
1296 SwapTracksUp::SwapTracksUp(MWindow *mwindow)
1297  : BC_MenuItem(_("Swap tracks up"), 0, UP)
1298 {
1299         this->mwindow = mwindow;
1300         set_shift();
1301 }
1302
1303 int SwapTracksUp::handle_event()
1304 {
1305         if( mwindow->session->current_operation == NO_OPERATION )
1306                 mwindow->swap_tracks_up();
1307         return 1;
1308 }
1309
1310 SwapTracksDown::SwapTracksDown(MWindow *mwindow)
1311  : BC_MenuItem(_("Swap tracks down"), 0, DOWN)
1312 {
1313         set_shift(); this->mwindow = mwindow;
1314 }
1315
1316 int SwapTracksDown::handle_event()
1317 {
1318         if( mwindow->session->current_operation == NO_OPERATION )
1319                 mwindow->swap_tracks_down();
1320         return 1;
1321 }
1322
1323
1324
1325
1326 ConcatenateTracks::ConcatenateTracks(MWindow *mwindow)
1327  : BC_MenuItem(_("Concatenate tracks"))
1328 {
1329         set_shift();
1330         this->mwindow = mwindow;
1331 }
1332
1333 int ConcatenateTracks::handle_event()
1334 {
1335         mwindow->concatenate_tracks();
1336         return 1;
1337 }
1338
1339
1340
1341
1342
1343 LoopPlayback::LoopPlayback(MWindow *mwindow)
1344  : BC_MenuItem(_("Loop Playback"), _("Shift-L"), 'L')
1345 {
1346         this->mwindow = mwindow;
1347         set_checked(mwindow->edl->local_session->loop_playback);
1348         set_shift();
1349 }
1350
1351 int LoopPlayback::handle_event()
1352 {
1353         if( mwindow->session->current_operation == NO_OPERATION ) {
1354                 mwindow->toggle_loop_playback();
1355                 set_checked(mwindow->edl->local_session->loop_playback);
1356         }
1357         return 1;
1358 }
1359
1360
1361
1362 // ============================================= subtitle
1363
1364
1365 AddSubttlTrack::AddSubttlTrack(MWindow *mwindow)
1366  : BC_MenuItem(_("Add subttl"), _("Shift-Y"), 'Y')
1367 {
1368         set_shift();
1369         this->mwindow = mwindow;
1370 }
1371
1372 int AddSubttlTrack::handle_event()
1373 {
1374         if( mwindow->session->current_operation == NO_OPERATION )
1375                 mwindow->add_subttl_track_entry(1, 0);
1376         return 1;
1377 }
1378
1379 PasteSubttl::PasteSubttl(MWindow *mwindow)
1380  : BC_MenuItem(_("paste subttl"), "y", 'y')
1381 {
1382         this->mwindow = mwindow;
1383 }
1384
1385 int PasteSubttl::handle_event()
1386 {
1387         if( mwindow->session->current_operation == NO_OPERATION )
1388                 mwindow->gui->swindow->paste_subttl();
1389         return 1;
1390 }
1391
1392
1393 SetBRenderActive::SetBRenderActive(MWindow *mwindow)
1394  : BC_MenuItem(_("Toggle background rendering"),_("Shift-G"),'G')
1395 {
1396         this->mwindow = mwindow;
1397         set_shift(1);
1398 }
1399
1400 int SetBRenderActive::handle_event()
1401 {
1402         if( mwindow->session->current_operation == NO_OPERATION ) {
1403                 int v = mwindow->brender_active ? 0 : 1;
1404                 set_checked(v);
1405                 mwindow->set_brender_active(v);
1406         }
1407         return 1;
1408 }
1409
1410
1411 LabelsFollowEdits::LabelsFollowEdits(MWindow *mwindow)
1412  : BC_MenuItem(_("Edit labels"))
1413 {
1414         this->mwindow = mwindow;
1415         set_checked(mwindow->edl->session->labels_follow_edits);
1416 }
1417
1418 int LabelsFollowEdits::handle_event()
1419 {
1420         set_checked(get_checked() ^ 1);
1421         mwindow->set_labels_follow_edits(get_checked());
1422         return 1;
1423 }
1424
1425
1426
1427
1428 PluginsFollowEdits::PluginsFollowEdits(MWindow *mwindow)
1429  : BC_MenuItem(_("Edit effects"))
1430 {
1431         this->mwindow = mwindow;
1432         set_checked(mwindow->edl->session->plugins_follow_edits);
1433 }
1434
1435 int PluginsFollowEdits::handle_event()
1436 {
1437         set_checked(get_checked() ^ 1);
1438         mwindow->edl->session->plugins_follow_edits = get_checked();
1439         return 1;
1440 }
1441
1442
1443
1444
1445 KeyframesFollowEdits::KeyframesFollowEdits(MWindow *mwindow)
1446  : BC_MenuItem(_("Keyframes follow edits"))
1447 {
1448         this->mwindow = mwindow;
1449         set_checked(mwindow->edl->session->autos_follow_edits);
1450 }
1451
1452 int KeyframesFollowEdits::handle_event()
1453 {
1454         mwindow->edl->session->autos_follow_edits ^= 1;
1455         set_checked(!get_checked());
1456         return 1;
1457 }
1458
1459
1460 CursorOnFrames::CursorOnFrames(MWindow *mwindow)
1461  : BC_MenuItem(_("Align cursor on frames"),_("Ctrl-a"),'a')
1462 {
1463         this->mwindow = mwindow;
1464         set_checked(mwindow->edl->session->cursor_on_frames);
1465         set_ctrl(1);
1466 }
1467
1468 int CursorOnFrames::handle_event()
1469 {
1470         mwindow->edl->session->cursor_on_frames = !mwindow->edl->session->cursor_on_frames;
1471         set_checked(mwindow->edl->session->cursor_on_frames);
1472         return 1;
1473 }
1474
1475
1476 TypelessKeyframes::TypelessKeyframes(MWindow *mwindow)
1477  : BC_MenuItem(_("Typeless keyframes"))
1478 {
1479         this->mwindow = mwindow;
1480         set_checked(mwindow->edl->session->typeless_keyframes);
1481 }
1482
1483 int TypelessKeyframes::handle_event()
1484 {
1485         mwindow->edl->session->typeless_keyframes = !mwindow->edl->session->typeless_keyframes;
1486         set_checked(mwindow->edl->session->typeless_keyframes);
1487         return 1;
1488 }
1489
1490
1491 ScrubSpeed::ScrubSpeed(MWindow *mwindow)
1492  : BC_MenuItem(_("Slow Shuttle"))
1493 {
1494         this->mwindow = mwindow;
1495 }
1496
1497 int ScrubSpeed::handle_event()
1498 {
1499         if(mwindow->edl->session->scrub_speed == .5)
1500         {
1501                 mwindow->edl->session->scrub_speed = 2;
1502                 set_text(_("Slow Shuttle"));
1503         }
1504         else
1505         {
1506                 mwindow->edl->session->scrub_speed = .5;
1507                 set_text(_("Fast Shuttle"));
1508         }
1509         return 1;
1510 }
1511
1512 SaveSettingsNow::SaveSettingsNow(MWindow *mwindow)
1513  : BC_MenuItem(_("Save settings now"),_("Ctrl-s"),'s')
1514 {
1515         this->mwindow = mwindow;
1516         set_ctrl(1);
1517 }
1518
1519 int SaveSettingsNow::handle_event()
1520 {
1521         mwindow->save_defaults();
1522         mwindow->save_backup();
1523         mwindow->gui->show_message(_("Saved settings."));
1524         return 1;
1525 }
1526
1527
1528
1529 // ============================================ window
1530
1531
1532
1533
1534
1535 ShowVWindow::ShowVWindow(MWindow *mwindow)
1536  : BC_MenuItem(_("Show Viewer"))
1537 {
1538         this->mwindow = mwindow;
1539         set_checked(mwindow->session->show_vwindow);
1540 }
1541 int ShowVWindow::handle_event()
1542 {
1543         mwindow->gui->unlock_window();
1544         mwindow->show_vwindow();
1545         mwindow->gui->lock_window("ShowVWindow::handle_event");
1546         return 1;
1547 }
1548
1549 ShowAWindow::ShowAWindow(MWindow *mwindow)
1550  : BC_MenuItem(_("Show Resources"))
1551 {
1552         this->mwindow = mwindow;
1553         set_checked(mwindow->session->show_awindow);
1554 }
1555 int ShowAWindow::handle_event()
1556 {
1557         mwindow->gui->unlock_window();
1558         mwindow->show_awindow();
1559         mwindow->gui->lock_window("ShowAWindow::handle_event");
1560         return 1;
1561 }
1562
1563 ShowCWindow::ShowCWindow(MWindow *mwindow)
1564  : BC_MenuItem(_("Show Compositor"))
1565 {
1566         this->mwindow = mwindow;
1567         set_checked(mwindow->session->show_cwindow);
1568 }
1569 int ShowCWindow::handle_event()
1570 {
1571         mwindow->gui->unlock_window();
1572         mwindow->show_cwindow();
1573         mwindow->gui->lock_window("ShowCWindow::handle_event");
1574         return 1;
1575 }
1576
1577
1578 ShowGWindow::ShowGWindow(MWindow *mwindow)
1579  : BC_MenuItem(_("Show Overlays"), _("Ctrl-0"), '0')
1580 {
1581         this->mwindow = mwindow;
1582         set_ctrl(1);
1583         set_checked(mwindow->session->show_gwindow);
1584 }
1585 int ShowGWindow::handle_event()
1586 {
1587         if( mwindow->session->current_operation == NO_OPERATION ) {
1588                 mwindow->gui->unlock_window();
1589                 if( !mwindow->session->show_gwindow )
1590                         mwindow->show_gwindow();
1591                 else
1592                         mwindow->hide_gwindow();
1593                 mwindow->gui->lock_window("ShowGWindow::handle_event");
1594                 set_checked(mwindow->session->show_gwindow);
1595         }
1596         return 1;
1597 }
1598
1599
1600 ShowLWindow::ShowLWindow(MWindow *mwindow)
1601  : BC_MenuItem(_("Show Levels"))
1602 {
1603         this->mwindow = mwindow;
1604         set_checked(mwindow->session->show_lwindow);
1605 }
1606 int ShowLWindow::handle_event()
1607 {
1608         mwindow->gui->unlock_window();
1609         mwindow->show_lwindow();
1610         mwindow->gui->lock_window("ShowLWindow::handle_event");
1611         return 1;
1612 }
1613
1614 TileWindows::TileWindows(MWindow *mwindow, const char *item_title, int config,
1615                 const char *hot_keytext, int hot_key)
1616  : BC_MenuItem(item_title, hot_keytext, hot_key)
1617 {
1618         this->mwindow = mwindow;
1619         this->config = config;
1620         if( hot_key ) set_ctrl(1);
1621 }
1622 int TileWindows::handle_event()
1623 {
1624         if( mwindow->session->current_operation == NO_OPERATION ) {
1625                 int window_config = config >= 0 ? config :
1626                         mwindow->session->window_config;
1627                 if( mwindow->tile_windows(window_config) ) {
1628                         mwindow->restart_status = 1;
1629                         mwindow->gui->set_done(0);
1630                 }
1631         }
1632         return 1;
1633 }
1634
1635 SplitX::SplitX(MWindow *mwindow)
1636  : BC_MenuItem(_("Split X pane"), _("Ctrl-1"), '1')
1637 {
1638         this->mwindow = mwindow;
1639         set_ctrl(1);
1640         set_checked(mwindow->gui->pane[TOP_RIGHT_PANE] != 0);
1641 }
1642 int SplitX::handle_event()
1643 {
1644         if( mwindow->session->current_operation == NO_OPERATION )
1645                 mwindow->split_x();
1646         return 1;
1647 }
1648
1649 SplitY::SplitY(MWindow *mwindow)
1650  : BC_MenuItem(_("Split Y pane"), _("Ctrl-2"), '2')
1651 {
1652         this->mwindow = mwindow;
1653         set_ctrl(1);
1654         set_checked(mwindow->gui->pane[BOTTOM_LEFT_PANE] != 0);
1655 }
1656 int SplitY::handle_event()
1657 {
1658         if( mwindow->session->current_operation == NO_OPERATION )
1659                 mwindow->split_y();
1660         return 1;
1661 }
1662
1663
1664 MixerItems::MixerItems(MWindow *mwindow)
1665  : BC_MenuItem(_("Mixers..."))
1666 {
1667         this->mwindow = mwindow;
1668 }
1669
1670 void MixerItems::create_objects()
1671 {
1672         BC_SubMenu *mixer_submenu = new BC_SubMenu();
1673         add_submenu(mixer_submenu);
1674         mixer_submenu->add_submenuitem(new MixerViewer(this));
1675         mixer_submenu->add_submenuitem(new TileMixers(this));
1676         mixer_submenu->add_submenuitem(new AlignMixers(this));
1677         mixer_submenu->add_submenuitem(new MixMasters(this));
1678 }
1679
1680 int MixerItems::activate_submenu()
1681 {
1682         BC_SubMenu *mixer_submenu = (BC_SubMenu *)get_submenu();
1683         int k = mixer_submenu->total_items();
1684         while( --k >= 0 ) {
1685                 MixerItem *mixer_item = (MixerItem *)mixer_submenu->get_item(k);
1686                 if( mixer_item->idx < 0 ) continue;
1687                 mixer_submenu->del_item(mixer_item);
1688         }
1689         int n = mwindow->edl->mixers.size();
1690         for( int i=0; i<n; ++i ) {
1691                 Mixer *mixer = mwindow->edl->mixers[i];
1692                 if( !mixer ) continue;
1693                 MixerItem *mixer_item = new MixerItem(this, mixer->title, mixer->idx);
1694                 mixer_submenu->add_submenuitem(mixer_item);
1695         }
1696         return BC_MenuItem::activate_submenu();
1697 }
1698
1699 MixerItem::MixerItem(MixerItems *mixer_items, const char *text, int idx)
1700  : BC_MenuItem(text)
1701 {
1702         this->mixer_items = mixer_items;
1703         this->idx = idx;
1704 }
1705
1706 MixerItem::MixerItem(MixerItems *mixer_items, const char *text, const char *hotkey_text, int hotkey)
1707  : BC_MenuItem(text, hotkey_text, hotkey)
1708 {
1709         this->mixer_items = mixer_items;
1710         this->idx = -1;
1711 }
1712
1713 int MixerItem::handle_event()
1714 {
1715         if( idx < 0 ) return 0;
1716         MWindow *mwindow = mixer_items->mwindow;
1717         Mixer *mixer = mwindow->edl->mixers.get_mixer(idx);
1718         if( !mixer ) return 0;
1719         ZWindow *zwindow = mwindow->get_mixer(idx);
1720         if( !zwindow )
1721                 zwindow = mwindow->get_mixer(mixer);
1722         if( !zwindow->zgui ) {
1723                 zwindow->set_title(mixer->title);
1724                 zwindow->start();
1725         }
1726         zwindow->zgui->lock_window("MixerItem::handle_event");
1727         zwindow->zgui->raise_window();
1728         zwindow->zgui->unlock_window();
1729         mwindow->refresh_mixers();
1730         return 1;
1731 }
1732
1733 MixerViewer::MixerViewer(MixerItems *mixer_items)
1734  : MixerItem(mixer_items, _("Mixer Viewer"), _("Shift-M"), 'M')
1735 {
1736         set_shift(1);
1737 }
1738
1739 int MixerViewer::handle_event()
1740 {
1741         MWindow *mwindow = mixer_items->mwindow;
1742         mwindow->start_mixer();
1743         return 1;
1744 }
1745
1746 TileMixers::TileMixers(MixerItems *mixer_items)
1747  : MixerItem(mixer_items, _("Tile mixers"), "Alt-t", 't')
1748 {
1749         set_alt();
1750 }
1751
1752 int TileMixers::handle_event()
1753 {
1754         MWindow *mwindow = mixer_items->mwindow;
1755         mwindow->tile_mixers();
1756         return 1;
1757 }
1758
1759 AlignMixers::AlignMixers(MixerItems *mixer_items)
1760  : MixerItem(mixer_items, _("Align mixers"), "", 0)
1761 {
1762 }
1763
1764 int AlignMixers::handle_event()
1765 {
1766         MWindow *mwindow = mixer_items->mwindow;
1767         int wx, wy;
1768         mwindow->gui->get_abs_cursor(wx, wy);
1769         mwindow->mixers_align->start_dialog(wx, wy);
1770         return 1;
1771 }
1772
1773 MixMasters::MixMasters(MixerItems *mixer_items)
1774  : MixerItem(mixer_items, _("Mix masters"), "", 0)
1775 {
1776 }
1777
1778 int MixMasters::handle_event()
1779 {
1780         MWindow *mwindow = mixer_items->mwindow;
1781         mwindow->mix_masters();
1782         return 1;
1783 }
1784
1785
1786 AlignTimecodes::AlignTimecodes(MWindow *mwindow)
1787  : BC_MenuItem(_("Align Timecodes"))
1788 {
1789         this->mwindow = mwindow;
1790 }
1791
1792 int AlignTimecodes::handle_event()
1793 {
1794         mwindow->align_timecodes();
1795         return 1;
1796 }
1797
1798
1799 LoadLayoutItem::LoadLayoutItem(LoadLayout *load_layout, const char *text, int idx, int hotkey)
1800  : BC_MenuItem(text, "", hotkey)
1801 {
1802         this->idx = idx;
1803         this->load_layout = load_layout;
1804         if( hotkey ) {
1805                 char hot_txt[BCSTRLEN];
1806                 sprintf(hot_txt, _("Ctrl-Shift+F%d"), hotkey-KEY_F1+1);
1807                 set_ctrl();  set_shift();
1808                 set_hotkey_text(hot_txt);
1809         }
1810 }
1811
1812
1813 int LoadLayoutItem::handle_event()
1814 {
1815 // key_press hotkey skips over activate_submenu
1816         load_layout->update();
1817         MWindow *mwindow = load_layout->mwindow;
1818         switch( load_layout->action ) {
1819         case LAYOUT_LOAD:
1820                 mwindow->load_layout(layout_file);
1821                 break;
1822         case LAYOUT_SAVE: {
1823                 int wx = 0, wy = 0;
1824                 mwindow->gui->get_abs_cursor(wx, wy);
1825                 load_layout->layout_dialog->start_confirm_dialog(wx, wy, idx);
1826                 break; }
1827         }
1828         return 1;
1829 }
1830
1831 LoadLayout::LoadLayout(MWindow *mwindow, const char *text, int action)
1832  : BC_MenuItem(text)
1833 {
1834         this->mwindow = mwindow;
1835         this->action = action;
1836         this->layout_dialog = new LoadLayoutDialog(this);
1837 }
1838
1839 LoadLayout::~LoadLayout()
1840 {
1841         delete layout_dialog;
1842 }
1843
1844 void LoadLayout::create_objects()
1845 {
1846         BC_SubMenu *layout_submenu = new BC_SubMenu();
1847         add_submenu(layout_submenu);
1848
1849         for( int i=0; i<LAYOUTS_MAX; ++i ) {
1850                 char text[BCSTRLEN];
1851                 sprintf(text, _("Layout %d"), i+1);
1852                 LoadLayoutItem *item = new LoadLayoutItem(this, text, i,
1853                                 action==LAYOUT_LOAD ? KEY_F1+i : 0);
1854                 layout_submenu->add_submenuitem(item);
1855         }
1856 }
1857
1858 int LoadLayout::activate_submenu()
1859 {
1860         update();
1861         return BC_MenuItem::activate_submenu();
1862 }
1863
1864 void LoadLayout::update()
1865 {
1866         FileSystem fs;
1867         fs.set_filter("layout*_rc");
1868         int ret = fs.update(File::get_config_path());
1869         int sz = !ret ? fs.dir_list.size() : 0;
1870         BC_SubMenu *layout_submenu = get_submenu();
1871
1872         for( int i=0; i<LAYOUTS_MAX; ++i ) {
1873                 LoadLayoutItem* item = (LoadLayoutItem *)
1874                         layout_submenu->get_item(i);
1875                 char layout_text[BCSTRLEN];  layout_text[0] = 0;
1876                 int n = sz, id = i+1;
1877                 while( --n >= 0 ) {
1878                         char *np = fs.dir_list[n]->name;
1879                         char *cp = strrchr(np, '_'), *bp = 0;
1880                         int no = strtol(np+6, &bp, 10);
1881                         if( no != id || !bp ) continue;
1882                         if( bp == cp ) {  n = -1;  break; }
1883                         if( *bp++ == '_' && bp < cp && !strcmp(cp, "_rc") ) {
1884                                 int k = cp - bp;  char *tp = layout_text;
1885                                 if( k > LAYOUT_NAME_LEN ) k = LAYOUT_NAME_LEN;
1886                                 while( --k >= 0 ) *tp++ = *bp++;
1887                                 *tp = 0;
1888                                 break;
1889                         }
1890                 }
1891                 strcpy(item->layout_text, layout_text);
1892                 char *lp = item->layout_file;
1893                 int k = sprintf(lp, LAYOUT_FILE, id);
1894                 if( n >= 0 && layout_text[0] )
1895                         sprintf(lp + k-2, "%s_rc", layout_text);
1896                 else
1897                         sprintf(layout_text, _("Layout %d"), id);
1898                 item->set_text(layout_text);
1899         }
1900 }
1901
1902 LoadLayoutDialog::LoadLayoutDialog(LoadLayout *load_layout)
1903 {
1904         this->load_layout = load_layout;
1905         wx = 0;  wy = 0;
1906         idx = -1;
1907         lgui = 0;
1908 }
1909
1910 LoadLayoutDialog::~LoadLayoutDialog()
1911 {
1912         close_window();
1913 }
1914
1915 void LoadLayoutDialog::handle_done_event(int result)
1916 {
1917         if( result ) return;
1918         char layout_file[BCSTRLEN];
1919         BC_SubMenu *layout_submenu = load_layout->get_submenu();
1920         LoadLayoutItem* item =
1921                 (LoadLayoutItem *) layout_submenu->get_item(idx);
1922         snprintf(layout_file, sizeof(layout_file), "%s", item->layout_file);
1923         load_layout->mwindow->delete_layout(layout_file);
1924         int k = sprintf(layout_file, LAYOUT_FILE, idx+1);
1925         const char *text = lgui->name_text->get_text();
1926         if( text[0] )
1927                 snprintf(layout_file + k-2, sizeof(layout_file)-k+2, "%s_rc", text);
1928         load_layout->mwindow->save_layout(layout_file);
1929 }
1930
1931 void LoadLayoutDialog::handle_close_event(int result)
1932 {
1933         lgui = 0;
1934 }
1935
1936 BC_Window *LoadLayoutDialog::new_gui()
1937 {
1938         lgui = new LoadLayoutConfirm(this, wx, wy);
1939         lgui->create_objects();
1940         return lgui;
1941 }
1942
1943 void LoadLayoutDialog::start_confirm_dialog(int wx, int wy, int idx)
1944 {
1945         close_window();
1946         this->wx = wx;  this->wy = wy;
1947         this->idx = idx;
1948         start();
1949 }
1950
1951 LoadLayoutNameText::LoadLayoutNameText(LoadLayoutConfirm *confirm,
1952                 int x, int y, int w, const char *text)
1953  : BC_TextBox(x, y, w, 1, text)
1954 {
1955         this->confirm = confirm;
1956 }
1957
1958 LoadLayoutNameText::~LoadLayoutNameText()
1959 {
1960 }
1961
1962 int LoadLayoutNameText::handle_event()
1963 {
1964         const char *text = get_text();
1965         int len = strlen(text), k = 0;
1966         char new_text[BCTEXTLEN];
1967         for( int i=0; i<len; ++i ) {
1968                 int ch = text[i];
1969                 if( (ch>='A' && ch<='Z') || (ch>='a' && ch<='z') ||
1970                     (ch>='0' && ch<='9') || ch=='_' )
1971                         new_text[k++] = ch;
1972         }
1973         new_text[k] = 0;  len = k;
1974         int i = len - LAYOUT_NAME_LEN;
1975         if( i >= 0 ) {
1976                 k = 0;
1977                 while( i < len ) new_text[k++] = new_text[i++];
1978                 new_text[k] = 0;
1979         }
1980         update(new_text);
1981         return 1;
1982 }
1983
1984 LoadLayoutConfirm::LoadLayoutConfirm(LoadLayoutDialog *layout_dialog, int x, int y)
1985  : BC_Window(_(PROGRAM_NAME ": Layout"), x, y, xS(300),yS(140), xS(300),yS(140), 0)
1986 {
1987         this->layout_dialog = layout_dialog;
1988 }
1989
1990 LoadLayoutConfirm::~LoadLayoutConfirm()
1991 {
1992 }
1993
1994 void LoadLayoutConfirm::create_objects()
1995 {
1996         int xs10 = xS(10), xs20 = xS(20);
1997         int ys10 = yS(10);
1998         lock_window("LoadLayoutConfirm::create_objects");
1999         int x = xs10, y = ys10;
2000         BC_SubMenu *layout_submenu = layout_dialog->load_layout->get_submenu();
2001         LoadLayoutItem *item = (LoadLayoutItem *)
2002                 layout_submenu->get_item(layout_dialog->idx);
2003         BC_Title *title;
2004         add_subwindow(title = new BC_Title(x, y, _("Layout Name:")));
2005         int x1 = x + title->get_w() + xs10;
2006         add_subwindow(title = new BC_Title(x1, y, item->get_text()));
2007         y += title->get_h() + ys10;
2008         add_subwindow(name_text = new LoadLayoutNameText(this,
2009                 x, y, get_w()-x-xs20, item->layout_text));
2010         y += name_text->get_h();
2011         x1 = x + xS(80);
2012         char legend[BCTEXTLEN];
2013         sprintf(legend, _("a-z,A-Z,0-9_ only, %dch max"), LAYOUT_NAME_LEN);
2014         add_subwindow(title = new BC_Title(x1, y, legend));
2015         add_subwindow(new BC_OKButton(this));
2016         add_subwindow(new BC_CancelButton(this));
2017         unlock_window();
2018 }
2019
2020
2021 LoadRecentItem::LoadRecentItem(const char *path)
2022 {
2023         this->path = cstrdup(path);
2024 }
2025
2026 LoadRecentItem::~LoadRecentItem()
2027 {
2028         delete [] path;
2029 }
2030
2031 int LoadRecentItems::add_load(char *path)
2032 {
2033 // test for existing copy
2034         FileSystem fs;
2035         char name[BCTEXTLEN], text[BCTEXTLEN];
2036         fs.extract_name(name, path);
2037         int loads_total = size();
2038         int ret = 0, k = loads_total;
2039         LoadRecentItem *load_item = 0;
2040
2041         for( int i=0; !ret && i<loads_total; ++i ) {
2042                 load_item = get(i);
2043                 fs.extract_name(text, load_item->path);
2044                 if( strcmp(name, text) ) continue;
2045                 k = i;  ret = 1; // already exists, move to top
2046         }
2047         if( !ret ) { // adding a new one
2048                 while( loads_total >= TOTAL_LOADS )
2049                         remove_object_number(--loads_total);
2050                 insert(new LoadRecentItem(path), 0);
2051         }
2052         else if( k > 0 ) { // cycle loads
2053                 while( --k >= 0 ) set(k+1, get(k));
2054                 set(0, load_item);
2055         }
2056         return ret;
2057 }
2058
2059 LoadRecentItems::LoadRecentItems()
2060 {
2061 }
2062
2063 LoadRecentItems::~LoadRecentItems()
2064 {
2065         remove_all_objects();
2066 }
2067
2068 LoadRecent::LoadRecent(MWindow *mwindow, MainMenu *main_menu)
2069  : BC_MenuItem(_("Load Recent..."))
2070 {
2071         this->mwindow = mwindow;
2072         this->main_menu = main_menu;
2073         total_items = 0;
2074 }
2075 LoadRecent::~LoadRecent()
2076 {
2077 }
2078
2079 void LoadRecent::create_objects()
2080 {
2081         add_submenu(submenu = new LoadRecentSubMenu(this));
2082 }
2083
2084 LoadPrevious *LoadRecent::get_next_item()
2085 {
2086         int k = total_items++;
2087         if( k < submenu->total_items() )
2088                 return (LoadPrevious *)submenu->get_item(k);
2089         LoadPrevious *load_prev = new LoadPrevious(mwindow, main_menu->load_file);
2090         submenu->add_item(load_prev);
2091         return load_prev;
2092 }
2093
2094 int LoadRecent::activate_submenu()
2095 {
2096         total_items = 0;
2097         scan_items(1);
2098         if( total_items > 0 ) {
2099                 LoadPrevious *load_prev = get_next_item();
2100                 load_prev->set_text("-");
2101                 load_prev->set_path("");
2102         }
2103         scan_items(0);
2104         while( total_items < submenu->total_items() )
2105                 submenu->del_item(0);
2106         return BC_MenuItem::activate_submenu();
2107 }
2108
2109 void LoadRecent::scan_items(int use_xml)
2110 {
2111         FileSystem fs;
2112         int loads_total = main_menu->load.size();
2113         for( int i=0; i<loads_total; ++i ) {
2114                 LoadRecentItem *recent = main_menu->load[i];
2115                 char name[BCTEXTLEN];
2116                 fs.extract_name(name, recent->path);
2117                 const char *cp = strrchr(name, '.');
2118                 if( !cp || strcasecmp(cp+1,"xml") ? use_xml : !use_xml ) continue;
2119                 LoadPrevious *load_prev = get_next_item();
2120                 load_prev->set_text(name);
2121                 load_prev->set_path(recent->path);
2122         }
2123 }
2124
2125 LoadRecentSubMenu::LoadRecentSubMenu(LoadRecent *load_recent)
2126  : BC_SubMenu()
2127 {
2128         this->load_recent = load_recent;
2129 }
2130
2131 LoadRecentSubMenu::~LoadRecentSubMenu()
2132 {
2133 }
2134