4 * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
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.
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.
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
22 #include "bcdisplayinfo.h"
27 #include "swapchannels.h"
40 REGISTER_PLUGIN(SwapMain)
49 SwapConfig::SwapConfig()
58 int SwapConfig::equivalent(SwapConfig &that)
60 return (red == that.red &&
61 green == that.green &&
66 void SwapConfig::copy_from(SwapConfig &that)
81 SwapWindow::SwapWindow(SwapMain *plugin)
82 : PluginClientWindow(plugin,
89 this->plugin = plugin;
92 SwapWindow::~SwapWindow()
97 void SwapWindow::create_objects()
102 add_subwindow(new BC_Title(x, y, _("Swap channels")));
104 add_subwindow(new BC_Title(x + 160, y + 5, _("-> Red")));
105 add_subwindow(red = new SwapMenu(plugin, &(plugin->config.red), x, y));
106 red->create_objects();
108 add_subwindow(new BC_Title(x + 160, y + 5, _("-> Green")));
109 add_subwindow(green = new SwapMenu(plugin, &(plugin->config.green), x, y));
110 green->create_objects();
112 add_subwindow(new BC_Title(x + 160, y + 5, _("-> Blue")));
113 add_subwindow(blue = new SwapMenu(plugin, &(plugin->config.blue), x, y));
114 blue->create_objects();
116 add_subwindow(new BC_Title(x + 160, y + 5, _("-> Alpha")));
117 add_subwindow(alpha = new SwapMenu(plugin, &(plugin->config.alpha), x, y));
118 alpha->create_objects();
132 SwapMenu::SwapMenu(SwapMain *client, int *output, int x, int y)
133 : BC_PopupMenu(x, y, 150, client->output_to_text(*output))
135 this->client = client;
136 this->output = output;
139 int SwapMenu::handle_event()
141 client->send_configure_change();
145 void SwapMenu::create_objects()
147 add_item(new SwapItem(this, client->output_to_text(RED_SRC)));
148 add_item(new SwapItem(this, client->output_to_text(GREEN_SRC)));
149 add_item(new SwapItem(this, client->output_to_text(BLUE_SRC)));
150 add_item(new SwapItem(this, client->output_to_text(ALPHA_SRC)));
151 add_item(new SwapItem(this, client->output_to_text(NO_SRC)));
152 add_item(new SwapItem(this, client->output_to_text(MAX_SRC)));
158 SwapItem::SwapItem(SwapMenu *menu, const char *title)
164 int SwapItem::handle_event()
166 menu->set_text(get_text());
167 *(menu->output) = menu->client->text_to_output(get_text());
168 menu->handle_event();
191 SwapMain::SwapMain(PluginServer *server)
192 : PluginVClient(server)
198 SwapMain::~SwapMain()
202 // if(temp) delete temp;
205 void SwapMain::reset()
211 const char* SwapMain::plugin_title() { return N_("Swap channels"); }
212 int SwapMain::is_synthesis() { return 1; }
213 int SwapMain::is_realtime() { return 1; }
215 NEW_WINDOW_MACRO(SwapMain, SwapWindow)
218 void SwapMain::save_data(KeyFrame *keyframe)
222 // cause data to be stored directly in text
223 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
224 output.tag.set_title("SWAPCHANNELS");
225 output.tag.set_property("RED", config.red);
226 output.tag.set_property("GREEN", config.green);
227 output.tag.set_property("BLUE", config.blue);
228 output.tag.set_property("ALPHA", config.alpha);
230 output.tag.set_title("/SWAPCHANNELS");
232 output.append_newline();
233 output.terminate_string();
234 // data is now in *text
237 void SwapMain::read_data(KeyFrame *keyframe)
241 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
247 result = input.read_tag();
251 if(input.tag.title_is("SWAPCHANNELS"))
253 config.red = input.tag.get_property("RED", config.red);
254 config.green = input.tag.get_property("GREEN", config.green);
255 config.blue = input.tag.get_property("BLUE", config.blue);
256 config.alpha = input.tag.get_property("ALPHA", config.alpha);
262 void SwapMain::update_gui()
266 load_configuration();
267 thread->window->lock_window();
268 ((SwapWindow*)thread->window)->red->set_text(output_to_text(config.red));
269 ((SwapWindow*)thread->window)->green->set_text(output_to_text(config.green));
270 ((SwapWindow*)thread->window)->blue->set_text(output_to_text(config.blue));
271 ((SwapWindow*)thread->window)->alpha->set_text(output_to_text(config.alpha));
272 thread->window->unlock_window();
277 int SwapMain::load_configuration()
279 KeyFrame *prev_keyframe;
280 prev_keyframe = get_prev_keyframe(get_source_position());
282 read_data(prev_keyframe);
309 #define MAXMINSRC(src, min, max) \
310 (src == MAX_SRC ? max : min)
312 #define SWAP_CHANNELS(type, min, max, components) \
314 int h = frame->get_h(); \
315 int w = frame->get_w(); \
316 int red = config.red; \
317 int green = config.green; \
318 int blue = config.blue; \
319 int alpha = config.alpha; \
321 if(components == 3) \
323 if(red == ALPHA_SRC) red = MAX_SRC; \
324 if(green == ALPHA_SRC) green = MAX_SRC; \
325 if(blue == ALPHA_SRC) blue = MAX_SRC; \
329 for(int i = 0; i < h; i++) \
331 type *inrow = (type*)frame->get_rows()[i]; \
332 type *outrow = (type*)temp->get_rows()[i]; \
334 for(int j = 0; j < w; j++) \
337 *outrow++ = *(inrow + red); \
339 *outrow++ = MAXMINSRC(red, 0, max); \
342 *outrow++ = *(inrow + green); \
344 *outrow++ = MAXMINSRC(green, min, max); \
347 *outrow++ = *(inrow + blue); \
349 *outrow++ = MAXMINSRC(blue, min, max); \
351 if(components == 4) \
354 *outrow++ = *(inrow + alpha); \
356 *outrow++ = MAXMINSRC(alpha, 0, max); \
359 inrow += components; \
363 frame->copy_from(temp); \
368 int SwapMain::process_buffer(VFrame *frame,
369 int64_t start_position,
372 load_configuration();
389 temp = new_temp(frame->get_w(),
391 frame->get_color_model());
393 switch(frame->get_color_model())
396 SWAP_CHANNELS(float, 0, 1, 3);
399 SWAP_CHANNELS(float, 0, 1, 4);
402 SWAP_CHANNELS(unsigned char, 0, 0xff, 3);
405 SWAP_CHANNELS(unsigned char, 0x80, 0xff, 3);
408 SWAP_CHANNELS(unsigned char, 0, 0xff, 4);
411 SWAP_CHANNELS(unsigned char, 0x80, 0xff, 4);
420 const char* SwapMain::output_to_text(int value)
448 int SwapMain::text_to_output(const char *text)
450 if(!strcmp(text, _("Red"))) return RED_SRC;
451 if(!strcmp(text, _("Green"))) return GREEN_SRC;
452 if(!strcmp(text, _("Blue"))) return BLUE_SRC;
453 if(!strcmp(text, _("Alpha"))) return ALPHA_SRC;
454 if(!strcmp(text, "0%")) return NO_SRC;
455 if(!strcmp(text, "100%")) return MAX_SRC;
459 int SwapMain::handle_opengl()
463 char output_frag[BCTEXTLEN];
465 "uniform sampler2D tex;\n"
466 "uniform float chroma_offset;\n"
469 " vec4 in_color = texture2D(tex, gl_TexCoord[0].st);\n"
470 " vec4 out_color;\n");
472 #define COLOR_SWITCH(config, variable) \
473 strcat(output_frag, " out_color." variable " = "); \
476 case RED_SRC: strcat(output_frag, "in_color.r;\n"); break; \
477 case GREEN_SRC: strcat(output_frag, "in_color.g;\n"); break; \
478 case BLUE_SRC: strcat(output_frag, "in_color.b;\n"); break; \
479 case ALPHA_SRC: strcat(output_frag, "in_color.a;\n"); break; \
480 case NO_SRC: strcat(output_frag, "chroma_offset;\n"); break; \
481 case MAX_SRC: strcat(output_frag, "1.0;\n"); break; \
485 COLOR_SWITCH(config.red, "r");
486 COLOR_SWITCH(config.green, "g");
487 COLOR_SWITCH(config.blue, "b");
488 COLOR_SWITCH(config.alpha, "a");
491 " gl_FragColor = out_color;\n"
494 get_output()->to_texture();
495 get_output()->enable_opengl();
496 get_output()->init_screen();
497 get_output()->clear_pbuffer();
498 get_output()->bind_texture(0);
500 unsigned int shader = VFrame::make_shader(0, output_frag, 0);
502 glUseProgram(shader);
503 glUniform1i(glGetUniformLocation(shader, "tex"), 0);
504 glUniform1f(glGetUniformLocation(shader, "chroma_offset"),
505 BC_CModels::is_yuv(get_output()->get_color_model()) ? 0.5 : 0.0);
508 get_output()->draw_texture();
510 get_output()->set_opengl_state(VFrame::SCREEN);