00001 #include "asset.h"
00002 #include "clip.h"
00003 #include "confirmsave.h"
00004 #include "bchash.h"
00005 #include "edl.h"
00006 #include "edlsession.h"
00007 #include "errorbox.h"
00008 #include "file.h"
00009 #include "formatcheck.h"
00010 #include "indexfile.h"
00011 #include "keyframe.h"
00012 #include "keys.h"
00013 #include "labels.h"
00014 #include "language.h"
00015 #include "loadmode.h"
00016 #include "localsession.h"
00017 #include "mainmenu.h"
00018 #include "mainsession.h"
00019 #include "mainundo.h"
00020 #include "mwindow.h"
00021 #include "mwindowgui.h"
00022 #include "menueffects.h"
00023 #include "playbackengine.h"
00024 #include "pluginarray.h"
00025 #include "pluginserver.h"
00026 #include "preferences.h"
00027 #include "render.h"
00028 #include "sighandler.h"
00029 #include "theme.h"
00030 #include "tracks.h"
00031
00032
00033
00034 MenuEffects::MenuEffects(MWindow *mwindow)
00035 : BC_MenuItem(_("Render effect..."))
00036 {
00037 this->mwindow = mwindow;
00038 }
00039
00040 MenuEffects::~MenuEffects()
00041 {
00042 }
00043
00044
00045 int MenuEffects::handle_event()
00046 {
00047 thread->set_title("");
00048 thread->start();
00049 }
00050
00051
00052
00053
00054
00055 MenuEffectPacket::MenuEffectPacket(char *path, int64_t start, int64_t end)
00056 {
00057 this->start = start;
00058 this->end = end;
00059 strcpy(this->path, path);
00060 }
00061
00062 MenuEffectPacket::~MenuEffectPacket()
00063 {
00064 }
00065
00066
00067
00068
00069
00070
00071 MenuEffectThread::MenuEffectThread(MWindow *mwindow)
00072 {
00073 this->mwindow = mwindow;
00074 sprintf(title, "");
00075 }
00076
00077 MenuEffectThread::~MenuEffectThread()
00078 {
00079 }
00080
00081
00082
00083
00084
00085 int MenuEffectThread::set_title(char *title)
00086 {
00087 strcpy(this->title, title);
00088 }
00089
00090
00091
00092 void MenuEffectThread::run()
00093 {
00094
00095 ArrayList<PluginServer*> *plugindb = mwindow->plugindb;
00096 BC_Hash *defaults = mwindow->defaults;
00097 ArrayList<BC_ListBoxItem*> plugin_list;
00098 ArrayList<PluginServer*> local_plugindb;
00099 char string[1024];
00100 int i;
00101 int result = 0;
00102
00103 Asset *default_asset = new Asset;
00104
00105 ArrayList<Asset*> assets;
00106
00107
00108
00109 if(!get_recordable_tracks(default_asset))
00110 {
00111 sprintf(string, _("No recordable tracks specified."));
00112 ErrorBox error(PROGRAM_NAME ": Error");
00113 error.create_objects(string);
00114 error.run_window();
00115 Garbage::delete_object(default_asset);
00116 return;
00117 }
00118
00119
00120 if(!plugindb->total)
00121 {
00122 sprintf(string, _("No plugins available."));
00123 ErrorBox error(PROGRAM_NAME ": Error");
00124 error.create_objects(string);
00125 error.run_window();
00126 Garbage::delete_object(default_asset);
00127 return;
00128 }
00129
00130
00131
00132
00133 get_derived_attributes(default_asset, defaults);
00134
00135 load_mode = defaults->get("RENDER_EFFECT_LOADMODE", LOAD_PASTE);
00136 strategy = defaults->get("RENDER_EFFECT_STRATEGY", SINGLE_PASS);
00137
00138
00139 int need_plugin;
00140 if(!strlen(title))
00141 need_plugin = 1;
00142 else
00143 need_plugin = 0;
00144
00145
00146 if(need_plugin)
00147 {
00148 mwindow->create_plugindb(default_asset->audio_data,
00149 default_asset->video_data,
00150 -1,
00151 0,
00152 0,
00153 local_plugindb);
00154
00155 for(int i = 0; i < local_plugindb.total; i++)
00156 {
00157 plugin_list.append(new BC_ListBoxItem(_(local_plugindb.values[i]->title)));
00158 }
00159 }
00160
00161
00162 int plugin_number, format_error = 0;
00163
00164 do
00165 {
00166 {
00167 MenuEffectWindow window(mwindow,
00168 this,
00169 need_plugin ? &plugin_list : 0,
00170 default_asset);
00171 window.create_objects();
00172 result = window.run_window();
00173 plugin_number = window.result;
00174 }
00175
00176 if(!result)
00177 {
00178 FormatCheck format_check(default_asset);
00179 format_error = format_check.check_format();
00180 }
00181 }while(format_error && !result);
00182
00183
00184 save_derived_attributes(default_asset, defaults);
00185 defaults->update("RENDER_EFFECT_LOADMODE", load_mode);
00186 defaults->update("RENDER_EFFECT_STRATEGY", strategy);
00187 mwindow->save_defaults();
00188
00189
00190 PluginServer *plugin_server = 0;
00191 PluginServer *plugin = 0;
00192 if(need_plugin)
00193 {
00194 plugin_list.remove_all_objects();
00195 if(plugin_number > -1)
00196 {
00197 plugin_server = local_plugindb.values[plugin_number];
00198 strcpy(title, plugin_server->title);
00199 }
00200 }
00201 else
00202 {
00203 for(int i = 0; i < plugindb->total && !plugin_server; i++)
00204 {
00205 if(!strcmp(plugindb->values[i]->title, title))
00206 {
00207 plugin_server = plugindb->values[i];
00208 plugin_number = i;
00209 }
00210 }
00211 }
00212
00213
00214 if(plugin_server)
00215 {
00216 plugin = new PluginServer(*plugin_server);
00217 fix_menu(title);
00218 }
00219
00220 if(!result && !strlen(default_asset->path))
00221 {
00222 result = 1;
00223 ErrorBox error(PROGRAM_NAME ": Error");
00224 error.create_objects(_("No output file specified."));
00225 error.run_window();
00226 }
00227
00228 if(!result && plugin_number < 0)
00229 {
00230 result = 1;
00231 ErrorBox error(PROGRAM_NAME ": Error");
00232 error.create_objects(_("No effect selected."));
00233 error.run_window();
00234 }
00235
00236
00237 KeyFrame plugin_data;
00238
00239
00240
00241 double total_start, total_end;
00242
00243 total_start = mwindow->edl->local_session->get_selectionstart();
00244
00245
00246 if(mwindow->edl->local_session->get_selectionend() ==
00247 mwindow->edl->local_session->get_selectionstart())
00248 total_end = mwindow->edl->tracks->total_playable_length();
00249 else
00250 total_end = mwindow->edl->local_session->get_selectionend();
00251
00252
00253
00254
00255 total_start = to_units(total_start, 0);
00256 total_end = to_units(total_end, 1);
00257
00258
00259
00260
00261 if(plugin &&
00262 !plugin->realtime &&
00263 total_end == total_start) total_end = total_start + 1;
00264
00265
00266 int64_t total_length = (int64_t)total_end - (int64_t)total_start;
00267
00268 int64_t output_start, output_end;
00269
00270 if(!result && total_length <= 0)
00271 {
00272 result = 1;
00273 ErrorBox error(PROGRAM_NAME ": Error");
00274 error.create_objects(_("No selected range to process."));
00275 error.run_window();
00276 }
00277
00278
00279 if(!result)
00280 {
00281
00282
00283 if(plugin->realtime)
00284 {
00285
00286 MenuEffectPrompt prompt(mwindow);
00287 prompt.create_objects();
00288 char title[BCTEXTLEN];
00289 sprintf(title, PROGRAM_NAME ": %s", plugin->title);
00290
00291
00292 plugin->set_mwindow(mwindow);
00293 plugin->set_keyframe(&plugin_data);
00294 plugin->set_prompt(&prompt);
00295 plugin->open_plugin(0, mwindow->preferences, mwindow->edl, 0, -1);
00296
00297 plugin->get_parameters((int64_t)total_start,
00298 (int64_t)total_end,
00299 1);
00300 plugin->show_gui();
00301
00302
00303 result = prompt.run_window();
00304
00305
00306 plugin->save_data(&plugin_data);
00307 delete plugin;
00308 default_asset->sample_rate = mwindow->edl->session->sample_rate;
00309 default_asset->frame_rate = mwindow->edl->session->frame_rate;
00310 realtime = 1;
00311 }
00312 else
00313
00314 {
00315 plugin->set_mwindow(mwindow);
00316 plugin->open_plugin(0, mwindow->preferences, mwindow->edl, 0, -1);
00317 result = plugin->get_parameters((int64_t)total_start,
00318 (int64_t)total_end,
00319 get_recordable_tracks(default_asset));
00320
00321
00322
00323 if(!result)
00324 {
00325 default_asset->sample_rate = plugin->get_samplerate();
00326 default_asset->frame_rate = plugin->get_framerate();
00327 }
00328 delete plugin;
00329 realtime = 0;
00330 }
00331
00332
00333 default_asset->width = mwindow->edl->session->output_w;
00334 default_asset->height = mwindow->edl->session->output_h;
00335 }
00336
00337
00338 ArrayList<MenuEffectPacket*> packets;
00339 if(!result)
00340 {
00341 Label *current_label = mwindow->edl->labels->first;
00342 mwindow->stop_brender();
00343
00344 int current_number;
00345 int number_start;
00346 int total_digits;
00347 Render::get_starting_number(default_asset->path,
00348 current_number,
00349 number_start,
00350 total_digits);
00351
00352
00353
00354
00355 for(int64_t fragment_start = (int64_t)total_start, fragment_end;
00356 fragment_start < (int64_t)total_end;
00357 fragment_start = fragment_end)
00358 {
00359
00360 if(strategy == FILE_PER_LABEL || strategy == FILE_PER_LABEL_FARM)
00361 {
00362 while(current_label &&
00363 to_units(current_label->position, 0) <= fragment_start)
00364 current_label = current_label->next;
00365 if(!current_label)
00366 fragment_end = (int64_t)total_end;
00367 else
00368 fragment_end = to_units(current_label->position, 0);
00369 }
00370 else
00371 {
00372 fragment_end = (int64_t)total_end;
00373 }
00374
00375
00376 char path[BCTEXTLEN];
00377 if(strategy == FILE_PER_LABEL || strategy == FILE_PER_LABEL_FARM)
00378 Render::create_filename(path,
00379 default_asset->path,
00380 current_number,
00381 total_digits,
00382 number_start);
00383 else
00384 strcpy(path, default_asset->path);
00385 current_number++;
00386
00387 MenuEffectPacket *packet = new MenuEffectPacket(path,
00388 fragment_start,
00389 fragment_end);
00390 packets.append(packet);
00391 }
00392
00393
00394
00395 ArrayList<char*> paths;
00396 for(int i = 0; i < packets.total; i++)
00397 {
00398 paths.append(packets.values[i]->path);
00399 }
00400 result = ConfirmSave::test_files(mwindow, &paths);
00401 paths.remove_all();
00402 }
00403
00404
00405
00406 for(int current_packet = 0;
00407 current_packet < packets.total && !result;
00408 current_packet++)
00409 {
00410 Asset *asset = new Asset(*default_asset);
00411 MenuEffectPacket *packet = packets.values[current_packet];
00412 int64_t fragment_start = packet->start;
00413 int64_t fragment_end = packet->end;
00414 strcpy(asset->path, packet->path);
00415
00416 assets.append(asset);
00417 File *file = new File;
00418
00419
00420
00421 if(!result)
00422 {
00423
00424 file->set_processors(mwindow->preferences->processors);
00425 if(file->open_file(mwindow->preferences,
00426 asset,
00427 0,
00428 1,
00429 mwindow->edl->session->sample_rate,
00430 mwindow->edl->session->frame_rate))
00431 {
00432
00433 sprintf(string, _("Couldn't open %s"), asset->path);
00434 ErrorBox error(PROGRAM_NAME ": Error");
00435 error.create_objects(string);
00436 error.run_window();
00437 result = 1;
00438 }
00439 else
00440 {
00441 mwindow->sighandler->push_file(file);
00442 IndexFile::delete_index(mwindow->preferences, asset);
00443 }
00444 }
00445
00446
00447 if(!result)
00448 {
00449
00450 output_start = 0;
00451
00452 PluginArray *plugin_array;
00453 plugin_array = create_plugin_array();
00454
00455 plugin_array->start_plugins(mwindow,
00456 mwindow->edl,
00457 plugin_server,
00458 &plugin_data,
00459 fragment_start,
00460 fragment_end,
00461 file);
00462 plugin_array->run_plugins();
00463
00464 plugin_array->stop_plugins();
00465 mwindow->sighandler->pull_file(file);
00466 file->close_file();
00467 asset->audio_length = file->asset->audio_length;
00468 asset->video_length = file->asset->video_length;
00469 delete plugin_array;
00470 }
00471
00472 delete file;
00473 }
00474
00475 packets.remove_all_objects();
00476
00477
00478 if(!result && load_mode != LOAD_NOTHING)
00479 {
00480 mwindow->gui->lock_window("MenuEffectThread::run");
00481
00482 if(load_mode == LOAD_PASTE)
00483 mwindow->clear(0);
00484 mwindow->load_assets(&assets,
00485 -1,
00486 load_mode,
00487 0,
00488 0,
00489 mwindow->edl->session->labels_follow_edits,
00490 mwindow->edl->session->plugins_follow_edits,
00491 0);
00492
00493
00494 mwindow->save_backup();
00495 mwindow->undo->update_undo(title, LOAD_ALL);
00496
00497
00498
00499 mwindow->restart_brender();
00500 mwindow->update_plugin_guis();
00501 mwindow->gui->update(1,
00502 2,
00503 1,
00504 1,
00505 1,
00506 1,
00507 0);
00508 mwindow->sync_parameters(CHANGE_ALL);
00509 mwindow->gui->unlock_window();
00510 }
00511
00512 for(int i = 0; i < assets.total; i++)
00513 Garbage::delete_object(assets.values[i]);
00514 assets.remove_all();
00515 Garbage::delete_object(default_asset);
00516 }
00517
00518
00519
00520
00521 MenuEffectItem::MenuEffectItem(MenuEffects *menueffect, char *string)
00522 : BC_MenuItem(string)
00523 {
00524 this->menueffect = menueffect;
00525 }
00526 int MenuEffectItem::handle_event()
00527 {
00528 menueffect->thread->set_title(get_text());
00529 menueffect->thread->start();
00530 }
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543 MenuEffectWindow::MenuEffectWindow(MWindow *mwindow,
00544 MenuEffectThread *menueffects,
00545 ArrayList<BC_ListBoxItem*> *plugin_list,
00546 Asset *asset)
00547 : BC_Window(PROGRAM_NAME ": Render effect",
00548 mwindow->gui->get_abs_cursor_x(1),
00549 mwindow->gui->get_abs_cursor_y(1) - mwindow->session->menueffect_h / 2,
00550 mwindow->session->menueffect_w,
00551 mwindow->session->menueffect_h,
00552 580,
00553 350,
00554 1,
00555 0,
00556 1)
00557 {
00558 this->menueffects = menueffects;
00559 this->plugin_list = plugin_list;
00560 this->asset = asset;
00561 this->mwindow = mwindow;
00562 }
00563
00564 MenuEffectWindow::~MenuEffectWindow()
00565 {
00566 delete format_tools;
00567 }
00568
00569
00570
00571 int MenuEffectWindow::create_objects()
00572 {
00573 int x, y;
00574 result = -1;
00575 mwindow->theme->get_menueffect_sizes(plugin_list ? 1 : 0);
00576
00577
00578 if(plugin_list)
00579 {
00580 add_subwindow(list_title = new BC_Title(mwindow->theme->menueffect_list_x,
00581 mwindow->theme->menueffect_list_y,
00582 _("Select an effect")));
00583 add_subwindow(list = new MenuEffectWindowList(this,
00584 mwindow->theme->menueffect_list_x,
00585 mwindow->theme->menueffect_list_y + list_title->get_h() + 5,
00586 mwindow->theme->menueffect_list_w,
00587 mwindow->theme->menueffect_list_h - list_title->get_h() - 5,
00588 plugin_list));
00589 }
00590
00591 add_subwindow(file_title = new BC_Title(mwindow->theme->menueffect_file_x,
00592 mwindow->theme->menueffect_file_y,
00593 (char*)((menueffects->strategy == FILE_PER_LABEL || menueffects->strategy == FILE_PER_LABEL_FARM) ?
00594 _("Select the first file to render to:") :
00595 _("Select a file to render to:"))));
00596
00597 x = mwindow->theme->menueffect_tools_x;
00598 y = mwindow->theme->menueffect_tools_y;
00599 format_tools = new FormatTools(mwindow,
00600 this,
00601 asset);
00602 format_tools->create_objects(x,
00603 y,
00604 asset->audio_data,
00605 asset->video_data,
00606 0,
00607 0,
00608 0,
00609 1,
00610 0,
00611 0,
00612 &menueffects->strategy,
00613 0);
00614
00615 loadmode = new LoadMode(mwindow,
00616 this,
00617 x,
00618 y,
00619 &menueffects->load_mode,
00620 1);
00621 loadmode->create_objects();
00622
00623 add_subwindow(new MenuEffectWindowOK(this));
00624 add_subwindow(new MenuEffectWindowCancel(this));
00625 show_window();
00626 flush();
00627 return 0;
00628 }
00629
00630 int MenuEffectWindow::resize_event(int w, int h)
00631 {
00632 mwindow->session->menueffect_w = w;
00633 mwindow->session->menueffect_h = h;
00634 mwindow->theme->get_menueffect_sizes(plugin_list ? 1 : 0);
00635
00636 if(plugin_list)
00637 {
00638 list_title->reposition_window(mwindow->theme->menueffect_list_x,
00639 mwindow->theme->menueffect_list_y);
00640 list->reposition_window(mwindow->theme->menueffect_list_x,
00641 mwindow->theme->menueffect_list_y + list_title->get_h() + 5,
00642 mwindow->theme->menueffect_list_w,
00643 mwindow->theme->menueffect_list_h - list_title->get_h() - 5);
00644 }
00645
00646 file_title->reposition_window(mwindow->theme->menueffect_file_x,
00647 mwindow->theme->menueffect_file_y);
00648 int x = mwindow->theme->menueffect_tools_x;
00649 int y = mwindow->theme->menueffect_tools_y;
00650 format_tools->reposition_window(x, y);
00651 loadmode->reposition_window(x, y);
00652 }
00653
00654
00655
00656 MenuEffectWindowOK::MenuEffectWindowOK(MenuEffectWindow *window)
00657 : BC_OKButton(window)
00658 {
00659 this->window = window;
00660 }
00661
00662 int MenuEffectWindowOK::handle_event()
00663 {
00664 if(window->plugin_list)
00665 window->result = window->list->get_selection_number(0, 0);
00666
00667 window->set_done(0);
00668 }
00669
00670 int MenuEffectWindowOK::keypress_event()
00671 {
00672 if(get_keypress() == RETURN)
00673 {
00674 handle_event();
00675 return 1;
00676 }
00677 return 0;
00678 }
00679
00680 MenuEffectWindowCancel::MenuEffectWindowCancel(MenuEffectWindow *window)
00681 : BC_CancelButton(window)
00682 {
00683 this->window = window;
00684 }
00685
00686 int MenuEffectWindowCancel::handle_event()
00687 {
00688 window->set_done(1);
00689 }
00690
00691 int MenuEffectWindowCancel::keypress_event()
00692 {
00693 if(get_keypress() == ESC)
00694 {
00695 handle_event();
00696 return 1;
00697 }
00698 return 0;
00699 }
00700
00701 MenuEffectWindowList::MenuEffectWindowList(MenuEffectWindow *window,
00702 int x,
00703 int y,
00704 int w,
00705 int h,
00706 ArrayList<BC_ListBoxItem*> *plugin_list)
00707 : BC_ListBox(x,
00708 y,
00709 w,
00710 h,
00711 LISTBOX_TEXT,
00712 plugin_list)
00713 {
00714 this->window = window;
00715 }
00716
00717 int MenuEffectWindowList::handle_event()
00718 {
00719 window->result = get_selection_number(0, 0);
00720 window->set_done(0);
00721 }
00722
00723 #define PROMPT_TEXT _("Set up effect panel and hit \"OK\"")
00724
00725 MenuEffectPrompt::MenuEffectPrompt(MWindow *mwindow)
00726 : BC_Window(PROGRAM_NAME ": Effect Prompt",
00727 mwindow->gui->get_abs_cursor_x(1) - 260 / 2,
00728 mwindow->gui->get_abs_cursor_y(1) - 300,
00729 MenuEffectPrompt::calculate_w(mwindow->gui),
00730 MenuEffectPrompt::calculate_h(mwindow->gui),
00731 MenuEffectPrompt::calculate_w(mwindow->gui),
00732 MenuEffectPrompt::calculate_h(mwindow->gui),
00733 0,
00734 0,
00735 1)
00736 {
00737 }
00738
00739 int MenuEffectPrompt::calculate_w(BC_WindowBase *gui)
00740 {
00741 int w = BC_Title::calculate_w(gui, PROMPT_TEXT) + 10;
00742 w = MAX(w, BC_OKButton::calculate_w() + BC_CancelButton::calculate_w() + 30);
00743 return w;
00744 }
00745
00746 int MenuEffectPrompt::calculate_h(BC_WindowBase *gui)
00747 {
00748 int h = BC_Title::calculate_h(gui, PROMPT_TEXT);
00749 h += BC_OKButton::calculate_h() + 30;
00750 return h;
00751 }
00752
00753
00754 int MenuEffectPrompt::create_objects()
00755 {
00756 int x = 10, y = 10;
00757 BC_Title *title;
00758 add_subwindow(title = new BC_Title(x, y, PROMPT_TEXT));
00759 add_subwindow(new BC_OKButton(this));
00760 add_subwindow(new BC_CancelButton(this));
00761 show_window();
00762 raise_window();
00763 flush();
00764 return 0;
00765 }
00766