r602: Fix baver's code... don't insert timecode when show_tc is not set
[cinelerra_cv/mob.git] / cinelerra / menueffects.C
bloba87fb27a369cbd29d4a575eca158366358091d0e
1 #include "asset.h"
2 #include "confirmsave.h"
3 #include "defaults.h"
4 #include "edl.h"
5 #include "edlsession.h"
6 #include "errorbox.h"
7 #include "file.h"
8 #include "formatcheck.h"
9 #include "indexfile.h"
10 #include "keyframe.h"
11 #include "keys.h"
12 #include "labels.h"
13 #include "language.h"
14 #include "loadmode.h"
15 #include "localsession.h"
16 #include "mainmenu.h"
17 #include "mainsession.h"
18 #include "mainundo.h"
19 #include "mwindow.h"
20 #include "mwindowgui.h"
21 #include "menueffects.h"
22 #include "playbackengine.h"
23 #include "pluginarray.h"
24 #include "pluginserver.h"
25 #include "preferences.h"
26 #include "render.h"
27 #include "sighandler.h"
28 #include "theme.h"
29 #include "tracks.h"
33 MenuEffects::MenuEffects(MWindow *mwindow)
34  : BC_MenuItem(_("Render effect..."))
36         this->mwindow = mwindow;
39 MenuEffects::~MenuEffects()
44 int MenuEffects::handle_event()
46         thread->set_title("");
47         thread->start();
54 MenuEffectPacket::MenuEffectPacket(char *path, int64_t start, int64_t end)
56         this->start = start;
57         this->end = end;
58         strcpy(this->path, path);
61 MenuEffectPacket::~MenuEffectPacket()
70 MenuEffectThread::MenuEffectThread(MWindow *mwindow)
72         this->mwindow = mwindow;
73         sprintf(title, "");
76 MenuEffectThread::~MenuEffectThread()
84 int MenuEffectThread::set_title(char *title)
86         strcpy(this->title, title);
89 // for recent effect menu items and running new effects
90 // prompts for an effect if title is blank
91 void MenuEffectThread::run()
93 // get stuff from main window
94         ArrayList<PluginServer*> *plugindb = mwindow->plugindb;
95         Defaults *defaults = mwindow->defaults;
96         ArrayList<BC_ListBoxItem*> plugin_list;
97         ArrayList<PluginServer*> local_plugindb;
98         char string[1024];
99         int i;
100         int result = 0;
101 // Default configuration
102         Asset default_asset;
103 // Output
104         ArrayList<Asset*> assets;
107 // check for recordable tracks
108         if(!get_recordable_tracks(&default_asset))
109         {
110                 sprintf(string, _("No recordable tracks specified."));
111                 ErrorBox error(PROGRAM_NAME ": Error");
112                 error.create_objects(string);
113                 error.run_window();
114                 return;
115         }
117 // check for plugins
118         if(!plugindb->total)
119         {
120                 sprintf(string, _("No plugins available."));
121                 ErrorBox error(PROGRAM_NAME ": Error");
122                 error.create_objects(string);
123                 error.run_window();
124                 return;
125         }
128 // get default attributes for output file
129 // used after completion
130         get_derived_attributes(&default_asset, defaults);
131 //      to_tracks = defaults->get("RENDER_EFFECT_TO_TRACKS", 1);
132         load_mode = defaults->get("RENDER_EFFECT_LOADMODE", LOAD_PASTE);
133         strategy = defaults->get("RENDER_EFFECT_STRATEGY", SINGLE_PASS);
135 // get plugin information
136         int need_plugin;
137         if(!strlen(title)) 
138                 need_plugin = 1; 
139         else 
140                 need_plugin = 0;
142 // generate a list of plugins for the window
143         if(need_plugin)
144         {
145                 mwindow->create_plugindb(default_asset.audio_data, 
146                         default_asset.video_data, 
147                         -1, 
148                         0,
149                         0,
150                         local_plugindb);
152                 for(int i = 0; i < local_plugindb.total; i++)
153                 {
154                         plugin_list.append(new BC_ListBoxItem(_(local_plugindb.values[i]->title)));
155                 }
156         }
158 // find out which effect to run and get output file
159         int plugin_number, format_error = 0;
161         do
162         {
163                 {
164                         MenuEffectWindow window(mwindow, 
165                                 this, 
166                                 need_plugin ? &plugin_list : 0, 
167                                 &default_asset);
168                         window.create_objects();
169                         result = window.run_window();
170                         plugin_number = window.result;
171                 }
173                 if(!result)
174                 {
175                         FormatCheck format_check(&default_asset);
176                         format_error = format_check.check_format();
177                 }
178         }while(format_error && !result);
180 // save defaults
181         save_derived_attributes(&default_asset, defaults);
182         defaults->update("RENDER_EFFECT_LOADMODE", load_mode);
183         defaults->update("RENDER_EFFECT_STRATEGY", strategy);
184         mwindow->save_defaults();
186 // get plugin server to use and delete the plugin list
187         PluginServer *plugin_server = 0;
188         PluginServer *plugin = 0;
189         if(need_plugin)
190         {
191                 plugin_list.remove_all_objects();
192                 if(plugin_number > -1)
193                 {
194                         plugin_server = local_plugindb.values[plugin_number];
195                         strcpy(title, plugin_server->title);
196                 }
197         }
198         else
199         {
200                 for(int i = 0; i < plugindb->total && !plugin_server; i++)
201                 {
202                         if(!strcmp(plugindb->values[i]->title, title))
203                         {
204                                 plugin_server = plugindb->values[i];
205                                 plugin_number = i;
206                         }
207                 }
208         }
210 // Update the  most recently used effects and copy the plugin server.
211         if(plugin_server)
212         {
213                 plugin = new PluginServer(*plugin_server);
214                 fix_menu(title);
215         }
217         if(!result && !strlen(default_asset.path))
218         {
219                 result = 1;        // no output path given
220                 ErrorBox error(PROGRAM_NAME ": Error");
221                 error.create_objects(_("No output file specified."));
222                 error.run_window();
223         }
225         if(!result && plugin_number < 0)
226         {
227                 result = 1;        // no output path given
228                 ErrorBox error(PROGRAM_NAME ": Error");
229                 error.create_objects(_("No effect selected."));
230                 error.run_window();
231         }
233 // Configuration for realtime plugins.
234         KeyFrame plugin_data;        
236 // get selection to render
237 // Range
238         double total_start, total_end;
240         total_start = mwindow->edl->local_session->get_selectionstart();
243         if(mwindow->edl->local_session->get_selectionend() == 
244                 mwindow->edl->local_session->get_selectionstart())
245                 total_end = mwindow->edl->tracks->total_playable_length();
246         else
247                 total_end = mwindow->edl->local_session->get_selectionend();
251 // get native units for range
252         total_start = to_units(total_start, 0);
253         total_end = to_units(total_end, 1);
257 // Trick boundaries in case of a non-realtime synthesis plugin
258         if(plugin && 
259                 !plugin->realtime && 
260                 total_end == total_start) total_end = total_start + 1;
262 // Units are now in the track's units.
263         int64_t total_length = (int64_t)total_end - (int64_t)total_start;
264 // length of output file
265         int64_t output_start, output_end;        
267         if(!result && total_length <= 0)
268         {
269                 result = 1;        // no output path given
270                 ErrorBox error(PROGRAM_NAME ": Error");
271                 error.create_objects(_("No selected range to process."));
272                 error.run_window();
273         }
275 // ========================= get keyframe from user
276         if(!result)
277         {
278 // ========================= realtime plugin 
279 // no get_parameters
280                 if(plugin->realtime)
281                 {
282 // Open a prompt GUI
283                         MenuEffectPrompt prompt(mwindow);
284                         prompt.create_objects();
285                         char title[BCTEXTLEN];
286                         sprintf(title, PROGRAM_NAME ": %s", plugin->title);
288 // Open the plugin GUI
289                         plugin->set_mwindow(mwindow);
290                         plugin->set_keyframe(&plugin_data);
291                         plugin->set_prompt(&prompt);
292                         plugin->open_plugin(0, mwindow->preferences, mwindow->edl, 0, -1);
293 // Must set parameters since there is no plugin object to draw from.
294                         plugin->get_parameters((int64_t)total_start,
295                                 (int64_t)total_end,
296                                 1);
297                         plugin->show_gui();
299 // wait for user input
300                         result = prompt.run_window();
302 // Close plugin.
303                         plugin->save_data(&plugin_data);
304                         delete plugin;
305                         default_asset.sample_rate = mwindow->edl->session->sample_rate;
306                         default_asset.frame_rate = mwindow->edl->session->frame_rate;
307                         realtime = 1;
308                 }
309                 else
310 // ============================non realtime plugin 
311                 {
312                         plugin->set_mwindow(mwindow);
313                         plugin->open_plugin(0, mwindow->preferences, mwindow->edl, 0, -1);
314                         result = plugin->get_parameters((int64_t)total_start, 
315                                 (int64_t)total_end, 
316                                 get_recordable_tracks(&default_asset));
317 // some plugins can change the sample rate and the frame rate
320                         if(!result)
321                         {
322                                 default_asset.sample_rate = plugin->get_samplerate();
323                                 default_asset.frame_rate = plugin->get_framerate();
324                         }
325                         delete plugin;
326                         realtime = 0;
327                 }
329 // Should take from first recordable track
330                 default_asset.width = mwindow->edl->session->output_w;
331                 default_asset.height = mwindow->edl->session->output_h;
332         }
334 // Process the total length in fragments
335         ArrayList<MenuEffectPacket*> packets;
336         if(!result)
337         {
338                 Label *current_label = mwindow->edl->labels->first;
339                 mwindow->stop_brender();
341                 int current_number;
342                 int number_start;
343                 int total_digits;
344                 Render::get_starting_number(default_asset.path, 
345                         current_number,
346                         number_start, 
347                         total_digits);
351 // Construct all packets for single overwrite confirmation
352                 for(int64_t fragment_start = (int64_t)total_start, fragment_end;
353                         fragment_start < (int64_t)total_end;
354                         fragment_start = fragment_end)
355                 {
356 // Get fragment end
357                         if(strategy == FILE_PER_LABEL || strategy == FILE_PER_LABEL_FARM)
358                         {
359                                 while(current_label  &&
360                                         to_units(current_label->position, 0) <= fragment_start)
361                                         current_label = current_label->next;
362                                 if(!current_label)
363                                         fragment_end = (int64_t)total_end;
364                                 else
365                                         fragment_end = to_units(current_label->position, 0);
366                         }
367                         else
368                         {
369                                 fragment_end = (int64_t)total_end;
370                         }
372 // Get path
373                         char path[BCTEXTLEN];
374                         if(strategy == FILE_PER_LABEL || strategy == FILE_PER_LABEL_FARM) 
375                                 Render::create_filename(path, 
376                                         default_asset.path, 
377                                         current_number,
378                                         total_digits,
379                                         number_start);
380                         else
381                                 strcpy(path, default_asset.path);
382                         current_number++;
384                         MenuEffectPacket *packet = new MenuEffectPacket(path, 
385                                 fragment_start,
386                                 fragment_end);
387                         packets.append(packet);
388                 }
391 // Test existence of files
392                 ArrayList<char*> paths;
393                 for(int i = 0; i < packets.total; i++)
394                 {
395                         paths.append(packets.values[i]->path);
396                 }
397                 result = ConfirmSave::test_files(mwindow, &paths);
398                 paths.remove_all();
399         }
403         for(int current_packet = 0; 
404                 current_packet < packets.total && !result; 
405                 current_packet++)
406         {
407                 Asset *asset = new Asset(default_asset);
408                 MenuEffectPacket *packet = packets.values[current_packet];
409                 int64_t fragment_start = packet->start;
410                 int64_t fragment_end = packet->end;
411                 strcpy(asset->path, packet->path);
413                 assets.append(asset);
414                 File *file = new File;
416 // Open the output file after getting the information because the sample rate
417 // is needed here.
418                 if(!result)
419                 {
420 // open output file in write mode
421                         file->set_processors(mwindow->preferences->processors);
422                         if(file->open_file(mwindow->plugindb, 
423                                 asset, 
424                                 0, 
425                                 1, 
426                                 mwindow->edl->session->sample_rate, 
427                                 mwindow->edl->session->frame_rate))
428                         {
429 // open failed
430                                 sprintf(string, _("Couldn't open %s"), asset->path);
431                                 ErrorBox error(PROGRAM_NAME ": Error");
432                                 error.create_objects(string);
433                                 error.run_window();
434                                 result = 1;
435                         }
436                         else
437                         {
438                                 mwindow->sighandler->push_file(file);
439                                 IndexFile::delete_index(mwindow->preferences, asset);
440                         }
441                 }
443 // run plugins
444                 if(!result)
445                 {
446 // position file
447                         output_start = 0;
449                         PluginArray *plugin_array;
450                         plugin_array = create_plugin_array();
452                         plugin_array->start_plugins(mwindow, 
453                                 mwindow->edl, 
454                                 plugin_server, 
455                                 &plugin_data,
456                                 fragment_start,
457                                 fragment_end,
458                                 file);
459                         plugin_array->run_plugins();
461                         plugin_array->stop_plugins();
462                         mwindow->sighandler->pull_file(file);
463                         file->close_file();
464                         asset->audio_length = file->asset->audio_length;
465                         asset->video_length = file->asset->video_length;
466                         delete plugin_array;
467                 }
469                 delete file;
470         }
472         packets.remove_all_objects();
474 // paste output to tracks
475         if(!result && load_mode != LOAD_NOTHING)
476         {
477                 mwindow->gui->lock_window();
478                 mwindow->undo->update_undo_before(title, LOAD_ALL);
480                 if(load_mode == LOAD_PASTE)
481                         mwindow->clear(0);
482                 mwindow->load_assets(&assets,
483                         -1,
484                         load_mode,
485                         0,
486                         0,
487                         mwindow->edl->session->labels_follow_edits, 
488                         mwindow->edl->session->plugins_follow_edits);
491                 mwindow->save_backup();
492                 mwindow->undo->update_undo_after();
496                 mwindow->restart_brender();
497                 mwindow->update_plugin_guis();
498                 mwindow->gui->update(1, 
499                         2,
500                         1,
501                         1,
502                         1,
503                         1,
504                         0);
505                 mwindow->sync_parameters(CHANGE_ALL);
506                 mwindow->gui->unlock_window();
507         }
509         assets.remove_all_objects();
515 MenuEffectItem::MenuEffectItem(MenuEffects *menueffect, char *string)
516  : BC_MenuItem(string)
518         this->menueffect = menueffect; 
520 int MenuEffectItem::handle_event()
522         menueffect->thread->set_title(get_text());
523         menueffect->thread->start();
537 MenuEffectWindow::MenuEffectWindow(MWindow *mwindow, 
538         MenuEffectThread *menueffects, 
539         ArrayList<BC_ListBoxItem*> *plugin_list, 
540         Asset *asset)
541  : BC_Window(PROGRAM_NAME ": Render effect", 
542                 mwindow->gui->get_abs_cursor_x(1),
543                 mwindow->gui->get_abs_cursor_y(1) - mwindow->session->menueffect_h / 2,
544                 mwindow->session->menueffect_w, 
545                 mwindow->session->menueffect_h, 
546                 580,
547                 350,
548                 1,
549                 0,
550                 1)
552         this->menueffects = menueffects; 
553         this->plugin_list = plugin_list; 
554         this->asset = asset;
555         this->mwindow = mwindow;
558 MenuEffectWindow::~MenuEffectWindow()
560         delete format_tools;
562 // 
563 // int MenuEffectWindow::calculate_w(int use_plugin_list)
564 // {
565 //      return use_plugin_list ? 580 : 420;
566 // }
567 // 
568 // int MenuEffectWindow::calculate_h(int use_plugin_list)
569 // {
570 //      return 350;
571 // }
574 int MenuEffectWindow::create_objects()
576         int x, y;
577         result = -1;
578         mwindow->theme->get_menueffect_sizes(plugin_list ? 1 : 0);
580 // only add the list if needed
581         if(plugin_list)
582         {
583                 add_subwindow(list_title = new BC_Title(mwindow->theme->menueffect_list_x, 
584                         mwindow->theme->menueffect_list_y, 
585                         _("Select an effect")));
586                 add_subwindow(list = new MenuEffectWindowList(this, 
587                         mwindow->theme->menueffect_list_x, 
588                         mwindow->theme->menueffect_list_y + 20, 
589                         mwindow->theme->menueffect_list_w,
590                         mwindow->theme->menueffect_list_h,
591                         plugin_list));
592         }
594         add_subwindow(file_title = new BC_Title(mwindow->theme->menueffect_file_x, 
595                 mwindow->theme->menueffect_file_y, 
596                 (char*)((menueffects->strategy == FILE_PER_LABEL  || menueffects->strategy == FILE_PER_LABEL_FARM) ? 
597                         _("Select the first file to render to:") : 
598                         _("Select a file to render to:"))));
600         x = mwindow->theme->menueffect_tools_x;
601         y = mwindow->theme->menueffect_tools_y;
602         format_tools = new FormatTools(mwindow,
603                                         this, 
604                                         asset);
605         format_tools->create_objects(x, 
606                                         y, 
607                                         asset->audio_data, 
608                                         asset->video_data, 
609                                         0, 
610                                         0, 
611                                         0,
612                                         1,
613                                         0,
614                                         0,
615                                         &menueffects->strategy,
616                                         0);
618         loadmode = new LoadMode(mwindow, 
619                 this, 
620                 x, 
621                 y, 
622                 &menueffects->load_mode, 
623                 1);
624         loadmode->create_objects();
626         add_subwindow(new MenuEffectWindowOK(this));
627         add_subwindow(new MenuEffectWindowCancel(this));
628         show_window();
629         flush();
630         return 0;
633 int MenuEffectWindow::resize_event(int w, int h)
635         mwindow->session->menueffect_w = w;
636         mwindow->session->menueffect_h = h;
637         mwindow->theme->get_menueffect_sizes(plugin_list ? 1 : 0);
639         if(plugin_list)
640         {
641                 list_title->reposition_window(mwindow->theme->menueffect_list_x, 
642                         mwindow->theme->menueffect_list_y);
643                 list->reposition_window(mwindow->theme->menueffect_list_x, 
644                         mwindow->theme->menueffect_list_y + 20, 
645                         mwindow->theme->menueffect_list_w,
646                         mwindow->theme->menueffect_list_h);
647         }
649         file_title->reposition_window(mwindow->theme->menueffect_file_x, 
650                 mwindow->theme->menueffect_file_y);
651         int x = mwindow->theme->menueffect_tools_x;
652         int y = mwindow->theme->menueffect_tools_y;
653         format_tools->reposition_window(x, y);
654         loadmode->reposition_window(x, y);
659 MenuEffectWindowOK::MenuEffectWindowOK(MenuEffectWindow *window)
660  : BC_OKButton(window)
662         this->window = window; 
665 int MenuEffectWindowOK::handle_event() 
667         if(window->plugin_list) 
668                 window->result = window->list->get_selection_number(0, 0); 
669         
670         window->set_done(0); 
673 int MenuEffectWindowOK::keypress_event() 
675         if(get_keypress() == 13) 
676         { 
677                 handle_event(); 
678                 return 1; 
679         }
680         return 0;
683 MenuEffectWindowCancel::MenuEffectWindowCancel(MenuEffectWindow *window)
684  : BC_CancelButton(window)
686         this->window = window; 
689 int MenuEffectWindowCancel::handle_event() 
691         window->set_done(1); 
694 int MenuEffectWindowCancel::keypress_event() 
696         if(get_keypress() == ESC) 
697         { 
698                 handle_event(); 
699                 return 1; 
700         }
701         return 0;
704 MenuEffectWindowList::MenuEffectWindowList(MenuEffectWindow *window, 
705         int x, 
706         int y, 
707         int w, 
708         int h, 
709         ArrayList<BC_ListBoxItem*> *plugin_list)
710  : BC_ListBox(x, 
711                 y, 
712                 w, 
713                 h, 
714                 LISTBOX_TEXT, 
715                 plugin_list)
717         this->window = window; 
720 int MenuEffectWindowList::handle_event() 
722         window->result = get_selection_number(0, 0);
723         window->set_done(0); 
728 MenuEffectPrompt::MenuEffectPrompt(MWindow *mwindow)
729  : BC_Window(PROGRAM_NAME ": Effect Prompt", 
730                 mwindow->gui->get_abs_cursor_x(1) - 260 / 2,
731                 mwindow->gui->get_abs_cursor_y(1) - 300,
732                 260, 
733                 80, 
734                 260,
735                 80,
736                 0,
737                 0,
738                 1)
742 MenuEffectPrompt::~MenuEffectPrompt()
746 int MenuEffectPrompt::create_objects()
748         int x = 10, y = 10;
749         add_subwindow(new BC_Title(x, y, _("Set up effect panel and hit \"OK\"")));
750         y += 20;
751         add_subwindow(new BC_OKButton(this));
752         x = get_w() - 100;
753         add_subwindow(new BC_CancelButton(this));
754         show_window();
755         raise_window();
756         flush();
757         return 0;