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()
107 add_subwindow(new BC_Title(x, y, _("Swap channels")));
109 add_subwindow(new BC_Title(x + 160, y + 5, _("-> Red")));
110 add_subwindow(red = new SwapMenu(plugin, &(plugin->config.red), x, y));
111 red->create_objects();
113 add_subwindow(new BC_Title(x + 160, y + 5, _("-> Green")));
114 add_subwindow(green = new SwapMenu(plugin, &(plugin->config.green), x, y));
115 green->create_objects();
117 add_subwindow(new BC_Title(x + 160, y + 5, _("-> Blue")));
118 add_subwindow(blue = new SwapMenu(plugin, &(plugin->config.blue), x, y));
119 blue->create_objects();
121 add_subwindow(new BC_Title(x + 160, y + 5, _("-> Alpha")));
122 add_subwindow(alpha = new SwapMenu(plugin, &(plugin->config.alpha), x, y));
123 alpha->create_objects();
126 add_subwindow(reset = new SwapReset(plugin, this, x, y));
139 SwapMenu::SwapMenu(SwapMain *client, int *output, int x, int y)
140 : BC_PopupMenu(x, y, 150, client->output_to_text(*output))
142 this->client = client;
143 this->output = output;
146 int SwapMenu::handle_event()
148 client->send_configure_change();
152 void SwapMenu::create_objects()
154 add_item(new SwapItem(this, client->output_to_text(RED_SRC)));
155 add_item(new SwapItem(this, client->output_to_text(GREEN_SRC)));
156 add_item(new SwapItem(this, client->output_to_text(BLUE_SRC)));
157 add_item(new SwapItem(this, client->output_to_text(ALPHA_SRC)));
158 add_item(new SwapItem(this, client->output_to_text(NO_SRC)));
159 add_item(new SwapItem(this, client->output_to_text(MAX_SRC)));
165 SwapItem::SwapItem(SwapMenu *menu, const char *title)
171 int SwapItem::handle_event()
173 menu->set_text(get_text());
174 *(menu->output) = menu->client->text_to_output(get_text());
175 menu->handle_event();
181 SwapReset::SwapReset(SwapMain *plugin, SwapWindow *gui, int x, int y)
182 : BC_GenericButton(x, y, _("Reset"))
184 this->plugin = plugin;
187 SwapReset::~SwapReset()
190 int SwapReset::handle_event()
192 plugin->config.reset_Config();
193 plugin->send_configure_change();
194 plugin->update_gui();
213 SwapMain::SwapMain(PluginServer *server)
214 : PluginVClient(server)
220 SwapMain::~SwapMain()
224 // if(temp) delete temp;
227 void SwapMain::reset()
233 const char* SwapMain::plugin_title() { return N_("Swap channels"); }
234 int SwapMain::is_synthesis() { return 1; }
235 int SwapMain::is_realtime() { return 1; }
237 NEW_WINDOW_MACRO(SwapMain, SwapWindow)
240 void SwapMain::save_data(KeyFrame *keyframe)
244 // cause data to be stored directly in text
245 output.set_shared_output(keyframe->xbuf);
246 output.tag.set_title("SWAPCHANNELS");
247 output.tag.set_property("RED", config.red);
248 output.tag.set_property("GREEN", config.green);
249 output.tag.set_property("BLUE", config.blue);
250 output.tag.set_property("ALPHA", config.alpha);
252 output.tag.set_title("/SWAPCHANNELS");
254 output.append_newline();
255 output.terminate_string();
256 // data is now in *text
259 void SwapMain::read_data(KeyFrame *keyframe)
263 input.set_shared_input(keyframe->xbuf);
269 result = input.read_tag();
273 if(input.tag.title_is("SWAPCHANNELS"))
275 config.red = input.tag.get_property("RED", config.red);
276 config.green = input.tag.get_property("GREEN", config.green);
277 config.blue = input.tag.get_property("BLUE", config.blue);
278 config.alpha = input.tag.get_property("ALPHA", config.alpha);
284 void SwapMain::update_gui()
288 load_configuration();
289 thread->window->lock_window();
290 ((SwapWindow*)thread->window)->red->set_text(output_to_text(config.red));
291 ((SwapWindow*)thread->window)->green->set_text(output_to_text(config.green));
292 ((SwapWindow*)thread->window)->blue->set_text(output_to_text(config.blue));
293 ((SwapWindow*)thread->window)->alpha->set_text(output_to_text(config.alpha));
294 thread->window->unlock_window();
299 int SwapMain::load_configuration()
301 KeyFrame *prev_keyframe;
302 prev_keyframe = get_prev_keyframe(get_source_position());
304 read_data(prev_keyframe);
331 #define MAXMINSRC(src, min, max) \
332 (src == MAX_SRC ? max : min)
334 #define SWAP_CHANNELS(type, min, max, components) \
336 int h = frame->get_h(); \
337 int w = frame->get_w(); \
338 int red = config.red; \
339 int green = config.green; \
340 int blue = config.blue; \
341 int alpha = config.alpha; \
343 if(components == 3) \
345 if(red == ALPHA_SRC) red = MAX_SRC; \
346 if(green == ALPHA_SRC) green = MAX_SRC; \
347 if(blue == ALPHA_SRC) blue = MAX_SRC; \
351 for(int i = 0; i < h; i++) \
353 type *inrow = (type*)frame->get_rows()[i]; \
354 type *outrow = (type*)temp->get_rows()[i]; \
356 for(int j = 0; j < w; j++) \
359 *outrow++ = *(inrow + red); \
361 *outrow++ = MAXMINSRC(red, 0, max); \
364 *outrow++ = *(inrow + green); \
366 *outrow++ = MAXMINSRC(green, min, max); \
369 *outrow++ = *(inrow + blue); \
371 *outrow++ = MAXMINSRC(blue, min, max); \
373 if(components == 4) \
376 *outrow++ = *(inrow + alpha); \
378 *outrow++ = MAXMINSRC(alpha, 0, max); \
381 inrow += components; \
385 frame->copy_from(temp); \
390 int SwapMain::process_buffer(VFrame *frame,
391 int64_t start_position,
394 load_configuration();
411 temp = new_temp(frame->get_w(),
413 frame->get_color_model());
415 switch(frame->get_color_model())
418 SWAP_CHANNELS(float, 0, 1, 3);
421 SWAP_CHANNELS(float, 0, 1, 4);
424 SWAP_CHANNELS(unsigned char, 0, 0xff, 3);
427 SWAP_CHANNELS(unsigned char, 0x80, 0xff, 3);
430 SWAP_CHANNELS(unsigned char, 0, 0xff, 4);
433 SWAP_CHANNELS(unsigned char, 0x80, 0xff, 4);
442 const char* SwapMain::output_to_text(int value)
470 int SwapMain::text_to_output(const char *text)
472 if(!strcmp(text, _("Red"))) return RED_SRC;
473 if(!strcmp(text, _("Green"))) return GREEN_SRC;
474 if(!strcmp(text, _("Blue"))) return BLUE_SRC;
475 if(!strcmp(text, _("Alpha"))) return ALPHA_SRC;
476 if(!strcmp(text, "0%")) return NO_SRC;
477 if(!strcmp(text, "100%")) return MAX_SRC;
481 int SwapMain::handle_opengl()
485 char output_frag[BCTEXTLEN];
487 "uniform sampler2D tex;\n"
488 "uniform float chroma_offset;\n"
491 " vec4 in_color = texture2D(tex, gl_TexCoord[0].st);\n"
492 " vec4 out_color;\n");
494 #define COLOR_SWITCH(config, variable) \
495 strcat(output_frag, " out_color." variable " = "); \
498 case RED_SRC: strcat(output_frag, "in_color.r;\n"); break; \
499 case GREEN_SRC: strcat(output_frag, "in_color.g;\n"); break; \
500 case BLUE_SRC: strcat(output_frag, "in_color.b;\n"); break; \
501 case ALPHA_SRC: strcat(output_frag, "in_color.a;\n"); break; \
502 case NO_SRC: strcat(output_frag, "chroma_offset;\n"); break; \
503 case MAX_SRC: strcat(output_frag, "1.0;\n"); break; \
507 COLOR_SWITCH(config.red, "r");
508 COLOR_SWITCH(config.green, "g");
509 COLOR_SWITCH(config.blue, "b");
510 COLOR_SWITCH(config.alpha, "a");
513 " gl_FragColor = out_color;\n"
516 get_output()->to_texture();
517 get_output()->enable_opengl();
518 get_output()->init_screen();
519 get_output()->clear_pbuffer();
520 get_output()->bind_texture(0);
522 unsigned int shader = VFrame::make_shader(0, output_frag, 0);
524 glUseProgram(shader);
525 glUniform1i(glGetUniformLocation(shader, "tex"), 0);
526 glUniform1f(glGetUniformLocation(shader, "chroma_offset"),
527 BC_CModels::is_yuv(get_output()->get_color_model()) ? 0.5 : 0.0);
530 get_output()->draw_texture();
532 get_output()->set_opengl_state(VFrame::SCREEN);