00001 #include "bcdisplayinfo.h"
00002 #include "clip.h"
00003 #include "bchash.h"
00004 #include "filexml.h"
00005 #include "guicast.h"
00006 #include "keyframe.h"
00007 #include "language.h"
00008 #include "overlayframe.h"
00009 #include "picon_png.h"
00010 #include "pluginvclient.h"
00011 #include "vframe.h"
00012
00013 #include <string.h>
00014 #include <stdint.h>
00015
00016
00017 class Reroute;
00018 class RerouteWindow;
00019
00020
00021 class RerouteConfig
00022 {
00023 public:
00024 RerouteConfig();
00025
00026
00027
00028 static char* operation_to_text(int operation);
00029 int operation;
00030 enum
00031 {
00032 REPLACE,
00033 REPLACE_COMPONENTS,
00034 REPLACE_ALPHA
00035 };
00036
00037 static char* output_to_text(int output_track);
00038 int output_track;
00039 enum
00040 {
00041 TOP,
00042 BOTTOM
00043 };
00044 };
00045
00046
00047
00048
00049
00050
00051 class RerouteOperation : public BC_PopupMenu
00052 {
00053 public:
00054 RerouteOperation(Reroute *plugin,
00055 int x,
00056 int y);
00057 void create_objects();
00058 int handle_event();
00059 Reroute *plugin;
00060 };
00061
00062 class RerouteOutput : public BC_PopupMenu
00063 {
00064 public:
00065 RerouteOutput(Reroute *plugin,
00066 int x,
00067 int y);
00068 void create_objects();
00069 int handle_event();
00070 Reroute *plugin;
00071 };
00072
00073
00074 class RerouteWindow : public BC_Window
00075 {
00076 public:
00077 RerouteWindow(Reroute *plugin, int x, int y);
00078 ~RerouteWindow();
00079
00080 void create_objects();
00081 int close_event();
00082
00083 Reroute *plugin;
00084 RerouteOperation *operation;
00085 RerouteOutput *output;
00086 };
00087
00088
00089 PLUGIN_THREAD_HEADER(Reroute, RerouteThread, RerouteWindow)
00090
00091
00092
00093 class Reroute : public PluginVClient
00094 {
00095 public:
00096 Reroute(PluginServer *server);
00097 ~Reroute();
00098
00099
00100 PLUGIN_CLASS_MEMBERS(RerouteConfig, RerouteThread);
00101
00102 int process_buffer(VFrame **frame, int64_t start_position, double frame_rate);
00103 int is_realtime();
00104 int is_multichannel();
00105 int load_defaults();
00106 int save_defaults();
00107 void save_data(KeyFrame *keyframe);
00108 void read_data(KeyFrame *keyframe);
00109 void update_gui();
00110
00111 int output_track;
00112 int input_track;
00113 };
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 RerouteConfig::RerouteConfig()
00127 {
00128 operation = RerouteConfig::REPLACE;
00129 output_track = RerouteConfig::TOP;
00130 }
00131
00132
00133 char* RerouteConfig::operation_to_text(int operation)
00134 {
00135 switch(operation)
00136 {
00137 case RerouteConfig::REPLACE: return _("replace Target");
00138 case RerouteConfig::REPLACE_COMPONENTS: return _("Components only");
00139 case RerouteConfig::REPLACE_ALPHA: return _("Alpha replace");
00140 }
00141 return "";
00142 }
00143
00144 char* RerouteConfig::output_to_text(int output_track)
00145 {
00146 switch(output_track)
00147 {
00148 case RerouteConfig::TOP: return _("Top");
00149 case RerouteConfig::BOTTOM: return _("Bottom");
00150 }
00151 return "";
00152 }
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 RerouteWindow::RerouteWindow(Reroute *plugin, int x, int y)
00163 : BC_Window(plugin->gui_string,
00164 x,
00165 y,
00166 300,
00167 160,
00168 300,
00169 160,
00170 0,
00171 0,
00172 1)
00173 {
00174 this->plugin = plugin;
00175 }
00176
00177 RerouteWindow::~RerouteWindow()
00178 {
00179 }
00180
00181 void RerouteWindow::create_objects()
00182 {
00183 int x = 10, y = 10;
00184
00185 BC_Title *title;
00186 add_subwindow(title = new BC_Title(x, y, _("Target track:")));
00187
00188 int col2 = title->get_w() + 5;
00189 add_subwindow(output = new RerouteOutput(plugin,
00190 x + col2,
00191 y));
00192 output->create_objects();
00193
00194 y += 30;
00195 add_subwindow(title = new BC_Title(x, y, _("Operation:")));
00196 add_subwindow(operation = new RerouteOperation(plugin,
00197 x + col2,
00198 y));
00199 operation->create_objects();
00200
00201 show_window();
00202 flush();
00203 }
00204
00205 WINDOW_CLOSE_EVENT(RerouteWindow)
00206
00207
00208
00209
00210
00211
00212
00213 RerouteOperation::RerouteOperation(Reroute *plugin,
00214 int x,
00215 int y)
00216 : BC_PopupMenu(x,
00217 y,
00218 150,
00219 RerouteConfig::operation_to_text(plugin->config.operation),
00220 1)
00221 {
00222 this->plugin = plugin;
00223 }
00224
00225 void RerouteOperation::create_objects()
00226 {
00227 add_item(new BC_MenuItem(
00228 RerouteConfig::operation_to_text(
00229 RerouteConfig::REPLACE)));
00230 add_item(new BC_MenuItem(
00231 RerouteConfig::operation_to_text(
00232 RerouteConfig::REPLACE_COMPONENTS)));
00233 add_item(new BC_MenuItem(
00234 RerouteConfig::operation_to_text(
00235 RerouteConfig::REPLACE_ALPHA)));
00236 }
00237
00238 int RerouteOperation::handle_event()
00239 {
00240 char *text = get_text();
00241
00242 if(!strcmp(text,
00243 RerouteConfig::operation_to_text(
00244 RerouteConfig::REPLACE)))
00245 plugin->config.operation = RerouteConfig::REPLACE;
00246 else
00247 if(!strcmp(text,
00248 RerouteConfig::operation_to_text(
00249 RerouteConfig::REPLACE_COMPONENTS)))
00250 plugin->config.operation = RerouteConfig::REPLACE_COMPONENTS;
00251 else
00252 if(!strcmp(text,
00253 RerouteConfig::operation_to_text(
00254 RerouteConfig::REPLACE_ALPHA)))
00255 plugin->config.operation = RerouteConfig::REPLACE_ALPHA;
00256
00257 plugin->send_configure_change();
00258 return 1;
00259 }
00260
00261
00262 RerouteOutput::RerouteOutput(Reroute *plugin,
00263 int x,
00264 int y)
00265 : BC_PopupMenu(x,
00266 y,
00267 100,
00268 RerouteConfig::output_to_text(plugin->config.output_track),
00269 1)
00270 {
00271 this->plugin = plugin;
00272 }
00273
00274 void RerouteOutput::create_objects()
00275 {
00276 add_item(new BC_MenuItem(
00277 RerouteConfig::output_to_text(
00278 RerouteConfig::TOP)));
00279 add_item(new BC_MenuItem(
00280 RerouteConfig::output_to_text(
00281 RerouteConfig::BOTTOM)));
00282 }
00283
00284 int RerouteOutput::handle_event()
00285 {
00286 char *text = get_text();
00287
00288 if(!strcmp(text,
00289 RerouteConfig::output_to_text(
00290 RerouteConfig::TOP)))
00291 plugin->config.output_track = RerouteConfig::TOP;
00292 else
00293 if(!strcmp(text,
00294 RerouteConfig::output_to_text(
00295 RerouteConfig::BOTTOM)))
00296 plugin->config.output_track = RerouteConfig::BOTTOM;
00297
00298 plugin->send_configure_change();
00299 return 1;
00300 }
00301
00302
00303
00304
00305
00306
00307
00308 PLUGIN_THREAD_OBJECT(Reroute, RerouteThread, RerouteWindow)
00309
00310 REGISTER_PLUGIN(Reroute)
00311
00312
00313
00314
00315
00316
00317
00318 Reroute::Reroute(PluginServer *server)
00319 : PluginVClient(server)
00320 {
00321 PLUGIN_CONSTRUCTOR_MACRO
00322 }
00323
00324
00325 Reroute::~Reroute()
00326 {
00327 PLUGIN_DESTRUCTOR_MACRO
00328 }
00329
00330
00331
00332
00333
00334
00335
00336 template<class TYPE, int COMPONENTS>
00337 struct px_type
00338 {
00339 static inline
00340 void transfer(VFrame*, VFrame*, bool, bool) ;
00341 };
00342
00343 template<class TYPE, int COMPONENTS>
00344 void px_type<TYPE,COMPONENTS>::transfer(VFrame *source, VFrame *target, bool do_components, bool do_alpha)
00345
00346 {
00347 int w = target->get_w();
00348 int h = source->get_h();
00349 do_alpha = do_alpha && (COMPONENTS > 3);
00350
00351 for(int i = 0; i < h; i++)
00352 {
00353 TYPE *inpx = (TYPE*)source->get_rows()[i];
00354 TYPE *outpx = (TYPE*)target->get_rows()[i];
00355
00356 for(int j = 0; j < w; j++)
00357 {
00358 if(do_components)
00359 {
00360 outpx[0] = inpx[0];
00361 outpx[1] = inpx[1];
00362 outpx[2] = inpx[2];
00363 }
00364 if(do_alpha)
00365 outpx[3] = inpx[3];
00366
00367 inpx += COMPONENTS;
00368 outpx += COMPONENTS;
00369 }
00370 }
00371 }
00372
00373
00374
00375 int Reroute::process_buffer(VFrame **frame,
00376 int64_t start_position,
00377 double frame_rate)
00378 {
00379 load_configuration();
00380
00381 bool do_components, do_alpha;
00382 switch(config.operation)
00383 {
00384 case RerouteConfig::REPLACE: do_components = do_alpha=true; break;
00385 case RerouteConfig::REPLACE_ALPHA: do_components=false; do_alpha=true; break;
00386 case RerouteConfig::REPLACE_COMPONENTS: do_components=true; do_alpha=false; break;
00387 }
00388
00389 if(config.output_track == RerouteConfig::TOP)
00390 {
00391 input_track = get_total_buffers() - 1;
00392 output_track = 0;
00393 }
00394 else
00395 {
00396 input_track = 0;
00397 output_track = get_total_buffers() - 1;
00398 }
00399
00400
00401
00402 VFrame *source = frame[input_track];
00403 VFrame *target = frame[output_track];
00404
00405
00406 read_frame(source,
00407 input_track,
00408 start_position,
00409 frame_rate,
00410 false );
00411
00412
00413
00414 if(get_total_buffers() <= 1)
00415 return 0;
00416
00417 if(config.operation == RerouteConfig::REPLACE)
00418 {
00419 target->copy_from(source);
00420 return 0;
00421 }
00422
00423
00424
00425
00426 read_frame(target,
00427 output_track,
00428 start_position,
00429 frame_rate);
00430
00431 switch(source->get_color_model())
00432 {
00433 case BC_RGB_FLOAT:
00434 px_type<float,3>::transfer(source,target, do_components,do_alpha);
00435 break;
00436 case BC_RGBA_FLOAT:
00437 px_type<float,4>::transfer(source,target, do_components,do_alpha);
00438 break;
00439 case BC_RGB888:
00440 case BC_YUV888:
00441 px_type<unsigned char,3>::transfer(source,target, do_components,do_alpha);
00442 break;
00443 case BC_RGBA8888:
00444 case BC_YUVA8888:
00445 px_type<unsigned char,4>::transfer(source,target, do_components,do_alpha);
00446 break;
00447 case BC_RGB161616:
00448 case BC_YUV161616:
00449 px_type<uint16_t,3>::transfer(source,target, do_components,do_alpha);
00450 break;
00451 case BC_RGBA16161616:
00452 case BC_YUVA16161616:
00453 px_type<uint16_t,4>::transfer(source,target, do_components,do_alpha);
00454 break;
00455 }
00456
00457 return 0;
00458 }
00459
00460
00461
00462
00463
00464
00465
00466
00467 char* Reroute::plugin_title() { return N_("Reroute"); }
00468 int Reroute::is_realtime() { return 1; }
00469 int Reroute::is_multichannel() { return 1; }
00470
00471
00472 NEW_PICON_MACRO(Reroute)
00473
00474 SHOW_GUI_MACRO(Reroute, RerouteThread)
00475
00476 RAISE_WINDOW_MACRO(Reroute)
00477
00478 SET_STRING_MACRO(Reroute);
00479
00480
00481
00482 int Reroute::load_configuration()
00483 {
00484 KeyFrame *prev_keyframe;
00485 prev_keyframe = get_prev_keyframe(get_source_position());
00486 read_data(prev_keyframe);
00487 return 0;
00488 }
00489
00490 int Reroute::load_defaults()
00491 {
00492 char directory[BCTEXTLEN];
00493
00494 sprintf(directory, "%sreroute.rc", BCASTDIR);
00495
00496
00497 defaults = new BC_Hash(directory);
00498 defaults->load();
00499
00500 config.operation = defaults->get("OPERATION", config.operation);
00501 config.output_track = defaults->get("OUTPUT_TRACK", config.output_track);
00502 return 0;
00503 }
00504
00505 int Reroute::save_defaults()
00506 {
00507 defaults->update("OPERATION", config.operation);
00508 defaults->update("OUTPUT_TRACK", config.output_track);
00509 defaults->save();
00510 return 0;
00511 }
00512
00513 void Reroute::save_data(KeyFrame *keyframe)
00514 {
00515 FileXML output;
00516
00517
00518 output.set_shared_string(keyframe->data, MESSAGESIZE);
00519 output.tag.set_title("REROUTE");
00520 output.tag.set_property("OPERATION", config.operation);
00521 output.tag.set_property("OUTPUT_TRACK", config.output_track);
00522 output.append_tag();
00523 output.tag.set_title("/REROUTE");
00524 output.append_tag();
00525 output.terminate_string();
00526 }
00527
00528 void Reroute::read_data(KeyFrame *keyframe)
00529 {
00530 FileXML input;
00531 input.set_shared_string(keyframe->data, strlen(keyframe->data));
00532 int result = 0;
00533
00534 while(!input.read_tag())
00535 {
00536 if(input.tag.title_is("REROUTE"))
00537 {
00538 config.operation = input.tag.get_property("OPERATION", config.operation);
00539 config.output_track = input.tag.get_property("OUTPUT_TRACK", config.output_track);
00540 }
00541 }
00542 }
00543
00544 void Reroute::update_gui()
00545 {
00546 if(thread)
00547 {
00548 thread->window->lock_window("Reroute::update_gui");
00549 thread->window->operation->set_text(RerouteConfig::operation_to_text(config.operation));
00550 thread->window->output->set_text(RerouteConfig::output_to_text(config.output_track));
00551 thread->window->unlock_window();
00552 }
00553 }