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()
54 void SwapConfig::reset_Config()
63 int SwapConfig::equivalent(SwapConfig &that)
65 return (red == that.red &&
66 green == that.green &&
71 void SwapConfig::copy_from(SwapConfig &that)
86 SwapWindow::SwapWindow(SwapMain *plugin)
87 : PluginClientWindow(plugin,
94 this->plugin = plugin;
97 SwapWindow::~SwapWindow()
102 void SwapWindow::create_objects()
104 int xs10 = xS(10), xs30 = xS(30), xs160 = xS(160);
105 int ys5 = yS(5), ys10 = yS(10), ys40 = yS(40);
106 int x = xs10, y = ys10;
109 add_subwindow(new BC_Title(x, y, _("Swap channels")));
111 add_subwindow(new BC_Title(x + xs160, y + ys5, _("-> Red")));
112 add_subwindow(red = new SwapMenu(plugin, &(plugin->config.red), x, y));
113 red->create_objects();
115 add_subwindow(new BC_Title(x + xs160, y + ys5, _("-> Green")));
116 add_subwindow(green = new SwapMenu(plugin, &(plugin->config.green), x, y));
117 green->create_objects();
119 add_subwindow(new BC_Title(x + xs160, y + ys5, _("-> Blue")));
120 add_subwindow(blue = new SwapMenu(plugin, &(plugin->config.blue), x, y));
121 blue->create_objects();
123 add_subwindow(new BC_Title(x + xs160, y + ys5, _("-> Alpha")));
124 add_subwindow(alpha = new SwapMenu(plugin, &(plugin->config.alpha), x, y));
125 alpha->create_objects();
128 add_subwindow(reset = new SwapReset(plugin, this, x, y));
141 SwapMenu::SwapMenu(SwapMain *client, int *output, int x, int y)
142 : BC_PopupMenu(x, y, xS(150), client->output_to_text(*output))
144 this->client = client;
145 this->output = output;
148 int SwapMenu::handle_event()
150 client->send_configure_change();
154 void SwapMenu::create_objects()
156 add_item(new SwapItem(this, client->output_to_text(RED_SRC)));
157 add_item(new SwapItem(this, client->output_to_text(GREEN_SRC)));
158 add_item(new SwapItem(this, client->output_to_text(BLUE_SRC)));
159 add_item(new SwapItem(this, client->output_to_text(ALPHA_SRC)));
160 add_item(new SwapItem(this, client->output_to_text(NO_SRC)));
161 add_item(new SwapItem(this, client->output_to_text(MAX_SRC)));
167 SwapItem::SwapItem(SwapMenu *menu, const char *title)
173 int SwapItem::handle_event()
175 menu->set_text(get_text());
176 *(menu->output) = menu->client->text_to_output(get_text());
177 menu->handle_event();
183 SwapReset::SwapReset(SwapMain *plugin, SwapWindow *gui, int x, int y)
184 : BC_GenericButton(x, y, _("Reset"))
186 this->plugin = plugin;
189 SwapReset::~SwapReset()
192 int SwapReset::handle_event()
194 plugin->config.reset_Config();
195 plugin->send_configure_change();
196 plugin->update_gui();
215 SwapMain::SwapMain(PluginServer *server)
216 : PluginVClient(server)
222 SwapMain::~SwapMain()
226 // if(temp) delete temp;
229 void SwapMain::reset()
235 const char* SwapMain::plugin_title() { return N_("Swap channels"); }
236 int SwapMain::is_synthesis() { return 1; }
237 int SwapMain::is_realtime() { return 1; }
239 NEW_WINDOW_MACRO(SwapMain, SwapWindow)
242 void SwapMain::save_data(KeyFrame *keyframe)
246 // cause data to be stored directly in text
247 output.set_shared_output(keyframe->xbuf);
248 output.tag.set_title("SWAPCHANNELS");
249 output.tag.set_property("RED", config.red);
250 output.tag.set_property("GREEN", config.green);
251 output.tag.set_property("BLUE", config.blue);
252 output.tag.set_property("ALPHA", config.alpha);
254 output.tag.set_title("/SWAPCHANNELS");
256 output.append_newline();
257 output.terminate_string();
258 // data is now in *text
261 void SwapMain::read_data(KeyFrame *keyframe)
265 input.set_shared_input(keyframe->xbuf);
271 result = input.read_tag();
275 if(input.tag.title_is("SWAPCHANNELS"))
277 config.red = input.tag.get_property("RED", config.red);
278 config.green = input.tag.get_property("GREEN", config.green);
279 config.blue = input.tag.get_property("BLUE", config.blue);
280 config.alpha = input.tag.get_property("ALPHA", config.alpha);
286 void SwapMain::update_gui()
290 load_configuration();
291 thread->window->lock_window();
292 ((SwapWindow*)thread->window)->red->set_text(output_to_text(config.red));
293 ((SwapWindow*)thread->window)->green->set_text(output_to_text(config.green));
294 ((SwapWindow*)thread->window)->blue->set_text(output_to_text(config.blue));
295 ((SwapWindow*)thread->window)->alpha->set_text(output_to_text(config.alpha));
296 thread->window->unlock_window();
301 int SwapMain::load_configuration()
303 KeyFrame *prev_keyframe;
304 prev_keyframe = get_prev_keyframe(get_source_position());
306 read_data(prev_keyframe);
333 #define MAXMINSRC(src, min, max) \
334 (src == MAX_SRC ? max : min)
336 #define SWAP_CHANNELS(type, min, max, components) \
338 int h = frame->get_h(); \
339 int w = frame->get_w(); \
340 int red = config.red; \
341 int green = config.green; \
342 int blue = config.blue; \
343 int alpha = config.alpha; \
345 if(components == 3) \
347 if(red == ALPHA_SRC) red = MAX_SRC; \
348 if(green == ALPHA_SRC) green = MAX_SRC; \
349 if(blue == ALPHA_SRC) blue = MAX_SRC; \
353 for(int i = 0; i < h; i++) \
355 type *inrow = (type*)frame->get_rows()[i]; \
356 type *outrow = (type*)temp->get_rows()[i]; \
358 for(int j = 0; j < w; j++) \
361 *outrow++ = *(inrow + red); \
363 *outrow++ = MAXMINSRC(red, 0, max); \
366 *outrow++ = *(inrow + green); \
368 *outrow++ = MAXMINSRC(green, min, max); \
371 *outrow++ = *(inrow + blue); \
373 *outrow++ = MAXMINSRC(blue, min, max); \
375 if(components == 4) \
378 *outrow++ = *(inrow + alpha); \
380 *outrow++ = MAXMINSRC(alpha, 0, max); \
383 inrow += components; \
387 frame->copy_from(temp); \
392 int SwapMain::process_buffer(VFrame *frame,
393 int64_t start_position,
396 load_configuration();
413 temp = new_temp(frame->get_w(),
415 frame->get_color_model());
417 switch(frame->get_color_model())
420 SWAP_CHANNELS(float, 0, 1, 3);
423 SWAP_CHANNELS(float, 0, 1, 4);
426 SWAP_CHANNELS(unsigned char, 0, 0xff, 3);
429 SWAP_CHANNELS(unsigned char, 0x80, 0xff, 3);
432 SWAP_CHANNELS(unsigned char, 0, 0xff, 4);
435 SWAP_CHANNELS(unsigned char, 0x80, 0xff, 4);
444 const char* SwapMain::output_to_text(int value)
472 int SwapMain::text_to_output(const char *text)
474 if(!strcmp(text, _("Red"))) return RED_SRC;
475 if(!strcmp(text, _("Green"))) return GREEN_SRC;
476 if(!strcmp(text, _("Blue"))) return BLUE_SRC;
477 if(!strcmp(text, _("Alpha"))) return ALPHA_SRC;
478 if(!strcmp(text, "0%")) return NO_SRC;
479 if(!strcmp(text, "100%")) return MAX_SRC;
483 int SwapMain::handle_opengl()
487 char output_frag[BCTEXTLEN];
489 "uniform sampler2D tex;\n"
490 "uniform float chroma_offset;\n"
493 " vec4 in_color = texture2D(tex, gl_TexCoord[0].st);\n"
494 " vec4 out_color;\n");
496 #define COLOR_SWITCH(config, variable) \
497 strcat(output_frag, " out_color." variable " = "); \
500 case RED_SRC: strcat(output_frag, "in_color.r;\n"); break; \
501 case GREEN_SRC: strcat(output_frag, "in_color.g;\n"); break; \
502 case BLUE_SRC: strcat(output_frag, "in_color.b;\n"); break; \
503 case ALPHA_SRC: strcat(output_frag, "in_color.a;\n"); break; \
504 case NO_SRC: strcat(output_frag, "chroma_offset;\n"); break; \
505 case MAX_SRC: strcat(output_frag, "1.0;\n"); break; \
509 COLOR_SWITCH(config.red, "r");
510 COLOR_SWITCH(config.green, "g");
511 COLOR_SWITCH(config.blue, "b");
512 COLOR_SWITCH(config.alpha, "a");
515 " gl_FragColor = out_color;\n"
518 get_output()->to_texture();
519 get_output()->enable_opengl();
520 get_output()->init_screen();
521 get_output()->clear_pbuffer();
522 get_output()->bind_texture(0);
524 unsigned int shader = VFrame::make_shader(0, output_frag, 0);
526 glUseProgram(shader);
527 glUniform1i(glGetUniformLocation(shader, "tex"), 0);
528 glUniform1f(glGetUniformLocation(shader, "chroma_offset"),
529 BC_CModels::is_yuv(get_output()->get_color_model()) ? 0.5 : 0.0);
532 get_output()->draw_texture();
534 get_output()->set_opengl_state(VFrame::SCREEN);