r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / cinelerra / menueffects.C
blob494017aa0ad63883156b606e669ff50ac13e3b12
1 #include "assets.h"
2 #include "defaults.h"
3 #include "edl.h"
4 #include "edlsession.h"
5 #include "errorbox.h"
6 #include "file.h"
7 #include "formatcheck.h"
8 #include "indexfile.h"
9 #include "keyframe.h"
10 #include "keys.h"
11 #include "loadmode.h"
12 #include "localsession.h"
13 #include "mainmenu.h"
14 #include "mainsession.h"
15 #include "mainundo.h"
16 #include "mwindow.h"
17 #include "mwindowgui.h"
18 #include "menueffects.h"
19 #include "neworappend.h"
20 #include "playbackengine.h"
21 #include "pluginarray.h"
22 #include "pluginserver.h"
23 #include "preferences.h"
24 #include "render.h"
25 #include "sighandler.h"
26 #include "theme.h"
27 #include "tracks.h"
29 #include <libintl.h>
30 #define _(String) gettext(String)
31 #define gettext_noop(String) String
32 #define N_(String) gettext_noop (String)
35 MenuEffects::MenuEffects(MWindow *mwindow)
36  : BC_MenuItem(_("Render effect..."))
38         this->mwindow = mwindow;
41 MenuEffects::~MenuEffects()
46 int MenuEffects::handle_event()
48         thread->set_title("");
49         thread->start();
56 MenuEffectPacket::MenuEffectPacket()
58         start = end = 0.0;
59         path[0] = 0;
62 MenuEffectPacket::~MenuEffectPacket()
71 MenuEffectThread::MenuEffectThread(MWindow *mwindow)
73         this->mwindow = mwindow;
74         sprintf(title, "");
77 MenuEffectThread::~MenuEffectThread()
85 int MenuEffectThread::set_title(char *title)
87         strcpy(this->title, title);
90 // for recent effect menu items and running new effects
91 // prompts for an effect if title is blank
92 void MenuEffectThread::run()
94 // get stuff from main window
95         ArrayList<PluginServer*> *plugindb = mwindow->plugindb;
96         Defaults *defaults = mwindow->defaults;
97         ArrayList<BC_ListBoxItem*> plugin_list;
98         ArrayList<PluginServer*> local_plugindb;
99         char string[1024];
100         int i;
101         int result = 0;
102 // Default configuration
103         Asset default_asset;
104 // Output
105         ArrayList<Asset*> assets;
107 //printf("MenuEffectThread::run 1\n");
108 //      sprintf(string, "");
109 //      defaults->get("EFFECTPATH", string);
111 // check for recordable tracks
112         if(!get_recordable_tracks(&default_asset))
113         {
114                 sprintf(string, _("No recordable tracks specified."));
115                 ErrorBox error(PROGRAM_NAME ": Error");
116                 error.create_objects(string);
117                 error.run_window();
118                 return;
119         }
121 //printf("MenuEffectThread::run 1\n");
122 // check for plugins
123         if(!plugindb->total)
124         {
125                 sprintf(string, _("No plugins available."));
126                 ErrorBox error(PROGRAM_NAME ": Error");
127                 error.create_objects(string);
128                 error.run_window();
129                 return;
130         }
132 //printf("MenuEffectThread::run 1\n");
134 //printf("MenuEffectThread::run 1\n");
135 // get default attributes for output file
136 // used after completion
137         get_derived_attributes(&default_asset, defaults);
138 //      to_tracks = defaults->get("RENDER_EFFECT_TO_TRACKS", 1);
139         load_mode = defaults->get("RENDER_EFFECT_LOADMODE", LOAD_PASTE);
140         strategy = defaults->get("RENDER_EFFECT_STRATEGY", SINGLE_PASS);
142 //printf("MenuEffectThread::run 1\n");
143 // get plugin information
144         int need_plugin;
145         if(!strlen(title)) 
146                 need_plugin = 1; 
147         else 
148                 need_plugin = 0;
150 //printf("MenuEffectThread::run 1\n");
151 // generate a list of plugins for the window
152         if(need_plugin)
153         {
154                 mwindow->create_plugindb(default_asset.audio_data, 
155                         default_asset.video_data, 
156                         -1, 
157                         0,
158                         0,
159                         local_plugindb);
161 //printf("MenuEffectThread::run 1\n");
162                 for(int i = 0; i < local_plugindb.total; i++)
163                 {
164                         plugin_list.append(new BC_ListBoxItem(local_plugindb.values[i]->title, BLACK));
165                 }
166         }
168 //printf("MenuEffectThread::run 2\n");
169 // find out which effect to run and get output file
170         int plugin_number, format_error = 0;
172         do
173         {
174                 {
175                         MenuEffectWindow window(mwindow, 
176                                 this, 
177                                 need_plugin ? &plugin_list : 0, 
178                                 &default_asset);
179                         window.create_objects();
180                         result = window.run_window();
181                         plugin_number = window.result;
182                 }
184 //printf("MenuEffectThread::run 3\n");
185                 if(!result)
186                 {
187                         FormatCheck format_check(&default_asset);
188                         format_error = format_check.check_format();
189                 }
190         }while(format_error && !result);
192 //printf("MenuEffectThread::run 4\n");
193 // save defaults
194         save_derived_attributes(&default_asset, defaults);
195         defaults->update("RENDER_EFFECT_LOADMODE", load_mode);
196         defaults->update("RENDER_EFFECT_STRATEGY", strategy);
197         mwindow->save_defaults();
199 //printf("MenuEffectThread::run 5\n");
200 // get plugin server to use and delete the plugin list
201         PluginServer *plugin_server = 0;
202         PluginServer *plugin = 0;
203         if(need_plugin)
204         {
205                 plugin_list.remove_all_objects();
206                 if(plugin_number > -1)
207                 {
208                         plugin_server = local_plugindb.values[plugin_number];
209                         strcpy(title, plugin_server->title);
210                 }
211         }
212         else
213         {
214                 for(int i = 0; i < plugindb->total && !plugin_server; i++)
215                 {
216                         if(!strcmp(plugindb->values[i]->title, title))
217                         {
218                                 plugin_server = plugindb->values[i];
219                                 plugin_number = i;
220                         }
221                 }
222         }
224 // Update the  most recently used effects and copy the plugin server.
225         if(plugin_server)
226         {
227                 plugin = new PluginServer(*plugin_server);
228                 fix_menu(title);
229         }
231 //printf("MenuEffectThread::run 6\n");
232         if(!result && !strlen(default_asset.path))
233         {
234                 result = 1;        // no output path given
235                 ErrorBox error(PROGRAM_NAME ": Error");
236                 error.create_objects(_("No output file specified."));
237                 error.run_window();
238         }
240         if(!result && plugin_number < 0)
241         {
242                 result = 1;        // no output path given
243                 ErrorBox error(PROGRAM_NAME ": Error");
244                 error.create_objects(_("No effect selected."));
245                 error.run_window();
246         }
247 //printf("MenuEffectThread::run 7\n");
249 // Configuration for realtime plugins.
250         KeyFrame plugin_data;        
251 //printf("MenuEffectThread::run 8\n");
253 // get selection to render
254 // Range
255         double total_start, total_end;
257 //printf("MenuEffectThread::run 9\n");
258         total_start = mwindow->edl->local_session->get_selectionstart();
261         if(mwindow->edl->local_session->get_selectionend() == 
262                 mwindow->edl->local_session->get_selectionstart())
263                 total_end = mwindow->edl->tracks->total_playable_length();
264         else
265                 total_end = mwindow->edl->local_session->get_selectionend();
269 //printf("MenuEffectThread::run 10\n");
270 // get native units for range
271         total_start = to_units(total_start, 0);
272         total_end = to_units(total_end, 1);
276 // Trick boundaries in case of a non-realtime synthesis plugin
277         if(plugin && 
278                 !plugin->realtime && 
279                 total_end == total_start) total_end = total_start + 1;
280 //printf("MenuEffectThread::run 11\n");
282 //printf("MenuEffectThread::run 1\n");
283 // Units are now in the track's units.
284         int64_t total_length = (int64_t)total_end - (int64_t)total_start;
285 // length of output file
286         int64_t output_start, output_end;        
288         if(!result && total_length <= 0)
289         {
290                 result = 1;        // no output path given
291                 ErrorBox error(PROGRAM_NAME ": Error");
292                 error.create_objects(_("No selected range to process."));
293                 error.run_window();
294         }
296 // ========================= get keyframe from user
297         if(!result)
298         {
299 // ========================= realtime plugin 
300 // no get_parameters
301                 if(plugin->realtime)
302                 {
303 // Open a prompt GUI
304 //printf("MenuEffectThread::run 10 %s\n", plugin->title);
305                         MenuEffectPrompt prompt(mwindow);
306                         prompt.create_objects();
307                         char title[1024];
308                         sprintf(title, PROGRAM_NAME ": %s", plugin->title);
309 //printf("MenuEffectThread::run 11 %s\n", plugin->title);
311 // Open the plugin GUI
312                         plugin->set_mwindow(mwindow);
313                         plugin->set_keyframe(&plugin_data);
314                         plugin->set_prompt(&prompt);
315 //printf("MenuEffectThread::run 11 %s\n", plugin->title);
316                         plugin->open_plugin(0, mwindow->edl, 0);
317 //printf("MenuEffectThread::run 11 %s\n", plugin->title);
318                         plugin->show_gui();
319 //printf("MenuEffectThread::run 12 %s\n", plugin->title);
321 // wait for user input
322                         result = prompt.run_window();
323 //printf("MenuEffectThread::run 13 %s\n", plugin->title);
325 // Close plugin.
326                         plugin->save_data(&plugin_data);
327 //printf("MenuEffectThread::run 13 %s\n", plugin->title);
328                         delete plugin;
329 //printf("MenuEffectThread::run 14\n");
330                         default_asset.sample_rate = mwindow->edl->session->sample_rate;
331                         default_asset.frame_rate = mwindow->edl->session->frame_rate;
332                         realtime = 1;
333                 }
334                 else
335 // ============================non realtime plugin 
336                 {
337 //printf("MenuEffectThread::run 15\n");
338                         plugin->set_mwindow(mwindow);
339 //printf("MenuEffectThread::run 16\n");
340                         plugin->open_plugin(0, mwindow->edl, 0);
341 //printf("MenuEffectThread::run 17\n");
342                         result = plugin->get_parameters();
343 // some plugins can change the sample rate and the frame rate
344 //printf("MenuEffectThread::run 18\n");
347                         if(!result)
348                         {
349                                 default_asset.sample_rate = plugin->get_samplerate();
350                                 default_asset.frame_rate = plugin->get_framerate();
351                         }
352 //printf("MenuEffectThread::run 19\n");
353                         delete plugin;
354                         realtime = 0;
355                 }
357 // Should take from first recordable track
358                 default_asset.width = mwindow->edl->session->output_w;
359                 default_asset.height = mwindow->edl->session->output_h;
360         }
362 //printf("MenuEffectThread::run 20\n");
363 // Process the total length in fragments
364         Label *current_label = mwindow->edl->labels->first;
365         mwindow->stop_brender();
367         int current_number;
368         int number_start;
369         int total_digits;
370         Render::get_starting_number(default_asset.path, 
371                 current_number,
372                 number_start, 
373                 total_digits);
374         for(int64_t fragment_start = (int64_t)total_start, fragment_end; 
375                 fragment_start < (int64_t)total_end && !result; 
376                 fragment_start = fragment_end)
377         {
378 // Get fragment end
379                 if(strategy == FILE_PER_LABEL || strategy == FILE_PER_LABEL_FARM)
380                 {
381                         while(current_label && 
382                                 to_units(current_label->position, 0) <= fragment_start)
383                                         current_label = current_label->next;
385                         if(!current_label)
386                                 fragment_end = (int64_t)total_end;
387                         else
388                                 fragment_end = to_units(current_label->position, 0);
389                 }
390                 else
391                 {
392                         fragment_end = (int64_t)total_end;
393                 }
395 // Create asset
396                 Asset *asset = new Asset(default_asset);
397                 if(strategy == FILE_PER_LABEL || strategy == FILE_PER_LABEL_FARM) 
398                         Render::create_filename(asset->path, 
399                                 default_asset.path, 
400                                 current_number,
401                                 total_digits,
402                                 number_start);
403                 current_number++;
405                 result = Render::test_existence(mwindow, asset);
407                 if(!result)
408                 {
409                         assets.append(asset);
410                         File *file = new File;
412 // Open the output file after getting the information because the sample rate
413 // is needed here.
414                         if(!result)
415                         {
416 // open output file in write mode
417                                 file->set_processors(mwindow->edl->session->smp + 1);
418                                 if(file->open_file(mwindow->plugindb, 
419                                         asset, 
420                                         0, 
421                                         1, 
422                                         mwindow->edl->session->sample_rate, 
423                                         mwindow->edl->session->frame_rate))
424                                 {
425 // open failed
426                                         sprintf(string, _("Couldn't open %s"), asset->path);
427                                         ErrorBox error(PROGRAM_NAME ": Error");
428                                         error.create_objects(string);
429                                         error.run_window();
430                                         result = 1;
431                                 }
432                                 else
433                                 {
434                                         mwindow->sighandler->push_file(file);
435                                         IndexFile::delete_index(mwindow->preferences, asset);
436                                 }
437                         }
439 //printf("MenuEffectThread::run 10\n");
440 // run plugins
441                         if(!result)
442                         {
443 // position file
444                                 output_start = 0;
446                                 PluginArray *plugin_array;
447                                 plugin_array = create_plugin_array();
449 //printf("MenuEffectThread::run 11\n");
450                                 plugin_array->start_plugins(mwindow, 
451                                         mwindow->edl, 
452                                         plugin_server, 
453                                         &plugin_data,
454                                         fragment_start,
455                                         fragment_end,
456                                         file);
457 //printf("MenuEffectThread::run 12\n");
458                                 plugin_array->run_plugins();
460 //printf("MenuEffectThread::run 13\n");
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 //printf("MenuEffectThread::run 14 %d %d\n", asset->audio_length, asset->video_length);
467                                 delete plugin_array;
468 //printf("MenuEffectThread::run 16\n");
469                         }
471                         delete file;
472                 }
473         }
474 //printf("MenuEffectThread::run 16 %d\n", result);
477 // paste output to tracks
478         if(!result && load_mode != LOAD_NOTHING)
479         {
480                 mwindow->gui->lock_window();
481 //printf("MenuEffectThread::run 17\n");
482                 mwindow->undo->update_undo_before(title, LOAD_ALL);
484 //printf("MenuEffectThread::run 18\n");
485                 if(load_mode == LOAD_PASTE)
486                         mwindow->clear(0);
487                 mwindow->load_assets(&assets,
488                         -1,
489                         load_mode,
490                         0,
491                         0,
492                         mwindow->edl->session->labels_follow_edits, 
493                         mwindow->edl->session->plugins_follow_edits);
495 //printf("MenuEffectThread::run 19\n");
497                 mwindow->save_backup();
498                 mwindow->undo->update_undo_after();
502                 mwindow->restart_brender();
503                 mwindow->update_plugin_guis();
504                 mwindow->gui->update(1, 
505                         2,
506                         1,
507                         1,
508                         0,
509                         1,
510                         0);
511                 mwindow->sync_parameters(CHANGE_ALL);
512 //printf("MenuEffectThread::run 22\n");
513                 mwindow->gui->unlock_window();
514 //printf("MenuEffectThread::run 23\n");
515         }
517         assets.remove_all_objects();
518 //printf("MenuEffectThread::run 24\n");
524 MenuEffectItem::MenuEffectItem(MenuEffects *menueffect, char *string)
525  : BC_MenuItem(string)
527         this->menueffect = menueffect; 
529 int MenuEffectItem::handle_event()
531         menueffect->thread->set_title(get_text());
532         menueffect->thread->start();
546 MenuEffectWindow::MenuEffectWindow(MWindow *mwindow, 
547         MenuEffectThread *menueffects, 
548         ArrayList<BC_ListBoxItem*> *plugin_list, 
549         Asset *asset)
550  : BC_Window(PROGRAM_NAME ": Render effect", 
551                 mwindow->gui->get_abs_cursor_x(),
552                 mwindow->gui->get_abs_cursor_y() - mwindow->session->menueffect_h / 2,
553                 mwindow->session->menueffect_w, 
554                 mwindow->session->menueffect_h, 
555                 580,
556                 350,
557                 1,
558                 0,
559                 1)
561         this->menueffects = menueffects; 
562         this->plugin_list = plugin_list; 
563         this->asset = asset;
564         this->mwindow = mwindow;
567 MenuEffectWindow::~MenuEffectWindow()
569         delete format_tools;
571 // 
572 // int MenuEffectWindow::calculate_w(int use_plugin_list)
573 // {
574 //      return use_plugin_list ? 580 : 420;
575 // }
576 // 
577 // int MenuEffectWindow::calculate_h(int use_plugin_list)
578 // {
579 //      return 350;
580 // }
583 int MenuEffectWindow::create_objects()
585         int x, y;
586         result = -1;
587         mwindow->theme->get_menueffect_sizes(plugin_list ? 1 : 0);
589 // only add the list if needed
590         if(plugin_list)
591         {
592                 add_subwindow(list_title = new BC_Title(mwindow->theme->menueffect_list_x, 
593                         mwindow->theme->menueffect_list_y, 
594                         _("Select an effect")));
595                 add_subwindow(list = new MenuEffectWindowList(this, 
596                         mwindow->theme->menueffect_list_x, 
597                         mwindow->theme->menueffect_list_y + 20, 
598                         mwindow->theme->menueffect_list_w,
599                         mwindow->theme->menueffect_list_h,
600                         plugin_list));
601         }
603         add_subwindow(file_title = new BC_Title(mwindow->theme->menueffect_file_x, 
604                 mwindow->theme->menueffect_file_y, 
605                 (char*)((menueffects->strategy == FILE_PER_LABEL  || menueffects->strategy == FILE_PER_LABEL_FARM) ? 
606                         _("Select the first file to render to:") : 
607                         _("Select a file to render to:"))));
609         x = mwindow->theme->menueffect_tools_x;
610         y = mwindow->theme->menueffect_tools_y;
611         format_tools = new FormatTools(mwindow,
612                                         this, 
613                                         asset);
614         format_tools->create_objects(x, 
615                                         y, 
616                                         asset->audio_data, 
617                                         asset->video_data, 
618                                         0, 
619                                         0, 
620                                         0,
621                                         1,
622                                         0,
623                                         0,
624                                         &menueffects->strategy,
625                                         0);
627         loadmode = new LoadMode(mwindow, 
628                 this, 
629                 x, 
630                 y, 
631                 &menueffects->load_mode, 
632                 1);
633         loadmode->create_objects();
635         add_subwindow(new MenuEffectWindowOK(this));
636         add_subwindow(new MenuEffectWindowCancel(this));
637         show_window();
638         flush();
639         return 0;
642 int MenuEffectWindow::resize_event(int w, int h)
644         mwindow->session->menueffect_w = w;
645         mwindow->session->menueffect_h = h;
646         mwindow->theme->get_menueffect_sizes(plugin_list ? 1 : 0);
648         if(plugin_list)
649         {
650                 list_title->reposition_window(mwindow->theme->menueffect_list_x, 
651                         mwindow->theme->menueffect_list_y);
652                 list->reposition_window(mwindow->theme->menueffect_list_x, 
653                         mwindow->theme->menueffect_list_y + 20, 
654                         mwindow->theme->menueffect_list_w,
655                         mwindow->theme->menueffect_list_h);
656         }
658         file_title->reposition_window(mwindow->theme->menueffect_file_x, 
659                 mwindow->theme->menueffect_file_y);
660         int x = mwindow->theme->menueffect_tools_x;
661         int y = mwindow->theme->menueffect_tools_y;
662         format_tools->reposition_window(x, y);
663         loadmode->reposition_window(x, y);
668 MenuEffectWindowOK::MenuEffectWindowOK(MenuEffectWindow *window)
669  : BC_OKButton(window)
671         this->window = window; 
674 int MenuEffectWindowOK::handle_event() 
676         if(window->plugin_list) 
677                 window->result = window->list->get_selection_number(0, 0); 
678         
679         window->set_done(0); 
682 int MenuEffectWindowOK::keypress_event() 
684         if(get_keypress() == 13) 
685         { 
686                 handle_event(); 
687                 return 1; 
688         }
689         return 0;
692 MenuEffectWindowCancel::MenuEffectWindowCancel(MenuEffectWindow *window)
693  : BC_CancelButton(window)
695         this->window = window; 
698 int MenuEffectWindowCancel::handle_event() 
700         window->set_done(1); 
703 int MenuEffectWindowCancel::keypress_event() 
705         if(get_keypress() == ESC) 
706         { 
707                 handle_event(); 
708                 return 1; 
709         }
710         return 0;
713 MenuEffectWindowList::MenuEffectWindowList(MenuEffectWindow *window, 
714         int x, 
715         int y, 
716         int w, 
717         int h, 
718         ArrayList<BC_ListBoxItem*> *plugin_list)
719  : BC_ListBox(x, 
720                 y, 
721                 w, 
722                 h, 
723                 LISTBOX_TEXT, 
724                 plugin_list)
726         this->window = window; 
729 int MenuEffectWindowList::handle_event() 
731         window->result = get_selection_number(0, 0);
732         window->set_done(0); 
737 MenuEffectPrompt::MenuEffectPrompt(MWindow *mwindow)
738  : BC_Window(PROGRAM_NAME ": Effect Prompt", 
739                 mwindow->gui->get_abs_cursor_x() - 260 / 2,
740                 mwindow->gui->get_abs_cursor_y() - 300,
741                 260, 
742                 80, 
743                 260,
744                 80,
745                 0,
746                 0,
747                 1)
751 MenuEffectPrompt::~MenuEffectPrompt()
755 int MenuEffectPrompt::create_objects()
757         int x = 10, y = 10;
758         add_subwindow(new BC_Title(x, y, _("Set up effect panel and hit \"OK\"")));
759         y += 20;
760         add_subwindow(new BC_OKButton(this));
761         x = get_w() - 100;
762         add_subwindow(new BC_CancelButton(this));
763         show_window();
764         raise_window();
765         flush();
766         return 0;