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
26 #include "bcdisplayinfo.h"
30 #include "timefront.h"
33 #include "overlayframe.h"
39 REGISTER_PLUGIN(TimeFrontMain)
46 TimeFrontConfig::TimeFrontConfig()
52 track_usage = TimeFrontConfig::OTHERTRACK_INTENSITY;
53 shape = TimeFrontConfig::LINEAR;
54 rate = TimeFrontConfig::LINEAR;
61 int TimeFrontConfig::equivalent(TimeFrontConfig &that)
63 return (EQUIV(angle, that.angle) &&
64 EQUIV(in_radius, that.in_radius) &&
65 EQUIV(out_radius, that.out_radius) &&
66 frame_range == that.frame_range &&
67 track_usage == that.track_usage &&
68 shape == that.shape &&
70 EQUIV(center_x, that.center_x) &&
71 EQUIV(center_y, that.center_y) &&
72 invert == that.invert &&
73 show_grayscale == that.show_grayscale);
76 void TimeFrontConfig::copy_from(TimeFrontConfig &that)
79 in_radius = that.in_radius;
80 out_radius = that.out_radius;
81 frame_range = that.frame_range;
82 track_usage = that.track_usage;
85 center_x = that.center_x;
86 center_y = that.center_y;
88 show_grayscale = that.show_grayscale;
91 void TimeFrontConfig::interpolate(TimeFrontConfig &prev,
92 TimeFrontConfig &next,
97 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
98 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
101 this->angle = (int)(prev.angle * prev_scale + next.angle * next_scale);
102 this->in_radius = (int)(prev.in_radius * prev_scale + next.in_radius * next_scale);
103 this->out_radius = (int)(prev.out_radius * prev_scale + next.out_radius * next_scale);
104 frame_range = (int)(prev.frame_range * prev_scale + next.frame_range * next_scale);
105 track_usage = prev.track_usage;
108 center_x = prev.center_x * prev_scale + next.center_x * next_scale;
109 center_y = prev.center_y * prev_scale + next.center_y * next_scale;
110 invert = prev.invert;
111 show_grayscale = prev.show_grayscale;
121 TimeFrontWindow::TimeFrontWindow(TimeFrontMain *plugin)
122 : PluginClientWindow(plugin,
129 this->plugin = plugin;
140 out_radius_title = 0;
142 track_usage_title = 0;
147 TimeFrontWindow::~TimeFrontWindow()
151 void TimeFrontWindow::create_objects()
156 add_subwindow(title = new BC_Title(x, y, _("Type:")));
157 add_subwindow(shape = new TimeFrontShape(plugin,
159 x + title->get_w() + 10,
161 shape->create_objects();
166 add_subwindow(title = new BC_Title(x, y, _("Time range:")));
167 add_subwindow(frame_range = new TimeFrontFrameRange(plugin, x + title->get_w() + 10, y));
168 frame_range_x = x + frame_range->get_w() + 10;
173 add_subwindow(invert = new TimeFrontInvert(plugin, x, y));
174 add_subwindow(show_grayscale = new TimeFrontShowGrayscale(plugin, x+ 100, y));
181 void TimeFrontWindow::update_shape()
183 int x = shape_x, y = shape_y;
185 if(plugin->config.shape == TimeFrontConfig::LINEAR)
187 delete center_x_title;
188 delete center_y_title;
191 delete track_usage_title;
197 track_usage_title = 0;
201 add_subwindow(angle_title = new BC_Title(x, y, _("Angle:")));
202 add_subwindow(angle = new TimeFrontAngle(plugin, x + angle_title->get_w() + 10, y));
207 add_subwindow(rate_title = new BC_Title(x, y, _("Rate:")));
208 add_subwindow(rate = new TimeFrontRate(plugin,
209 x + rate_title->get_w() + 10,
211 rate->create_objects();
213 add_subwindow(in_radius_title = new BC_Title(x, y, _("Inner radius:")));
214 add_subwindow(in_radius = new TimeFrontInRadius(plugin, x + in_radius_title->get_w() + 10, y));
216 add_subwindow(out_radius_title = new BC_Title(x, y, _("Outer radius:")));
217 add_subwindow(out_radius = new TimeFrontOutRadius(plugin, x + out_radius_title->get_w() + 10, y));
222 if(plugin->config.shape == TimeFrontConfig::RADIAL)
226 delete track_usage_title;
230 track_usage_title = 0;
234 add_subwindow(center_x_title = new BC_Title(x, y, _("Center X:")));
235 add_subwindow(center_x = new TimeFrontCenterX(plugin,
236 x + center_x_title->get_w() + 10,
238 x += center_x_title->get_w() + 10 + center_x->get_w() + 10;
239 add_subwindow(center_y_title = new BC_Title(x, y, _("Center Y:")));
240 add_subwindow(center_y = new TimeFrontCenterY(plugin,
241 x + center_y_title->get_w() + 10,
250 add_subwindow(rate_title = new BC_Title(x, y, _("Rate:")));
251 add_subwindow(rate = new TimeFrontRate(plugin,
252 x + rate_title->get_w() + 10,
254 rate->create_objects();
256 add_subwindow(in_radius_title = new BC_Title(x, y, _("Inner radius:")));
257 add_subwindow(in_radius = new TimeFrontInRadius(plugin, x + in_radius_title->get_w() + 10, y));
259 add_subwindow(out_radius_title = new BC_Title(x, y, _("Outer radius:")));
260 add_subwindow(out_radius = new TimeFrontOutRadius(plugin, x + out_radius_title->get_w() + 10, y));
264 if(plugin->config.shape == TimeFrontConfig::OTHERTRACK)
266 delete center_x_title;
267 delete center_y_title;
274 delete in_radius_title;
276 delete out_radius_title;
288 out_radius_title = 0;
292 add_subwindow(track_usage_title = new BC_Title(x, y, _("As timefront use:")));
293 add_subwindow(track_usage = new TimeFrontTrackUsage(plugin,
295 x + track_usage_title->get_w() + 10,
297 track_usage->create_objects();
301 if(plugin->config.shape == TimeFrontConfig::ALPHA)
303 delete center_x_title;
304 delete center_y_title;
311 delete in_radius_title;
313 delete out_radius_title;
315 delete track_usage_title;
327 out_radius_title = 0;
329 track_usage_title = 0;
348 TimeFrontShape::TimeFrontShape(TimeFrontMain *plugin,
349 TimeFrontWindow *gui,
352 : BC_PopupMenu(x, y, 230, to_text(plugin->config.shape), 1)
354 this->plugin = plugin;
357 void TimeFrontShape::create_objects()
359 add_item(new BC_MenuItem(to_text(TimeFrontConfig::LINEAR)));
360 add_item(new BC_MenuItem(to_text(TimeFrontConfig::RADIAL)));
361 add_item(new BC_MenuItem(to_text(TimeFrontConfig::ALPHA)));
362 add_item(new BC_MenuItem(to_text(TimeFrontConfig::OTHERTRACK)));
364 char* TimeFrontShape::to_text(int shape)
368 case TimeFrontConfig::LINEAR:
370 case TimeFrontConfig::OTHERTRACK:
371 return _("Other track as timefront");
372 case TimeFrontConfig::ALPHA:
373 return _("Alpha as timefront");
378 int TimeFrontShape::from_text(char *text)
380 if(!strcmp(text, to_text(TimeFrontConfig::LINEAR)))
381 return TimeFrontConfig::LINEAR;
382 if(!strcmp(text, to_text(TimeFrontConfig::OTHERTRACK)))
383 return TimeFrontConfig::OTHERTRACK;
384 if(!strcmp(text, to_text(TimeFrontConfig::ALPHA)))
385 return TimeFrontConfig::ALPHA;
386 return TimeFrontConfig::RADIAL;
388 int TimeFrontShape::handle_event()
390 plugin->config.shape = from_text(get_text());
393 plugin->send_configure_change();
398 TimeFrontTrackUsage::TimeFrontTrackUsage(TimeFrontMain *plugin,
399 TimeFrontWindow *gui, int x, int y)
400 : BC_PopupMenu(x, y, 140, to_text(plugin->config.track_usage), 1)
402 this->plugin = plugin;
405 void TimeFrontTrackUsage::create_objects()
407 add_item(new BC_MenuItem(to_text(TimeFrontConfig::OTHERTRACK_INTENSITY)));
408 add_item(new BC_MenuItem(to_text(TimeFrontConfig::OTHERTRACK_ALPHA)));
410 char* TimeFrontTrackUsage::to_text(int track_usage)
414 case TimeFrontConfig::OTHERTRACK_INTENSITY:
415 return _("Intensity");
416 case TimeFrontConfig::OTHERTRACK_ALPHA:
417 return _("Alpha mask");
422 int TimeFrontTrackUsage::from_text(char *text)
424 if(!strcmp(text, to_text(TimeFrontConfig::OTHERTRACK_INTENSITY)))
425 return TimeFrontConfig::OTHERTRACK_INTENSITY;
426 if(!strcmp(text, to_text(TimeFrontConfig::OTHERTRACK_ALPHA)))
427 return TimeFrontConfig::OTHERTRACK_ALPHA;
429 return TimeFrontConfig::OTHERTRACK_INTENSITY;
431 int TimeFrontTrackUsage::handle_event()
433 plugin->config.track_usage = from_text(get_text());
436 plugin->send_configure_change();
443 TimeFrontCenterX::TimeFrontCenterX(TimeFrontMain *plugin, int x, int y)
444 : BC_FPot(x, y, plugin->config.center_x, 0, 100)
446 this->plugin = plugin;
448 int TimeFrontCenterX::handle_event()
450 plugin->config.center_x = get_value();
451 plugin->send_configure_change();
457 TimeFrontCenterY::TimeFrontCenterY(TimeFrontMain *plugin, int x, int y)
458 : BC_FPot(x, y, plugin->config.center_y, 0, 100)
460 this->plugin = plugin;
463 int TimeFrontCenterY::handle_event()
465 plugin->config.center_y = get_value();
466 plugin->send_configure_change();
473 TimeFrontAngle::TimeFrontAngle(TimeFrontMain *plugin, int x, int y)
476 plugin->config.angle,
480 this->plugin = plugin;
483 int TimeFrontAngle::handle_event()
485 plugin->config.angle = get_value();
486 plugin->send_configure_change();
491 TimeFrontRate::TimeFrontRate(TimeFrontMain *plugin, int x, int y)
495 to_text(plugin->config.rate),
498 this->plugin = plugin;
500 void TimeFrontRate::create_objects()
502 add_item(new BC_MenuItem(to_text(TimeFrontConfig::LINEAR)));
503 add_item(new BC_MenuItem(to_text(TimeFrontConfig::LOG)));
504 add_item(new BC_MenuItem(to_text(TimeFrontConfig::SQUARE)));
506 char* TimeFrontRate::to_text(int shape)
510 case TimeFrontConfig::LINEAR:
512 case TimeFrontConfig::LOG:
518 int TimeFrontRate::from_text(char *text)
520 if(!strcmp(text, to_text(TimeFrontConfig::LINEAR)))
521 return TimeFrontConfig::LINEAR;
522 if(!strcmp(text, to_text(TimeFrontConfig::LOG)))
523 return TimeFrontConfig::LOG;
524 return TimeFrontConfig::SQUARE;
526 int TimeFrontRate::handle_event()
528 plugin->config.rate = from_text(get_text());
529 plugin->send_configure_change();
535 TimeFrontInRadius::TimeFrontInRadius(TimeFrontMain *plugin, int x, int y)
543 (float)plugin->config.in_radius)
545 this->plugin = plugin;
548 int TimeFrontInRadius::handle_event()
550 plugin->config.in_radius = get_value();
551 plugin->send_configure_change();
556 TimeFrontOutRadius::TimeFrontOutRadius(TimeFrontMain *plugin, int x, int y)
564 (float)plugin->config.out_radius)
566 this->plugin = plugin;
569 int TimeFrontOutRadius::handle_event()
571 plugin->config.out_radius = get_value();
572 plugin->send_configure_change();
576 TimeFrontFrameRange::TimeFrontFrameRange(TimeFrontMain *plugin, int x, int y)
584 (int)plugin->config.frame_range)
586 this->plugin = plugin;
589 int TimeFrontFrameRange::handle_event()
591 plugin->config.frame_range = get_value();
592 plugin->send_configure_change();
597 TimeFrontInvert::TimeFrontInvert(TimeFrontMain *client, int x, int y)
600 client->config.invert,
603 this->plugin = client;
606 int TimeFrontInvert::handle_event()
608 plugin->config.invert = get_value();
609 plugin->send_configure_change();
613 TimeFrontShowGrayscale::TimeFrontShowGrayscale(TimeFrontMain *client, int x, int y)
616 client->config.show_grayscale,
617 _("Show grayscale (for tuning"))
619 this->plugin = client;
622 int TimeFrontShowGrayscale::handle_event()
624 plugin->config.show_grayscale = get_value();
625 plugin->send_configure_change();
631 TimeFrontMain::TimeFrontMain(PluginServer *server)
632 : PluginVClient(server)
635 need_reconfigure = 1;
641 TimeFrontMain::~TimeFrontMain()
645 if(gradient) delete gradient;
646 if(engine) delete engine;
647 if(overlayer) delete overlayer;
650 const char* TimeFrontMain::plugin_title() { return N_("TimeFront"); }
651 int TimeFrontMain::is_realtime() { return 1; }
652 int TimeFrontMain::is_multichannel() { return 1; }
656 NEW_WINDOW_MACRO(TimeFrontMain, TimeFrontWindow)
658 LOAD_CONFIGURATION_MACRO(TimeFrontMain, TimeFrontConfig)
660 int TimeFrontMain::is_synthesis()
665 #define GRADIENTFROMAVG(type, inttype, components, maxval) \
666 for(int i = 0; i < tfframe->get_h(); i++) \
668 type *in_row = (type *)tfframe->get_rows()[i]; \
669 unsigned char *grad_row = gradient->get_rows()[i]; \
670 for(int j = 0; j < tfframe->get_w(); j++) \
672 inttype tmp = (inttype) in_row[j * components] + \
673 in_row[j * components + 1] + \
674 in_row[j * components + 2]; \
675 if (components == 3) \
676 grad_row[j] = (unsigned char) (CLIP((float)config.frame_range * tmp / maxval / 3, 0.0F, config.frame_range)); \
677 else if(components == 4) \
678 grad_row[j] = (unsigned char) (CLIP((float)config.frame_range * tmp * in_row[j * components + 3] / maxval / maxval / 3, 0.0F, config.frame_range)); \
682 #define GRADIENTFROMCHANNEL(type, components, max, channel) \
683 for(int i = 0; i < tfframe->get_h(); i++) \
685 type *in_row = (type *)tfframe->get_rows()[i]; \
686 unsigned char *grad_row = gradient->get_rows()[i]; \
687 for(int j = 0; j < tfframe->get_w(); j++) \
689 if (components == 3) \
690 grad_row[j] = (unsigned char) (CLIP((float)config.frame_range * in_row[j * components + channel] / max, 0.0F, config.frame_range)); \
691 else if(components == 4) \
692 grad_row[j] = (unsigned char) (CLIP((float)config.frame_range * in_row[j * components + channel] * in_row[j * components + 3]/ max /max, 0.0F, config.frame_range)); \
696 #define SETALPHA(type, max) \
697 for(int i = 0; i < outframes[0]->get_h(); i++) \
699 type *out_row = (type *)outframes[0]->get_rows()[i]; \
700 for(int j = 0; j < outframes[0]->get_w(); j++) \
702 out_row[j * 4 + 3] = max; \
706 #define GRADIENTTOPICTURE(type, inttype, components, max, invertion) \
707 for(int i = 0; i < height; i++) \
709 type *out_row = (type *)outframes[0]->get_rows()[i]; \
710 unsigned char *grad_row = gradient->get_rows()[i]; \
711 for (int j = 0; j < width; j++) \
713 out_row[0] = (inttype)max * (invertion grad_row[0]) / config.frame_range; \
714 out_row[1] = (inttype)max * (invertion grad_row[0]) / config.frame_range; \
715 out_row[2] = (inttype)max * (invertion grad_row[0]) / config.frame_range; \
716 if (components == 4) \
718 out_row += components; \
723 #define GRADIENTTOYUVPICTURE(type, inttype, components, max, invertion) \
724 for(int i = 0; i < height; i++) \
726 type *out_row = (type *)outframes[0]->get_rows()[i]; \
727 unsigned char *grad_row = gradient->get_rows()[i]; \
728 for (int j = 0; j < width; j++) \
730 out_row[0] = (inttype)max * (invertion grad_row[0]) / config.frame_range; \
731 out_row[1] = max/2; \
732 out_row[2] = max/2; \
733 if (components == 4) \
735 out_row += components; \
740 #define COMPOSITEIMAGE(type, components, invertion) \
741 for (int i = 0; i < height; i++) \
743 type *out_row = (type *)outframes[0]->get_rows()[i]; \
744 unsigned char *gradient_row = gradient->get_rows()[i]; \
745 for (int j = 0; j < width; j++) \
747 unsigned int choice = invertion gradient_row[j]; \
749 type *in_row = (type *)framelist[choice]->get_rows()[i]; \
750 out_row[0] = in_row[j * components + 0]; \
751 out_row[1] = in_row[j * components + 1]; \
752 out_row[2] = in_row[j * components + 2]; \
753 if (components == 4) \
754 out_row[3] = in_row[j * components + 3]; \
756 out_row += components; \
762 int TimeFrontMain::process_buffer(VFrame **frame,
763 int64_t start_position,
765 //int TimeFrontMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
767 VFrame **outframes = frame;
768 VFrame *(framelist[1024]);
769 framelist[0] = new VFrame (outframes[0]->get_w(), outframes[0]->get_h(),
770 outframes[0]->get_color_model(), 0);
771 read_frame(framelist[0],
776 this->input = framelist[0];
777 this->output = outframes[0];
778 need_reconfigure |= load_configuration();
779 if (config.shape == TimeFrontConfig::OTHERTRACK)
781 // this->output = frame[1];
782 if (get_total_buffers() != 2)
784 // FIXME, maybe this should go to some other notification area?
785 printf(_("ERROR: TimeFront plugin - If you are using another track for timefront, you have to have it under shared effects\n"));
788 if (outframes[0]->get_w() != outframes[1]->get_w() || outframes[0]->get_h() != outframes[1]->get_h())
790 printf(_("Sizes of master track and timefront track do not match\n"));
795 // Generate new gradient
798 need_reconfigure = 0;
801 gradient = new VFrame( outframes[0]->get_w(), outframes[0]->get_h(), BC_A8, 0);
803 if (config.shape != TimeFrontConfig::OTHERTRACK &&
804 config.shape != TimeFrontConfig::ALPHA)
806 if(!engine) engine = new TimeFrontServer(this,
807 get_project_smp() + 1,
808 get_project_smp() + 1);
809 engine->process_packages();
813 if (config.shape == TimeFrontConfig::ALPHA)
816 gradient = new VFrame(outframes[0]->get_w(), outframes[0]->get_h(), BC_A8, 0);
817 VFrame *tfframe = framelist[0];
818 switch (tfframe->get_color_model())
822 GRADIENTFROMCHANNEL(unsigned char, 4, 255, 3);
827 GRADIENTFROMCHANNEL(float, 4, 1.0f, 3);
832 printf(_("TimeFront plugin error: ALPHA used, but project color model does not have alpha\n"));
839 if (config.shape == TimeFrontConfig::OTHERTRACK)
842 gradient = new VFrame(outframes[0]->get_w(), outframes[0]->get_h(), BC_A8, 0);
843 VFrame *tfframe = outframes[1];
849 if (config.track_usage == TimeFrontConfig::OTHERTRACK_INTENSITY)
851 switch (tfframe->get_color_model())
854 GRADIENTFROMAVG(unsigned char, unsigned short, 4, 255); // Has to be 2 ranges bigger, sice we need precision for alpha
857 GRADIENTFROMAVG(unsigned char, unsigned short, 3, 255);
860 GRADIENTFROMAVG(float, float, 3, 1.0f);
863 GRADIENTFROMAVG(float, float, 4, 1.0f);
865 case BC_YUV888: // We cheat and take Y component as intensity
866 GRADIENTFROMCHANNEL(unsigned char, 3, 255, 0);
869 GRADIENTFROMCHANNEL(unsigned char, 4, 255, 0);
875 if (config.track_usage == TimeFrontConfig::OTHERTRACK_ALPHA)
877 switch (tfframe->get_color_model())
881 GRADIENTFROMCHANNEL(unsigned char, 4, 255, 3);
886 GRADIENTFROMCHANNEL(float, 4, 1.0f, 3);
891 printf(_("TimeFront plugin error: ALPHA track used, but project color model does not have alpha\n"));
898 printf(_("TimeFront plugin error: unsupported track_usage parameter\n"));
903 if (!config.show_grayscale)
905 for (int i = 1; i <= config.frame_range; i++)
907 framelist[i] = new VFrame (outframes[0]->get_w(), outframes[0]->get_h(),
908 outframes[0]->get_color_model(), 0);
910 read_frame(framelist[i],
919 int width = outframes[0]->get_w();
920 int height = outframes[0]->get_h();
921 if (config.show_grayscale)
925 switch (outframes[0]->get_color_model())
928 GRADIENTTOPICTURE(unsigned char, unsigned short, 3, 255, );
931 GRADIENTTOPICTURE(unsigned char, unsigned short, 4, 255, );
934 GRADIENTTOYUVPICTURE(unsigned char, unsigned short, 3, 255, );
937 GRADIENTTOYUVPICTURE(unsigned char, unsigned short, 4, 255, );
940 GRADIENTTOPICTURE(float, float, 3, 1.0f, );
943 GRADIENTTOPICTURE(float, float, 4, 1.0f, );
950 switch (outframes[0]->get_color_model())
953 GRADIENTTOPICTURE(unsigned char, unsigned short, 3, 255, config.frame_range -);
956 GRADIENTTOPICTURE(unsigned char, unsigned short, 4, 255, config.frame_range -);
959 GRADIENTTOYUVPICTURE(unsigned char, unsigned short, 3, 255, config.frame_range -);
962 GRADIENTTOYUVPICTURE(unsigned char, unsigned short, 4, 255, config.frame_range -);
965 GRADIENTTOPICTURE(float, float, 3, 1.0f, config.frame_range -);
968 GRADIENTTOPICTURE(float, float, 4, 1.0f, config.frame_range -);
977 switch (outframes[0]->get_color_model())
980 COMPOSITEIMAGE(unsigned char, 3, );
983 COMPOSITEIMAGE(unsigned char, 4, );
986 COMPOSITEIMAGE(unsigned char, 3, );
989 COMPOSITEIMAGE(unsigned char, 4, );
992 COMPOSITEIMAGE(float, 3, );
995 COMPOSITEIMAGE(float, 4, );
1003 switch (outframes[0]->get_color_model())
1006 COMPOSITEIMAGE(unsigned char, 3, config.frame_range -);
1009 COMPOSITEIMAGE(unsigned char, 4, config.frame_range -);
1012 COMPOSITEIMAGE(unsigned char, 3, config.frame_range -);
1015 COMPOSITEIMAGE(unsigned char, 4, config.frame_range -);
1018 COMPOSITEIMAGE(float, 3, config.frame_range -);
1021 COMPOSITEIMAGE(float, 4, config.frame_range -);
1028 if (config.shape == TimeFrontConfig::ALPHA)
1031 switch (outframes[0]->get_color_model())
1035 SETALPHA(unsigned char, 255);
1038 SETALPHA(float, 1.0f);
1046 delete framelist[0];
1047 if (!config.show_grayscale)
1049 for (int i = 1; i <= config.frame_range; i++)
1050 delete framelist[i];
1056 void TimeFrontMain::update_gui()
1060 if(load_configuration())
1062 thread->window->lock_window("TimeFrontMain::update_gui");
1063 ((TimeFrontWindow*)thread->window)->frame_range->update(config.frame_range);
1064 ((TimeFrontWindow*)thread->window)->shape->set_text(TimeFrontShape::to_text(config.shape));
1065 ((TimeFrontWindow*)thread->window)->show_grayscale->update(config.show_grayscale);
1066 ((TimeFrontWindow*)thread->window)->invert->update(config.invert);
1067 ((TimeFrontWindow*)thread->window)->shape->set_text(TimeFrontShape::to_text(config.shape));
1068 if (((TimeFrontWindow*)thread->window)->rate)
1069 ((TimeFrontWindow*)thread->window)->rate->set_text(TimeFrontRate::to_text(config.rate));
1070 if (((TimeFrontWindow*)thread->window)->in_radius)
1071 ((TimeFrontWindow*)thread->window)->in_radius->update(config.in_radius);
1072 if (((TimeFrontWindow*)thread->window)->out_radius)
1073 ((TimeFrontWindow*)thread->window)->out_radius->update(config.out_radius);
1074 if (((TimeFrontWindow*)thread->window)->track_usage)
1075 ((TimeFrontWindow*)thread->window)->track_usage->set_text(TimeFrontTrackUsage::to_text(config.track_usage));
1076 if(((TimeFrontWindow*)thread->window)->angle)
1077 ((TimeFrontWindow*)thread->window)->angle->update(config.angle);
1078 if(((TimeFrontWindow*)thread->window)->center_x)
1079 ((TimeFrontWindow*)thread->window)->center_x->update(config.center_x);
1080 if(((TimeFrontWindow*)thread->window)->center_y)
1081 ((TimeFrontWindow*)thread->window)->center_y->update(config.center_y);
1083 ((TimeFrontWindow*)thread->window)->update_shape();
1084 thread->window->unlock_window();
1092 void TimeFrontMain::save_data(KeyFrame *keyframe)
1096 // cause data to be stored directly in text
1097 output.set_shared_output(keyframe->xbuf);
1098 output.tag.set_title("TIMEFRONT");
1100 output.tag.set_property("ANGLE", config.angle);
1101 output.tag.set_property("IN_RADIUS", config.in_radius);
1102 output.tag.set_property("OUT_RADIUS", config.out_radius);
1103 output.tag.set_property("FRAME_RANGE", config.frame_range);
1104 output.tag.set_property("SHAPE", config.shape);
1105 output.tag.set_property("TRACK_USAGE", config.track_usage);
1106 output.tag.set_property("RATE", config.rate);
1107 output.tag.set_property("CENTER_X", config.center_x);
1108 output.tag.set_property("CENTER_Y", config.center_y);
1109 output.tag.set_property("INVERT", config.invert);
1110 output.tag.set_property("SHOW_GRAYSCALE", config.show_grayscale);
1111 output.append_tag();
1112 output.tag.set_title("/TIMEFRONT");
1113 output.append_tag();
1114 output.append_newline();
1115 output.terminate_string();
1118 void TimeFrontMain::read_data(KeyFrame *keyframe)
1122 input.set_shared_input(keyframe->xbuf);
1128 result = input.read_tag();
1132 if(input.tag.title_is("TIMEFRONT"))
1134 config.angle = input.tag.get_property("ANGLE", config.angle);
1135 config.rate = input.tag.get_property("RATE", config.rate);
1136 config.in_radius = input.tag.get_property("IN_RADIUS", config.in_radius);
1137 config.out_radius = input.tag.get_property("OUT_RADIUS", config.out_radius);
1138 config.frame_range = input.tag.get_property("FRAME_RANGE", config.frame_range);
1139 config.shape = input.tag.get_property("SHAPE", config.shape);
1140 config.track_usage = input.tag.get_property("TRACK_USAGE", config.track_usage);
1141 config.center_x = input.tag.get_property("CENTER_X", config.center_x);
1142 config.center_y = input.tag.get_property("CENTER_Y", config.center_y);
1143 config.invert = input.tag.get_property("INVERT", config.invert);
1144 config.show_grayscale = input.tag.get_property("SHOW_GRAYSCALE", config.show_grayscale);
1155 TimeFrontPackage::TimeFrontPackage()
1163 TimeFrontUnit::TimeFrontUnit(TimeFrontServer *server, TimeFrontMain *plugin)
1164 : LoadClient(server)
1166 this->plugin = plugin;
1167 this->server = server;
1173 #define CREATE_GRADIENT \
1175 /* Synthesize linear gradient for lookups */ \
1177 a_table = (unsigned char *)malloc(sizeof(unsigned char) * gradient_size); \
1179 for(int i = 0; i < gradient_size; i++) \
1181 float opacity = 0.0; \
1182 switch(plugin->config.rate) \
1184 case TimeFrontConfig::LINEAR: \
1188 if(i >= out_radius) \
1191 opacity = (float)(i - in_radius) / (out_radius - in_radius); \
1193 case TimeFrontConfig::LOG: \
1194 opacity = 1 - exp(LOG_RANGE * -(float)(i - in_radius) / (out_radius - in_radius)); \
1196 case TimeFrontConfig::SQUARE: \
1197 opacity = SQR((float)(i - in_radius) / (out_radius - in_radius)); \
1201 CLAMP(opacity, 0, 1); \
1202 float transparency = 1.0 - opacity; \
1203 a_table[i] = (unsigned char)(out4 * opacity + in4 * transparency); \
1206 for(int i = pkg->y1; i < pkg->y2; i++) \
1208 unsigned char *out_row = plugin->gradient->get_rows()[i]; \
1210 switch(plugin->config.shape) \
1212 case TimeFrontConfig::LINEAR: \
1213 for(int j = 0; j < w; j++) \
1215 int x = j - half_w; \
1216 int y = -(i - half_h); \
1218 /* Rotate by effect angle */ \
1219 int input_y = (int)(gradient_size / 2 - \
1220 (x * sin_angle + y * cos_angle) + \
1223 /* Get gradient value from these coords */ \
1227 out_row[0] = out4; \
1230 if(input_y >= gradient_size) \
1236 out_row[0] = a_table[input_y]; \
1243 case TimeFrontConfig::RADIAL: \
1244 for(int j = 0; j < w; j++) \
1246 double x = j - center_x; \
1247 double y = i - center_y; \
1248 double magnitude = hypot(x, y); \
1249 int input_y = (int)magnitude; \
1250 out_row[0] = a_table[input_y]; \
1258 void TimeFrontUnit::process_package(LoadPackage *package)
1260 TimeFrontPackage *pkg = (TimeFrontPackage*)package;
1261 int h = plugin->input->get_h();
1262 int w = plugin->input->get_w();
1265 int gradient_size = (int)(ceil(hypot(w, h)));
1266 int in_radius = (int)(plugin->config.in_radius / 100 * gradient_size);
1267 int out_radius = (int)(plugin->config.out_radius / 100 * gradient_size);
1268 double sin_angle = sin(plugin->config.angle * (M_PI / 180));
1269 double cos_angle = cos(plugin->config.angle * (M_PI / 180));
1270 double center_x = plugin->config.center_x * w / 100;
1271 double center_y = plugin->config.center_y * h / 100;
1272 unsigned char *a_table = 0;
1274 if(in_radius > out_radius)
1276 in_radius ^= out_radius;
1277 out_radius ^= in_radius;
1278 in_radius ^= out_radius;
1282 int in4 = plugin->config.frame_range;
1286 if(a_table) free(a_table);
1294 TimeFrontServer::TimeFrontServer(TimeFrontMain *plugin,
1297 : LoadServer(total_clients, total_packages)
1299 this->plugin = plugin;
1302 void TimeFrontServer::init_packages()
1304 for(int i = 0; i < get_total_packages(); i++)
1306 TimeFrontPackage *package = (TimeFrontPackage*)get_package(i);
1307 package->y1 = plugin->input->get_h() *
1309 get_total_packages();
1310 package->y2 = plugin->input->get_h() *
1312 get_total_packages();
1316 LoadClient* TimeFrontServer::new_client()
1318 return new TimeFrontUnit(this, plugin);
1321 LoadPackage* TimeFrontServer::new_package()
1323 return new TimeFrontPackage;