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, 190, 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());
392 plugin->send_configure_change();
397 TimeFrontTrackUsage::TimeFrontTrackUsage(TimeFrontMain *plugin,
398 TimeFrontWindow *gui, int x, int y)
399 : BC_PopupMenu(x, y, 140, to_text(plugin->config.track_usage), 1)
401 this->plugin = plugin;
404 void TimeFrontTrackUsage::create_objects()
406 add_item(new BC_MenuItem(to_text(TimeFrontConfig::OTHERTRACK_INTENSITY)));
407 add_item(new BC_MenuItem(to_text(TimeFrontConfig::OTHERTRACK_ALPHA)));
409 char* TimeFrontTrackUsage::to_text(int track_usage)
413 case TimeFrontConfig::OTHERTRACK_INTENSITY:
414 return _("Intensity");
415 case TimeFrontConfig::OTHERTRACK_ALPHA:
416 return _("Alpha mask");
421 int TimeFrontTrackUsage::from_text(char *text)
423 if(!strcmp(text, to_text(TimeFrontConfig::OTHERTRACK_INTENSITY)))
424 return TimeFrontConfig::OTHERTRACK_INTENSITY;
425 if(!strcmp(text, to_text(TimeFrontConfig::OTHERTRACK_ALPHA)))
426 return TimeFrontConfig::OTHERTRACK_ALPHA;
428 return TimeFrontConfig::OTHERTRACK_INTENSITY;
430 int TimeFrontTrackUsage::handle_event()
432 plugin->config.track_usage = from_text(get_text());
434 plugin->send_configure_change();
441 TimeFrontCenterX::TimeFrontCenterX(TimeFrontMain *plugin, int x, int y)
442 : BC_FPot(x, y, plugin->config.center_x, 0, 100)
444 this->plugin = plugin;
446 int TimeFrontCenterX::handle_event()
448 plugin->config.center_x = get_value();
449 plugin->send_configure_change();
455 TimeFrontCenterY::TimeFrontCenterY(TimeFrontMain *plugin, int x, int y)
456 : BC_FPot(x, y, plugin->config.center_y, 0, 100)
458 this->plugin = plugin;
461 int TimeFrontCenterY::handle_event()
463 plugin->config.center_y = get_value();
464 plugin->send_configure_change();
471 TimeFrontAngle::TimeFrontAngle(TimeFrontMain *plugin, int x, int y)
474 plugin->config.angle,
478 this->plugin = plugin;
481 int TimeFrontAngle::handle_event()
483 plugin->config.angle = get_value();
484 plugin->send_configure_change();
489 TimeFrontRate::TimeFrontRate(TimeFrontMain *plugin, int x, int y)
493 to_text(plugin->config.rate),
496 this->plugin = plugin;
498 void TimeFrontRate::create_objects()
500 add_item(new BC_MenuItem(to_text(TimeFrontConfig::LINEAR)));
501 add_item(new BC_MenuItem(to_text(TimeFrontConfig::LOG)));
502 add_item(new BC_MenuItem(to_text(TimeFrontConfig::SQUARE)));
504 char* TimeFrontRate::to_text(int shape)
508 case TimeFrontConfig::LINEAR:
510 case TimeFrontConfig::LOG:
516 int TimeFrontRate::from_text(char *text)
518 if(!strcmp(text, to_text(TimeFrontConfig::LINEAR)))
519 return TimeFrontConfig::LINEAR;
520 if(!strcmp(text, to_text(TimeFrontConfig::LOG)))
521 return TimeFrontConfig::LOG;
522 return TimeFrontConfig::SQUARE;
524 int TimeFrontRate::handle_event()
526 plugin->config.rate = from_text(get_text());
527 plugin->send_configure_change();
533 TimeFrontInRadius::TimeFrontInRadius(TimeFrontMain *plugin, int x, int y)
541 (float)plugin->config.in_radius)
543 this->plugin = plugin;
546 int TimeFrontInRadius::handle_event()
548 plugin->config.in_radius = get_value();
549 plugin->send_configure_change();
554 TimeFrontOutRadius::TimeFrontOutRadius(TimeFrontMain *plugin, int x, int y)
562 (float)plugin->config.out_radius)
564 this->plugin = plugin;
567 int TimeFrontOutRadius::handle_event()
569 plugin->config.out_radius = get_value();
570 plugin->send_configure_change();
574 TimeFrontFrameRange::TimeFrontFrameRange(TimeFrontMain *plugin, int x, int y)
582 (int)plugin->config.frame_range)
584 this->plugin = plugin;
587 int TimeFrontFrameRange::handle_event()
589 plugin->config.frame_range = get_value();
590 plugin->send_configure_change();
595 TimeFrontInvert::TimeFrontInvert(TimeFrontMain *client, int x, int y)
598 client->config.invert,
601 this->plugin = client;
604 int TimeFrontInvert::handle_event()
606 plugin->config.invert = get_value();
607 plugin->send_configure_change();
611 TimeFrontShowGrayscale::TimeFrontShowGrayscale(TimeFrontMain *client, int x, int y)
614 client->config.show_grayscale,
615 _("Show grayscale (for tuning"))
617 this->plugin = client;
620 int TimeFrontShowGrayscale::handle_event()
622 plugin->config.show_grayscale = get_value();
623 plugin->send_configure_change();
629 TimeFrontMain::TimeFrontMain(PluginServer *server)
630 : PluginVClient(server)
633 need_reconfigure = 1;
639 TimeFrontMain::~TimeFrontMain()
643 if(gradient) delete gradient;
644 if(engine) delete engine;
645 if(overlayer) delete overlayer;
648 const char* TimeFrontMain::plugin_title() { return _("TimeFront"); }
649 int TimeFrontMain::is_realtime() { return 1; }
650 int TimeFrontMain::is_multichannel() { return 1; }
654 NEW_WINDOW_MACRO(TimeFrontMain, TimeFrontWindow)
656 LOAD_CONFIGURATION_MACRO(TimeFrontMain, TimeFrontConfig)
658 int TimeFrontMain::is_synthesis()
663 #define GRADIENTFROMAVG(type, inttype, components, maxval) \
664 for(int i = 0; i < tfframe->get_h(); i++) \
666 type *in_row = (type *)tfframe->get_rows()[i]; \
667 unsigned char *grad_row = gradient->get_rows()[i]; \
668 for(int j = 0; j < tfframe->get_w(); j++) \
670 inttype tmp = (inttype) in_row[j * components] + \
671 in_row[j * components + 1] + \
672 in_row[j * components + 2]; \
673 if (components == 3) \
674 grad_row[j] = (unsigned char) (CLIP((float)config.frame_range * tmp / maxval / 3, 0.0F, config.frame_range)); \
675 else if(components == 4) \
676 grad_row[j] = (unsigned char) (CLIP((float)config.frame_range * tmp * in_row[j * components + 3] / maxval / maxval / 3, 0.0F, config.frame_range)); \
680 #define GRADIENTFROMCHANNEL(type, components, max, channel) \
681 for(int i = 0; i < tfframe->get_h(); i++) \
683 type *in_row = (type *)tfframe->get_rows()[i]; \
684 unsigned char *grad_row = gradient->get_rows()[i]; \
685 for(int j = 0; j < tfframe->get_w(); j++) \
687 if (components == 3) \
688 grad_row[j] = (unsigned char) (CLIP((float)config.frame_range * in_row[j * components + channel] / max, 0.0F, config.frame_range)); \
689 else if(components == 4) \
690 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)); \
694 #define SETALPHA(type, max) \
695 for(int i = 0; i < outframes[0]->get_h(); i++) \
697 type *out_row = (type *)outframes[0]->get_rows()[i]; \
698 for(int j = 0; j < outframes[0]->get_w(); j++) \
700 out_row[j * 4 + 3] = max; \
704 #define GRADIENTTOPICTURE(type, inttype, components, max, invertion) \
705 for(int i = 0; i < height; i++) \
707 type *out_row = (type *)outframes[0]->get_rows()[i]; \
708 unsigned char *grad_row = gradient->get_rows()[i]; \
709 for (int j = 0; j < width; j++) \
711 out_row[0] = (inttype)max * (invertion grad_row[0]) / config.frame_range; \
712 out_row[1] = (inttype)max * (invertion grad_row[0]) / config.frame_range; \
713 out_row[2] = (inttype)max * (invertion grad_row[0]) / config.frame_range; \
714 if (components == 4) \
716 out_row += components; \
721 #define GRADIENTTOYUVPICTURE(type, inttype, components, max, invertion) \
722 for(int i = 0; i < height; i++) \
724 type *out_row = (type *)outframes[0]->get_rows()[i]; \
725 unsigned char *grad_row = gradient->get_rows()[i]; \
726 for (int j = 0; j < width; j++) \
728 out_row[0] = (inttype)max * (invertion grad_row[0]) / config.frame_range; \
729 out_row[1] = max/2; \
730 out_row[2] = max/2; \
731 if (components == 4) \
733 out_row += components; \
738 #define COMPOSITEIMAGE(type, components, invertion) \
739 for (int i = 0; i < height; i++) \
741 type *out_row = (type *)outframes[0]->get_rows()[i]; \
742 unsigned char *gradient_row = gradient->get_rows()[i]; \
743 for (int j = 0; j < width; j++) \
745 unsigned int choice = invertion gradient_row[j]; \
747 out_row[0] = framelist[choice]->get_rows()[i][j * components + 0]; \
748 out_row[1] = framelist[choice]->get_rows()[i][j * components + 1]; \
749 out_row[2] = framelist[choice]->get_rows()[i][j * components + 2]; \
750 if (components == 4) \
751 out_row[3] = framelist[choice]->get_rows()[i][j * components + 3]; \
753 out_row += components; \
759 int TimeFrontMain::process_buffer(VFrame **frame,
760 int64_t start_position,
762 //int TimeFrontMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
764 VFrame **outframes = frame;
765 VFrame *(framelist[1024]);
766 framelist[0] = new VFrame (
767 outframes[0]->get_w(),
768 outframes[0]->get_h(),
769 outframes[0]->get_color_model());
770 read_frame(framelist[0],
775 this->input = framelist[0];
776 this->output = outframes[0];
777 need_reconfigure |= load_configuration();
778 if (config.shape == TimeFrontConfig::OTHERTRACK)
780 // this->output = frame[1];
781 if (get_total_buffers() != 2)
783 // FIXME, maybe this should go to some other notification area?
784 printf(_("ERROR: TimeFront plugin - If you are using another track for timefront, you have to have it under shared effects\n"));
787 if (outframes[0]->get_w() != outframes[1]->get_w() || outframes[0]->get_h() != outframes[1]->get_h())
789 printf(_("Sizes of master track and timefront track do not match\n"));
794 // Generate new gradient
797 need_reconfigure = 0;
799 if(!gradient) gradient = new VFrame(
800 outframes[0]->get_w(),
801 outframes[0]->get_h(),
805 if (config.shape != TimeFrontConfig::OTHERTRACK &&
806 config.shape != TimeFrontConfig::ALPHA)
808 if(!engine) engine = new TimeFrontServer(this,
809 get_project_smp() + 1,
810 get_project_smp() + 1);
811 engine->process_packages();
815 if (config.shape == TimeFrontConfig::ALPHA)
817 if(!gradient) gradient = new VFrame(
818 outframes[0]->get_w(),
819 outframes[0]->get_h(),
821 VFrame *tfframe = framelist[0];
822 switch (tfframe->get_color_model())
826 GRADIENTFROMCHANNEL(unsigned char, 4, 255, 3);
831 GRADIENTFROMCHANNEL(float, 4, 1.0f, 3);
836 printf(_("TimeFront plugin error: ALPHA used, but project color model does not have alpha\n"));
843 if (config.shape == TimeFrontConfig::OTHERTRACK)
845 if(!gradient) gradient = new VFrame(
846 outframes[0]->get_w(),
847 outframes[0]->get_h(),
849 VFrame *tfframe = outframes[1];
855 if (config.track_usage == TimeFrontConfig::OTHERTRACK_INTENSITY)
857 switch (tfframe->get_color_model())
860 GRADIENTFROMAVG(unsigned char, unsigned short, 4, 255); // Has to be 2 ranges bigger, sice we need precision for alpha
863 GRADIENTFROMAVG(unsigned char, unsigned short, 3, 255);
866 GRADIENTFROMAVG(float, float, 3, 1.0f);
869 GRADIENTFROMAVG(float, float, 4, 1.0f);
871 case BC_YUV888: // We cheat and take Y component as intensity
872 GRADIENTFROMCHANNEL(unsigned char, 3, 255, 0);
875 GRADIENTFROMCHANNEL(unsigned char, 4, 255, 0);
881 if (config.track_usage == TimeFrontConfig::OTHERTRACK_ALPHA)
883 switch (tfframe->get_color_model())
887 GRADIENTFROMCHANNEL(unsigned char, 4, 255, 3);
892 GRADIENTFROMCHANNEL(float, 4, 1.0f, 3);
897 printf(_("TimeFront plugin error: ALPHA track used, but project color model does not have alpha\n"));
904 printf(_("TimeFront plugin error: unsupported track_usage parameter\n"));
909 if (!config.show_grayscale)
911 for (int i = 1; i <= config.frame_range; i++)
913 framelist[i] = new VFrame (
914 outframes[0]->get_w(),
915 outframes[0]->get_h(),
916 outframes[0]->get_color_model());
918 read_frame(framelist[i],
927 int width = outframes[0]->get_w();
928 int height = outframes[0]->get_h();
929 if (config.show_grayscale)
933 switch (outframes[0]->get_color_model())
936 GRADIENTTOPICTURE(unsigned char, unsigned short, 3, 255, );
939 GRADIENTTOPICTURE(unsigned char, unsigned short, 4, 255, );
942 GRADIENTTOYUVPICTURE(unsigned char, unsigned short, 3, 255, );
945 GRADIENTTOYUVPICTURE(unsigned char, unsigned short, 4, 255, );
948 GRADIENTTOPICTURE(float, float, 3, 1.0f, );
951 GRADIENTTOPICTURE(float, float, 4, 1.0f, );
958 switch (outframes[0]->get_color_model())
961 GRADIENTTOPICTURE(unsigned char, unsigned short, 3, 255, config.frame_range -);
964 GRADIENTTOPICTURE(unsigned char, unsigned short, 4, 255, config.frame_range -);
967 GRADIENTTOYUVPICTURE(unsigned char, unsigned short, 3, 255, config.frame_range -);
970 GRADIENTTOYUVPICTURE(unsigned char, unsigned short, 4, 255, config.frame_range -);
973 GRADIENTTOPICTURE(float, float, 3, 1.0f, config.frame_range -);
976 GRADIENTTOPICTURE(float, float, 4, 1.0f, config.frame_range -);
985 switch (outframes[0]->get_color_model())
988 COMPOSITEIMAGE(unsigned char, 3, );
991 COMPOSITEIMAGE(unsigned char, 4, );
994 COMPOSITEIMAGE(unsigned char, 3, );
997 COMPOSITEIMAGE(unsigned char, 4, );
1000 COMPOSITEIMAGE(float, 3, );
1003 COMPOSITEIMAGE(float, 4, );
1011 switch (outframes[0]->get_color_model())
1014 COMPOSITEIMAGE(unsigned char, 3, config.frame_range -);
1017 COMPOSITEIMAGE(unsigned char, 4, config.frame_range -);
1020 COMPOSITEIMAGE(unsigned char, 3, config.frame_range -);
1023 COMPOSITEIMAGE(unsigned char, 4, config.frame_range -);
1026 COMPOSITEIMAGE(float, 3, config.frame_range -);
1029 COMPOSITEIMAGE(float, 4, config.frame_range -);
1036 if (config.shape == TimeFrontConfig::ALPHA)
1039 switch (outframes[0]->get_color_model())
1043 SETALPHA(unsigned char, 255);
1046 SETALPHA(float, 1.0f);
1054 delete framelist[0];
1055 if (!config.show_grayscale)
1057 for (int i = 1; i <= config.frame_range; i++)
1058 delete framelist[i];
1064 void TimeFrontMain::update_gui()
1068 if(load_configuration())
1070 thread->window->lock_window("TimeFrontMain::update_gui");
1071 ((TimeFrontWindow*)thread->window)->frame_range->update(config.frame_range);
1072 ((TimeFrontWindow*)thread->window)->shape->set_text(TimeFrontShape::to_text(config.shape));
1073 ((TimeFrontWindow*)thread->window)->show_grayscale->update(config.show_grayscale);
1074 ((TimeFrontWindow*)thread->window)->invert->update(config.invert);
1075 ((TimeFrontWindow*)thread->window)->shape->set_text(TimeFrontShape::to_text(config.shape));
1076 if (((TimeFrontWindow*)thread->window)->rate)
1077 ((TimeFrontWindow*)thread->window)->rate->set_text(TimeFrontRate::to_text(config.rate));
1078 if (((TimeFrontWindow*)thread->window)->in_radius)
1079 ((TimeFrontWindow*)thread->window)->in_radius->update(config.in_radius);
1080 if (((TimeFrontWindow*)thread->window)->out_radius)
1081 ((TimeFrontWindow*)thread->window)->out_radius->update(config.out_radius);
1082 if (((TimeFrontWindow*)thread->window)->track_usage)
1083 ((TimeFrontWindow*)thread->window)->track_usage->set_text(TimeFrontTrackUsage::to_text(config.track_usage));
1084 if(((TimeFrontWindow*)thread->window)->angle)
1085 ((TimeFrontWindow*)thread->window)->angle->update(config.angle);
1086 if(((TimeFrontWindow*)thread->window)->center_x)
1087 ((TimeFrontWindow*)thread->window)->center_x->update(config.center_x);
1088 if(((TimeFrontWindow*)thread->window)->center_y)
1089 ((TimeFrontWindow*)thread->window)->center_y->update(config.center_y);
1091 ((TimeFrontWindow*)thread->window)->update_shape();
1092 thread->window->unlock_window();
1100 void TimeFrontMain::save_data(KeyFrame *keyframe)
1104 // cause data to be stored directly in text
1105 output.set_shared_output(keyframe->get_data(), MESSAGESIZE);
1106 output.tag.set_title("TIMEFRONT");
1108 output.tag.set_property("ANGLE", config.angle);
1109 output.tag.set_property("IN_RADIUS", config.in_radius);
1110 output.tag.set_property("OUT_RADIUS", config.out_radius);
1111 output.tag.set_property("FRAME_RANGE", config.frame_range);
1112 output.tag.set_property("SHAPE", config.shape);
1113 output.tag.set_property("TRACK_USAGE", config.track_usage);
1114 output.tag.set_property("RATE", config.rate);
1115 output.tag.set_property("CENTER_X", config.center_x);
1116 output.tag.set_property("CENTER_Y", config.center_y);
1117 output.tag.set_property("INVERT", config.invert);
1118 output.tag.set_property("SHOW_GRAYSCALE", config.show_grayscale);
1119 output.append_tag();
1120 output.tag.set_title("/TIMEFRONT");
1121 output.append_tag();
1122 output.append_newline();
1123 output.terminate_string();
1126 void TimeFrontMain::read_data(KeyFrame *keyframe)
1130 input.set_shared_input(keyframe->get_data(), strlen(keyframe->get_data()));
1136 result = input.read_tag();
1140 if(input.tag.title_is("TIMEFRONT"))
1142 config.angle = input.tag.get_property("ANGLE", config.angle);
1143 config.rate = input.tag.get_property("RATE", config.rate);
1144 config.in_radius = input.tag.get_property("IN_RADIUS", config.in_radius);
1145 config.out_radius = input.tag.get_property("OUT_RADIUS", config.out_radius);
1146 config.frame_range = input.tag.get_property("FRAME_RANGE", config.frame_range);
1147 config.shape = input.tag.get_property("SHAPE", config.shape);
1148 config.track_usage = input.tag.get_property("TRACK_USAGE", config.track_usage);
1149 config.center_x = input.tag.get_property("CENTER_X", config.center_x);
1150 config.center_y = input.tag.get_property("CENTER_Y", config.center_y);
1151 config.invert = input.tag.get_property("INVERT", config.invert);
1152 config.show_grayscale = input.tag.get_property("SHOW_GRAYSCALE", config.show_grayscale);
1163 TimeFrontPackage::TimeFrontPackage()
1171 TimeFrontUnit::TimeFrontUnit(TimeFrontServer *server, TimeFrontMain *plugin)
1172 : LoadClient(server)
1174 this->plugin = plugin;
1175 this->server = server;
1181 #define CREATE_GRADIENT \
1183 /* Synthesize linear gradient for lookups */ \
1185 a_table = (unsigned char *)malloc(sizeof(unsigned char) * gradient_size); \
1187 for(int i = 0; i < gradient_size; i++) \
1189 float opacity = 0.0; \
1190 switch(plugin->config.rate) \
1192 case TimeFrontConfig::LINEAR: \
1196 if(i >= out_radius) \
1199 opacity = (float)(i - in_radius) / (out_radius - in_radius); \
1201 case TimeFrontConfig::LOG: \
1202 opacity = 1 - exp(LOG_RANGE * -(float)(i - in_radius) / (out_radius - in_radius)); \
1204 case TimeFrontConfig::SQUARE: \
1205 opacity = SQR((float)(i - in_radius) / (out_radius - in_radius)); \
1209 CLAMP(opacity, 0, 1); \
1210 float transparency = 1.0 - opacity; \
1211 a_table[i] = (unsigned char)(out4 * opacity + in4 * transparency); \
1214 for(int i = pkg->y1; i < pkg->y2; i++) \
1216 unsigned char *out_row = plugin->gradient->get_rows()[i]; \
1218 switch(plugin->config.shape) \
1220 case TimeFrontConfig::LINEAR: \
1221 for(int j = 0; j < w; j++) \
1223 int x = j - half_w; \
1224 int y = -(i - half_h); \
1226 /* Rotate by effect angle */ \
1227 int input_y = (int)(gradient_size / 2 - \
1228 (x * sin_angle + y * cos_angle) + \
1231 /* Get gradient value from these coords */ \
1235 out_row[0] = out4; \
1238 if(input_y >= gradient_size) \
1244 out_row[0] = a_table[input_y]; \
1251 case TimeFrontConfig::RADIAL: \
1252 for(int j = 0; j < w; j++) \
1254 double x = j - center_x; \
1255 double y = i - center_y; \
1256 double magnitude = hypot(x, y); \
1257 int input_y = (int)magnitude; \
1258 out_row[0] = a_table[input_y]; \
1266 void TimeFrontUnit::process_package(LoadPackage *package)
1268 TimeFrontPackage *pkg = (TimeFrontPackage*)package;
1269 int h = plugin->input->get_h();
1270 int w = plugin->input->get_w();
1273 int gradient_size = (int)(ceil(hypot(w, h)));
1274 int in_radius = (int)(plugin->config.in_radius / 100 * gradient_size);
1275 int out_radius = (int)(plugin->config.out_radius / 100 * gradient_size);
1276 double sin_angle = sin(plugin->config.angle * (M_PI / 180));
1277 double cos_angle = cos(plugin->config.angle * (M_PI / 180));
1278 double center_x = plugin->config.center_x * w / 100;
1279 double center_y = plugin->config.center_y * h / 100;
1280 unsigned char *a_table = 0;
1282 if(in_radius > out_radius)
1284 in_radius ^= out_radius;
1285 out_radius ^= in_radius;
1286 in_radius ^= out_radius;
1290 int in4 = plugin->config.frame_range;
1294 if(a_table) free(a_table);
1302 TimeFrontServer::TimeFrontServer(TimeFrontMain *plugin,
1305 : LoadServer(total_clients, total_packages)
1307 this->plugin = plugin;
1310 void TimeFrontServer::init_packages()
1312 for(int i = 0; i < get_total_packages(); i++)
1314 TimeFrontPackage *package = (TimeFrontPackage*)get_package(i);
1315 package->y1 = plugin->input->get_h() *
1317 get_total_packages();
1318 package->y2 = plugin->input->get_h() *
1320 get_total_packages();
1324 LoadClient* TimeFrontServer::new_client()
1326 return new TimeFrontUnit(this, plugin);
1329 LoadPackage* TimeFrontServer::new_package()
1331 return new TimeFrontPackage;