5 #include "bcdisplayinfo.h"
11 #include "overlayframe.h"
12 #include "picon_png.h"
16 #define _(String) gettext(String)
17 #define gettext_noop(String) String
18 #define N_(String) gettext_noop (String)
22 REGISTER_PLUGIN(GradientMain)
29 GradientConfig::GradientConfig()
44 int GradientConfig::equivalent(GradientConfig &that)
46 return (EQUIV(angle, that.angle) &&
47 EQUIV(in_radius, that.in_radius) &&
48 EQUIV(out_radius, that.out_radius) &&
53 out_r == that.out_r &&
54 out_g == that.out_g &&
55 out_b == that.out_b &&
59 void GradientConfig::copy_from(GradientConfig &that)
62 in_radius = that.in_radius;
63 out_radius = that.out_radius;
74 void GradientConfig::interpolate(GradientConfig &prev,
80 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
81 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
84 this->angle = (int)(prev.angle * prev_scale + next.angle * next_scale);
85 this->in_radius = (int)(prev.in_radius * prev_scale + next.in_radius * next_scale);
86 this->out_radius = (int)(prev.out_radius * prev_scale + next.out_radius * next_scale);
87 in_r = (int)(prev.in_r * prev_scale + next.in_r * next_scale);
88 in_g = (int)(prev.in_g * prev_scale + next.in_g * next_scale);
89 in_b = (int)(prev.in_b * prev_scale + next.in_b * next_scale);
90 in_a = (int)(prev.in_a * prev_scale + next.in_a * next_scale);
91 out_r = (int)(prev.out_r * prev_scale + next.out_r * next_scale);
92 out_g = (int)(prev.out_g * prev_scale + next.out_g * next_scale);
93 out_b = (int)(prev.out_b * prev_scale + next.out_b * next_scale);
94 out_a = (int)(prev.out_a * prev_scale + next.out_a * next_scale);
97 int GradientConfig::get_in_color()
99 int result = (in_r << 16) | (in_g << 8) | (in_b);
103 int GradientConfig::get_out_color()
105 int result = (out_r << 16) | (out_g << 8) | (out_b);
117 PLUGIN_THREAD_OBJECT(GradientMain, GradientThread, GradientWindow)
123 GradientWindow::GradientWindow(GradientMain *plugin, int x, int y)
124 : BC_Window(plugin->gui_string,
134 this->plugin = plugin;
137 GradientWindow::~GradientWindow()
139 delete in_color_thread;
140 delete out_color_thread;
143 int GradientWindow::create_objects()
145 int x = 10, y = 10, x2 = 130;
147 add_subwindow(new BC_Title(x, y, _("Angle:")));
148 add_subwindow(angle = new GradientAngle(plugin, x2, y));
150 add_subwindow(new BC_Title(x, y, _("Inner radius:")));
151 add_subwindow(in_radius = new GradientInRadius(plugin, x2, y));
153 add_subwindow(new BC_Title(x, y, _("Outer radius:")));
154 add_subwindow(out_radius = new GradientOutRadius(plugin, x2, y));
156 add_subwindow(in_color = new GradientInColorButton(plugin, this, x, y));
160 add_subwindow(out_color = new GradientOutColorButton(plugin, this, x, y));
163 in_color_thread = new GradientInColorThread(plugin, this);
164 out_color_thread = new GradientOutColorThread(plugin, this);
173 int GradientWindow::close_event()
175 // Set result to 1 to indicate a plugin side close
180 void GradientWindow::update_in_color()
182 //printf("GradientWindow::update_in_color 1 %08x\n", plugin->config.get_in_color());
183 set_color(plugin->config.get_in_color());
184 draw_box(in_color_x, in_color_y, COLOR_W, COLOR_H);
185 flash(in_color_x, in_color_y, COLOR_W, COLOR_H);
188 void GradientWindow::update_out_color()
190 //printf("GradientWindow::update_out_color 1 %08x\n", plugin->config.get_in_color());
191 set_color(plugin->config.get_out_color());
192 draw_box(out_color_x, out_color_y, COLOR_W, COLOR_H);
193 flash(out_color_x, out_color_y, COLOR_W, COLOR_H);
204 GradientAngle::GradientAngle(GradientMain *plugin, int x, int y)
207 plugin->config.angle,
211 this->plugin = plugin;
214 int GradientAngle::handle_event()
216 plugin->config.angle = get_value();
217 plugin->send_configure_change();
222 GradientInRadius::GradientInRadius(GradientMain *plugin, int x, int y)
230 (float)plugin->config.in_radius)
232 this->plugin = plugin;
235 int GradientInRadius::handle_event()
237 plugin->config.in_radius = get_value();
238 plugin->send_configure_change();
243 GradientOutRadius::GradientOutRadius(GradientMain *plugin, int x, int y)
251 (float)plugin->config.out_radius)
253 this->plugin = plugin;
256 int GradientOutRadius::handle_event()
258 plugin->config.out_radius = get_value();
259 plugin->send_configure_change();
263 GradientInColorButton::GradientInColorButton(GradientMain *plugin, GradientWindow *window, int x, int y)
264 : BC_GenericButton(x, y, _("Inner color:"))
266 this->plugin = plugin;
267 this->window = window;
270 int GradientInColorButton::handle_event()
272 window->in_color_thread->start_window(
273 plugin->config.get_in_color(),
274 plugin->config.in_a);
279 GradientOutColorButton::GradientOutColorButton(GradientMain *plugin, GradientWindow *window, int x, int y)
280 : BC_GenericButton(x, y, _("Outer color:"))
282 this->plugin = plugin;
283 this->window = window;
286 int GradientOutColorButton::handle_event()
288 window->out_color_thread->start_window(
289 plugin->config.get_out_color(),
290 plugin->config.out_a);
296 GradientInColorThread::GradientInColorThread(GradientMain *plugin,
297 GradientWindow *window)
298 : ColorThread(1, _("Inner color"))
300 this->plugin = plugin;
301 this->window = window;
304 int GradientInColorThread::handle_event(int output)
306 plugin->config.in_r = (output & 0xff0000) >> 16;
307 plugin->config.in_g = (output & 0xff00) >> 8;
308 plugin->config.in_b = (output & 0xff);
309 plugin->config.in_a = alpha;
310 window->update_in_color();
312 plugin->send_configure_change();
313 // printf("GradientInColorThread::handle_event 1 %d %d %d %d %d %d %d %d\n",
314 // plugin->config.in_r,
315 // plugin->config.in_g,
316 // plugin->config.in_b,
317 // plugin->config.in_a,
318 // plugin->config.out_r,
319 // plugin->config.out_g,
320 // plugin->config.out_b,
321 // plugin->config.out_a);
328 GradientOutColorThread::GradientOutColorThread(GradientMain *plugin,
329 GradientWindow *window)
330 : ColorThread(1, _("Outer color"))
332 this->plugin = plugin;
333 this->window = window;
336 int GradientOutColorThread::handle_event(int output)
338 plugin->config.out_r = (output & 0xff0000) >> 16;
339 plugin->config.out_g = (output & 0xff00) >> 8;
340 plugin->config.out_b = (output & 0xff);
341 plugin->config.out_a = alpha;
342 window->update_out_color();
344 plugin->send_configure_change();
345 // printf("GradientOutColorThread::handle_event 1 %d %d %d %d %d %d %d %d\n",
346 // plugin->config.in_r,
347 // plugin->config.in_g,
348 // plugin->config.in_b,
349 // plugin->config.in_a,
350 // plugin->config.out_r,
351 // plugin->config.out_g,
352 // plugin->config.out_b,
353 // plugin->config.out_a);
368 GradientMain::GradientMain(PluginServer *server)
369 : PluginVClient(server)
371 PLUGIN_CONSTRUCTOR_MACRO
372 need_reconfigure = 1;
378 GradientMain::~GradientMain()
380 PLUGIN_DESTRUCTOR_MACRO
382 if(gradient) delete gradient;
383 if(engine) delete engine;
384 if(overlayer) delete overlayer;
387 char* GradientMain::plugin_title() { return _("Gradient"); }
388 int GradientMain::is_realtime() { return 1; }
391 NEW_PICON_MACRO(GradientMain)
393 SHOW_GUI_MACRO(GradientMain, GradientThread)
395 SET_STRING_MACRO(GradientMain)
397 RAISE_WINDOW_MACRO(GradientMain)
399 LOAD_CONFIGURATION_MACRO(GradientMain, GradientConfig)
401 int GradientMain::is_synthesis()
407 int GradientMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
409 this->input = input_ptr;
410 this->output = output_ptr;
411 need_reconfigure |= load_configuration();
413 // printf("GradientMain::process_realtime 1 %d %d %d %d %d %d %d %d\n",
425 // Generate new gradient
428 need_reconfigure = 0;
430 //printf("GradientMain::process_realtime 1\n");
431 if(!gradient) gradient = new VFrame(0,
434 input->get_color_model());
436 if(!engine) engine = new GradientServer(this,
437 get_project_smp() + 1,
438 get_project_smp() + 1);
439 engine->process_packages();
442 //printf("GradientMain::process_realtime 2\n");
443 // Overlay new gradient
444 if(output->get_rows()[0] != input->get_rows()[0])
446 output->copy_from(input);
449 //printf("GradientMain::process_realtime 2\n");
450 if(!overlayer) overlayer = new OverlayFrame(get_project_smp() + 1);
451 overlayer->overlay(output,
464 //printf("GradientMain::process_realtime 2\n");
470 void GradientMain::update_gui()
474 load_configuration();
475 thread->window->lock_window();
476 thread->window->angle->update(config.angle);
477 thread->window->in_radius->update(config.in_radius);
478 thread->window->out_radius->update(config.out_radius);
479 thread->window->update_in_color();
480 thread->window->update_out_color();
481 thread->window->unlock_window();
486 int GradientMain::load_defaults()
488 char directory[1024], string[1024];
489 // set the default directory
490 sprintf(directory, "%sgradient.rc", BCASTDIR);
493 defaults = new Defaults(directory);
496 // printf("GradientMain::load_defaults %d %d %d %d\n",
501 config.angle = defaults->get("ANGLE", config.angle);
502 config.in_radius = defaults->get("IN_RADIUS", config.in_radius);
503 config.out_radius = defaults->get("OUT_RADIUS", config.out_radius);
504 config.in_r = defaults->get("IN_R", config.in_r);
505 config.in_g = defaults->get("IN_G", config.in_g);
506 config.in_b = defaults->get("IN_B", config.in_b);
507 config.in_a = defaults->get("IN_A", config.in_a);
508 config.out_r = defaults->get("OUT_R", config.out_r);
509 config.out_g = defaults->get("OUT_G", config.out_g);
510 config.out_b = defaults->get("OUT_B", config.out_b);
511 config.out_a = defaults->get("OUT_A", config.out_a);
516 int GradientMain::save_defaults()
518 defaults->update("ANGLE", config.angle);
519 defaults->update("IN_RADIUS", config.in_radius);
520 defaults->update("OUT_RADIUS", config.out_radius);
521 defaults->update("IN_R", config.in_r);
522 defaults->update("IN_G", config.in_g);
523 defaults->update("IN_B", config.in_b);
524 defaults->update("IN_A", config.in_a);
525 defaults->update("OUT_R", config.out_r);
526 defaults->update("OUT_G", config.out_g);
527 defaults->update("OUT_B", config.out_b);
528 defaults->update("OUT_A", config.out_a);
535 void GradientMain::save_data(KeyFrame *keyframe)
539 // cause data to be stored directly in text
540 output.set_shared_string(keyframe->data, MESSAGESIZE);
541 output.tag.set_title("GRADIENT");
543 output.tag.set_property("ANGLE", config.angle);
544 output.tag.set_property("IN_RADIUS", config.in_radius);
545 output.tag.set_property("OUT_RADIUS", config.out_radius);
546 output.tag.set_property("IN_R", config.in_r);
547 output.tag.set_property("IN_G", config.in_g);
548 output.tag.set_property("IN_B", config.in_b);
549 output.tag.set_property("IN_A", config.in_a);
550 output.tag.set_property("OUT_R", config.out_r);
551 output.tag.set_property("OUT_G", config.out_g);
552 output.tag.set_property("OUT_B", config.out_b);
553 output.tag.set_property("OUT_A", config.out_a);
555 output.terminate_string();
558 void GradientMain::read_data(KeyFrame *keyframe)
562 input.set_shared_string(keyframe->data, strlen(keyframe->data));
568 result = input.read_tag();
572 if(input.tag.title_is("GRADIENT"))
574 config.angle = input.tag.get_property("ANGLE", config.angle);
575 config.in_radius = input.tag.get_property("IN_RADIUS", config.in_radius);
576 config.out_radius = input.tag.get_property("OUT_RADIUS", config.out_radius);
577 config.in_r = input.tag.get_property("IN_R", config.in_r);
578 config.in_g = input.tag.get_property("IN_G", config.in_g);
579 config.in_b = input.tag.get_property("IN_B", config.in_b);
580 config.in_a = input.tag.get_property("IN_A", config.in_a);
581 config.out_r = input.tag.get_property("OUT_R", config.out_r);
582 config.out_g = input.tag.get_property("OUT_G", config.out_g);
583 config.out_b = input.tag.get_property("OUT_B", config.out_b);
584 config.out_a = input.tag.get_property("OUT_A", config.out_a);
595 GradientPackage::GradientPackage()
603 GradientUnit::GradientUnit(GradientServer *server, GradientMain *plugin)
606 this->plugin = plugin;
607 this->server = server;
611 #define SQR(x) ((x) * (x))
614 #define CREATE_GRADIENT(type, components, max) \
616 /* Synthesize linear gradient for lookups */ \
618 for(int i = 0; i < gradient_size; i++) \
621 float transparency; \
626 opacity = (float)(i - in_radius) / (out_radius - in_radius); \
629 transparency = 1.0 - opacity; \
630 r_table[i] = (int)(out1 * opacity + in1 * transparency); \
631 g_table[i] = (int)(out2 * opacity + in2 * transparency); \
632 b_table[i] = (int)(out3 * opacity + in3 * transparency); \
633 a_table[i] = (int)(out4 * opacity + in4 * transparency); \
636 for(int i = pkg->y1; i < pkg->y2; i++) \
638 type *out_row = (type*)plugin->gradient->get_rows()[i]; \
640 for(int j = 0; j < w; j++) \
642 /* Convert to polar coords */ \
643 int x = j - half_w; \
644 int y = -(i - half_h); \
645 double magnitude = sqrt(SQR(x) + SQR(y)); \
649 angle = atan((float)y / x); \
650 if(x > 0 && y < 0) angle = M_PI / 2 - angle; \
651 if(x > 0 && y > 0) angle = M_PI / 2 - angle; \
652 if(x < 0 && y > 0) angle = -M_PI / 2 - angle; \
653 if(x < 0 && y < 0) angle = -M_PI / 2 - angle; \
654 if(y == 0 && x > 0) angle = M_PI / 2; \
655 if(y == 0 && x < 0) angle = -M_PI / 2; \
665 /* Rotate by effect angle */ \
666 angle -= effect_angle; \
668 /* Convert to cartesian coords */ \
669 int input_y = (int)(gradient_size / 2 - magnitude * cos(angle)); \
671 /* Get gradient value from these coords */ \
678 if(components == 4) out_row[3] = out4; \
681 if(input_y >= gradient_size) \
686 if(components == 4) out_row[3] = in4; \
690 out_row[0] = r_table[input_y]; \
691 out_row[1] = g_table[input_y]; \
692 out_row[2] = b_table[input_y]; \
693 if(components == 4) out_row[3] = a_table[input_y]; \
696 out_row += components; \
701 void GradientUnit::process_package(LoadPackage *package)
703 GradientPackage *pkg = (GradientPackage*)package;
704 int in1, in2, in3, in4;
705 int out1, out2, out3, out4;
706 int h = plugin->input->get_h();
707 int w = plugin->input->get_w();
710 int gradient_size = (int)(sqrt(SQR(w) + SQR(h)) + 1);
711 int in_radius = (int)(plugin->config.in_radius / 100 * gradient_size);
712 int out_radius = (int)(plugin->config.out_radius / 100 * gradient_size);
713 double effect_angle = plugin->config.angle / 360 * 2 * M_PI;
714 int r_table[gradient_size];
715 int g_table[gradient_size];
716 int b_table[gradient_size];
717 int a_table[gradient_size];
719 if(in_radius > out_radius)
721 in_radius ^= out_radius ^= in_radius ^= out_radius;
725 switch(plugin->input->get_color_model())
728 in1 = plugin->config.in_r;
729 in2 = plugin->config.in_g;
730 in3 = plugin->config.in_b;
731 in4 = plugin->config.in_a;
732 out1 = plugin->config.out_r;
733 out2 = plugin->config.out_g;
734 out3 = plugin->config.out_b;
735 out4 = plugin->config.out_a;
736 CREATE_GRADIENT(unsigned char, 3, 0xff)
739 in1 = plugin->config.in_r;
740 in2 = plugin->config.in_g;
741 in3 = plugin->config.in_b;
742 in4 = plugin->config.in_a;
743 out1 = plugin->config.out_r;
744 out2 = plugin->config.out_g;
745 out3 = plugin->config.out_b;
746 out4 = plugin->config.out_a;
747 CREATE_GRADIENT(unsigned char, 4, 0xff)
750 in1 = (plugin->config.in_r << 8) | plugin->config.in_r;
751 in2 = (plugin->config.in_g << 8) | plugin->config.in_g;
752 in3 = (plugin->config.in_b << 8) | plugin->config.in_b;
753 in4 = (plugin->config.in_a << 8) | plugin->config.in_a;
754 out1 = (plugin->config.out_r << 8) | plugin->config.out_r;
755 out2 = (plugin->config.out_g << 8) | plugin->config.out_g;
756 out3 = (plugin->config.out_b << 8) | plugin->config.out_b;
757 out4 = (plugin->config.out_a << 8) | plugin->config.out_a;
758 CREATE_GRADIENT(uint16_t, 3, 0xffff)
760 case BC_RGBA16161616:
761 in1 = (plugin->config.in_r << 8) | plugin->config.in_r;
762 in2 = (plugin->config.in_g << 8) | plugin->config.in_g;
763 in3 = (plugin->config.in_b << 8) | plugin->config.in_b;
764 in4 = (plugin->config.in_a << 8) | plugin->config.in_a;
765 out1 = (plugin->config.out_r << 8) | plugin->config.out_r;
766 out2 = (plugin->config.out_g << 8) | plugin->config.out_g;
767 out3 = (plugin->config.out_b << 8) | plugin->config.out_b;
768 out4 = (plugin->config.out_a << 8) | plugin->config.out_a;
769 CREATE_GRADIENT(uint16_t, 4, 0xffff)
772 yuv.rgb_to_yuv_8(plugin->config.in_r,
778 in4 = plugin->config.in_a;
779 yuv.rgb_to_yuv_8(plugin->config.out_r,
780 plugin->config.out_g,
781 plugin->config.out_b,
785 out4 = plugin->config.out_a;
786 CREATE_GRADIENT(unsigned char, 3, 0xff)
789 yuv.rgb_to_yuv_8(plugin->config.in_r,
795 in4 = plugin->config.in_a;
796 yuv.rgb_to_yuv_8(plugin->config.out_r,
797 plugin->config.out_g,
798 plugin->config.out_b,
802 out4 = plugin->config.out_a;
803 CREATE_GRADIENT(unsigned char, 4, 0xff)
813 in4 = plugin->config.in_a;
815 (plugin->config.out_r << 8) | plugin->config.out_r,
816 (plugin->config.out_g << 8) | plugin->config.out_g,
817 (plugin->config.out_b << 8) | plugin->config.out_b,
821 out4 = (plugin->config.out_a << 8) | plugin->config.out_a;
822 CREATE_GRADIENT(uint16_t, 3, 0xffff)
824 case BC_YUVA16161616:
826 (plugin->config.in_r << 8) | plugin->config.in_r,
827 (plugin->config.in_g << 8) | plugin->config.in_g,
828 (plugin->config.in_b << 8) | plugin->config.in_b,
832 in4 = (plugin->config.in_a << 8) | plugin->config.in_a;
834 (plugin->config.out_r << 8) | plugin->config.out_r,
835 (plugin->config.out_g << 8) | plugin->config.out_g,
836 (plugin->config.out_b << 8) | plugin->config.out_b,
840 out4 = (plugin->config.out_a << 8) | plugin->config.out_a;
841 CREATE_GRADIENT(uint16_t, 4, 0xffff)
851 GradientServer::GradientServer(GradientMain *plugin,
854 : LoadServer(total_clients, total_packages)
856 this->plugin = plugin;
859 void GradientServer::init_packages()
861 for(int i = 0; i < total_packages; i++)
863 GradientPackage *package = (GradientPackage*)packages[i];
864 package->y1 = plugin->input->get_h() *
867 package->y2 = package->y1 +
868 plugin->input->get_h() /
870 if(i >= total_packages - 1) package->y2 = plugin->input->get_h();
874 LoadClient* GradientServer::new_client()
876 return new GradientUnit(this, plugin);
879 LoadPackage* GradientServer::new_package()
881 return new GradientPackage;