5 #include "bcdisplayinfo.h"
12 #include "overlayframe.h"
13 #include "picon_png.h"
19 REGISTER_PLUGIN(TimeFrontMain)
26 TimeFrontConfig::TimeFrontConfig()
32 track_usage = TimeFrontConfig::OTHERTRACK_INTENSITY;
33 shape = TimeFrontConfig::LINEAR;
34 rate = TimeFrontConfig::LINEAR;
41 int TimeFrontConfig::equivalent(TimeFrontConfig &that)
43 return (EQUIV(angle, that.angle) &&
44 EQUIV(in_radius, that.in_radius) &&
45 EQUIV(out_radius, that.out_radius) &&
46 frame_range == that.frame_range &&
47 track_usage == that.track_usage &&
48 shape == that.shape &&
50 EQUIV(center_x, that.center_x) &&
51 EQUIV(center_y, that.center_y) &&
52 invert == that.invert &&
53 show_grayscale == that.show_grayscale);
56 void TimeFrontConfig::copy_from(TimeFrontConfig &that)
59 in_radius = that.in_radius;
60 out_radius = that.out_radius;
61 frame_range = that.frame_range;
62 track_usage = that.track_usage;
65 center_x = that.center_x;
66 center_y = that.center_y;
68 show_grayscale = that.show_grayscale;
71 void TimeFrontConfig::interpolate(TimeFrontConfig &prev,
72 TimeFrontConfig &next,
77 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
78 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
81 this->angle = (int)(prev.angle * prev_scale + next.angle * next_scale);
82 this->in_radius = (int)(prev.in_radius * prev_scale + next.in_radius * next_scale);
83 this->out_radius = (int)(prev.out_radius * prev_scale + next.out_radius * next_scale);
84 frame_range = (int)(prev.frame_range * prev_scale + next.frame_range * next_scale);
85 track_usage = prev.track_usage;
88 center_x = prev.center_x * prev_scale + next.center_x * next_scale;
89 center_y = prev.center_y * prev_scale + next.center_y * next_scale;
91 show_grayscale = prev.show_grayscale;
99 PLUGIN_THREAD_OBJECT(TimeFrontMain, TimeFrontThread, TimeFrontWindow)
102 TimeFrontWindow::TimeFrontWindow(TimeFrontMain *plugin, int x, int y)
103 : BC_Window(plugin->gui_string,
113 this->plugin = plugin;
124 out_radius_title = 0;
126 track_usage_title = 0;
131 TimeFrontWindow::~TimeFrontWindow()
135 int TimeFrontWindow::create_objects()
140 add_subwindow(title = new BC_Title(x, y, _("Type:")));
141 add_subwindow(shape = new TimeFrontShape(plugin,
143 x + title->get_w() + 10,
145 shape->create_objects();
150 add_subwindow(title = new BC_Title(x, y, _("Time range:")));
151 add_subwindow(frame_range = new TimeFrontFrameRange(plugin, x + title->get_w() + 10, y));
152 frame_range_x = x + frame_range->get_w() + 10;
157 add_subwindow(invert = new TimeFrontInvert(plugin, x, y));
158 add_subwindow(show_grayscale = new TimeFrontShowGrayscale(plugin, x+ 100, y));
166 void TimeFrontWindow::update_shape()
168 int x = shape_x, y = shape_y;
170 if(plugin->config.shape == TimeFrontConfig::LINEAR)
172 delete center_x_title;
173 delete center_y_title;
176 delete track_usage_title;
182 track_usage_title = 0;
186 add_subwindow(angle_title = new BC_Title(x, y, _("Angle:")));
187 add_subwindow(angle = new TimeFrontAngle(plugin, x + angle_title->get_w() + 10, y));
192 add_subwindow(rate_title = new BC_Title(x, y, _("Rate:")));
193 add_subwindow(rate = new TimeFrontRate(plugin,
194 x + rate_title->get_w() + 10,
196 rate->create_objects();
198 add_subwindow(in_radius_title = new BC_Title(x, y, _("Inner radius:")));
199 add_subwindow(in_radius = new TimeFrontInRadius(plugin, x + in_radius_title->get_w() + 10, y));
201 add_subwindow(out_radius_title = new BC_Title(x, y, _("Outer radius:")));
202 add_subwindow(out_radius = new TimeFrontOutRadius(plugin, x + out_radius_title->get_w() + 10, y));
207 if(plugin->config.shape == TimeFrontConfig::RADIAL)
211 delete track_usage_title;
215 track_usage_title = 0;
219 add_subwindow(center_x_title = new BC_Title(x, y, _("Center X:")));
220 add_subwindow(center_x = new TimeFrontCenterX(plugin,
221 x + center_x_title->get_w() + 10,
223 x += center_x_title->get_w() + 10 + center_x->get_w() + 10;
224 add_subwindow(center_y_title = new BC_Title(x, y, _("Center Y:")));
225 add_subwindow(center_y = new TimeFrontCenterY(plugin,
226 x + center_y_title->get_w() + 10,
235 add_subwindow(rate_title = new BC_Title(x, y, _("Rate:")));
236 add_subwindow(rate = new TimeFrontRate(plugin,
237 x + rate_title->get_w() + 10,
239 rate->create_objects();
241 add_subwindow(in_radius_title = new BC_Title(x, y, _("Inner radius:")));
242 add_subwindow(in_radius = new TimeFrontInRadius(plugin, x + in_radius_title->get_w() + 10, y));
244 add_subwindow(out_radius_title = new BC_Title(x, y, _("Outer radius:")));
245 add_subwindow(out_radius = new TimeFrontOutRadius(plugin, x + out_radius_title->get_w() + 10, y));
249 if(plugin->config.shape == TimeFrontConfig::OTHERTRACK)
251 delete center_x_title;
252 delete center_y_title;
259 delete in_radius_title;
261 delete out_radius_title;
273 out_radius_title = 0;
277 add_subwindow(track_usage_title = new BC_Title(x, y, _("As timefront use:")));
278 add_subwindow(track_usage = new TimeFrontTrackUsage(plugin,
280 x + track_usage_title->get_w() + 10,
282 track_usage->create_objects();
286 if(plugin->config.shape == TimeFrontConfig::ALPHA)
288 delete center_x_title;
289 delete center_y_title;
296 delete in_radius_title;
298 delete out_radius_title;
300 delete track_usage_title;
312 out_radius_title = 0;
314 track_usage_title = 0;
321 int TimeFrontWindow::close_event()
323 // Set result to 1 to indicate a plugin side close
338 TimeFrontShape::TimeFrontShape(TimeFrontMain *plugin,
339 TimeFrontWindow *gui,
342 : BC_PopupMenu(x, y, 190, to_text(plugin->config.shape), 1)
344 this->plugin = plugin;
347 void TimeFrontShape::create_objects()
349 add_item(new BC_MenuItem(to_text(TimeFrontConfig::LINEAR)));
350 add_item(new BC_MenuItem(to_text(TimeFrontConfig::RADIAL)));
351 add_item(new BC_MenuItem(to_text(TimeFrontConfig::ALPHA)));
352 add_item(new BC_MenuItem(to_text(TimeFrontConfig::OTHERTRACK)));
354 char* TimeFrontShape::to_text(int shape)
358 case TimeFrontConfig::LINEAR:
360 case TimeFrontConfig::OTHERTRACK:
361 return _("Other track as timefront");
362 case TimeFrontConfig::ALPHA:
363 return _("Alpha as timefront");
368 int TimeFrontShape::from_text(char *text)
370 if(!strcmp(text, to_text(TimeFrontConfig::LINEAR)))
371 return TimeFrontConfig::LINEAR;
372 if(!strcmp(text, to_text(TimeFrontConfig::OTHERTRACK)))
373 return TimeFrontConfig::OTHERTRACK;
374 if(!strcmp(text, to_text(TimeFrontConfig::ALPHA)))
375 return TimeFrontConfig::ALPHA;
376 return TimeFrontConfig::RADIAL;
378 int TimeFrontShape::handle_event()
380 plugin->config.shape = from_text(get_text());
382 plugin->send_configure_change();
386 TimeFrontTrackUsage::TimeFrontTrackUsage(TimeFrontMain *plugin,
387 TimeFrontWindow *gui,
390 : BC_PopupMenu(x, y, 140, to_text(plugin->config.track_usage), 1)
392 this->plugin = plugin;
395 void TimeFrontTrackUsage::create_objects()
397 add_item(new BC_MenuItem(to_text(TimeFrontConfig::OTHERTRACK_INTENSITY)));
398 add_item(new BC_MenuItem(to_text(TimeFrontConfig::OTHERTRACK_ALPHA)));
400 char* TimeFrontTrackUsage::to_text(int track_usage)
404 case TimeFrontConfig::OTHERTRACK_INTENSITY:
405 return _("Intensity");
406 case TimeFrontConfig::OTHERTRACK_ALPHA:
407 return _("Alpha mask");
412 int TimeFrontTrackUsage::from_text(char *text)
414 if(!strcmp(text, to_text(TimeFrontConfig::OTHERTRACK_INTENSITY)))
415 return TimeFrontConfig::OTHERTRACK_INTENSITY;
416 if(!strcmp(text, to_text(TimeFrontConfig::OTHERTRACK_ALPHA)))
417 return TimeFrontConfig::OTHERTRACK_ALPHA;
419 return TimeFrontConfig::OTHERTRACK_INTENSITY;
421 int TimeFrontTrackUsage::handle_event()
423 plugin->config.track_usage = from_text(get_text());
425 plugin->send_configure_change();
431 TimeFrontCenterX::TimeFrontCenterX(TimeFrontMain *plugin, int x, int y)
432 : BC_FPot(x, y, plugin->config.center_x, 0, 100)
434 this->plugin = plugin;
436 int TimeFrontCenterX::handle_event()
438 plugin->config.center_x = get_value();
439 plugin->send_configure_change();
445 TimeFrontCenterY::TimeFrontCenterY(TimeFrontMain *plugin, int x, int y)
446 : BC_FPot(x, y, plugin->config.center_y, 0, 100)
448 this->plugin = plugin;
451 int TimeFrontCenterY::handle_event()
453 plugin->config.center_y = get_value();
454 plugin->send_configure_change();
461 TimeFrontAngle::TimeFrontAngle(TimeFrontMain *plugin, int x, int y)
464 plugin->config.angle,
468 this->plugin = plugin;
471 int TimeFrontAngle::handle_event()
473 plugin->config.angle = get_value();
474 plugin->send_configure_change();
479 TimeFrontRate::TimeFrontRate(TimeFrontMain *plugin, int x, int y)
483 to_text(plugin->config.rate),
486 this->plugin = plugin;
488 void TimeFrontRate::create_objects()
490 add_item(new BC_MenuItem(to_text(TimeFrontConfig::LINEAR)));
491 add_item(new BC_MenuItem(to_text(TimeFrontConfig::LOG)));
492 add_item(new BC_MenuItem(to_text(TimeFrontConfig::SQUARE)));
494 char* TimeFrontRate::to_text(int shape)
498 case TimeFrontConfig::LINEAR:
500 case TimeFrontConfig::LOG:
506 int TimeFrontRate::from_text(char *text)
508 if(!strcmp(text, to_text(TimeFrontConfig::LINEAR)))
509 return TimeFrontConfig::LINEAR;
510 if(!strcmp(text, to_text(TimeFrontConfig::LOG)))
511 return TimeFrontConfig::LOG;
512 return TimeFrontConfig::SQUARE;
514 int TimeFrontRate::handle_event()
516 plugin->config.rate = from_text(get_text());
517 plugin->send_configure_change();
523 TimeFrontInRadius::TimeFrontInRadius(TimeFrontMain *plugin, int x, int y)
531 (float)plugin->config.in_radius)
533 this->plugin = plugin;
536 int TimeFrontInRadius::handle_event()
538 plugin->config.in_radius = get_value();
539 plugin->send_configure_change();
544 TimeFrontOutRadius::TimeFrontOutRadius(TimeFrontMain *plugin, int x, int y)
552 (float)plugin->config.out_radius)
554 this->plugin = plugin;
557 int TimeFrontOutRadius::handle_event()
559 plugin->config.out_radius = get_value();
560 plugin->send_configure_change();
564 TimeFrontFrameRange::TimeFrontFrameRange(TimeFrontMain *plugin, int x, int y)
572 (int)plugin->config.frame_range)
574 this->plugin = plugin;
577 int TimeFrontFrameRange::handle_event()
579 plugin->config.frame_range = get_value();
580 plugin->send_configure_change();
585 TimeFrontInvert::TimeFrontInvert(TimeFrontMain *client, int x, int y)
588 client->config.invert,
591 this->plugin = client;
594 int TimeFrontInvert::handle_event()
596 plugin->config.invert = get_value();
597 plugin->send_configure_change();
601 TimeFrontShowGrayscale::TimeFrontShowGrayscale(TimeFrontMain *client, int x, int y)
604 client->config.show_grayscale,
605 _("Show grayscale (for tuning"))
607 this->plugin = client;
610 int TimeFrontShowGrayscale::handle_event()
612 plugin->config.show_grayscale = get_value();
613 plugin->send_configure_change();
619 TimeFrontMain::TimeFrontMain(PluginServer *server)
620 : PluginVClient(server)
622 PLUGIN_CONSTRUCTOR_MACRO
623 need_reconfigure = 1;
629 TimeFrontMain::~TimeFrontMain()
631 PLUGIN_DESTRUCTOR_MACRO
633 if(gradient) delete gradient;
634 if(engine) delete engine;
635 if(overlayer) delete overlayer;
638 char* TimeFrontMain::plugin_title() { return N_("TimeFront"); }
639 int TimeFrontMain::is_realtime() { return 1; }
640 int TimeFrontMain::is_multichannel() { return 1; }
643 NEW_PICON_MACRO(TimeFrontMain)
645 SHOW_GUI_MACRO(TimeFrontMain, TimeFrontThread)
647 SET_STRING_MACRO(TimeFrontMain)
649 RAISE_WINDOW_MACRO(TimeFrontMain)
651 LOAD_CONFIGURATION_MACRO(TimeFrontMain, TimeFrontConfig)
653 int TimeFrontMain::is_synthesis()
658 #define GRADIENTFROMAVG(type, inttype, components, maxval) \
659 for(int i = 0; i < tfframe->get_h(); i++) \
661 type *in_row = (type *)tfframe->get_rows()[i]; \
662 unsigned char *grad_row = gradient->get_rows()[i]; \
663 for(int j = 0; j < tfframe->get_w(); j++) \
665 inttype tmp = (inttype) in_row[j * components] + \
666 in_row[j * components + 1] + \
667 in_row[j * components + 2]; \
668 if (components == 3) \
669 grad_row[j] = (unsigned char) (CLIP((float)config.frame_range * tmp / maxval / 3, 0.0F, config.frame_range)); \
670 else if(components == 4) \
671 grad_row[j] = (unsigned char) (CLIP((float)config.frame_range * tmp * in_row[j * components + 3] / maxval / maxval / 3, 0.0F, config.frame_range)); \
675 #define GRADIENTFROMCHANNEL(type, components, max, channel) \
676 for(int i = 0; i < tfframe->get_h(); i++) \
678 type *in_row = (type *)tfframe->get_rows()[i]; \
679 unsigned char *grad_row = gradient->get_rows()[i]; \
680 for(int j = 0; j < tfframe->get_w(); j++) \
682 if (components == 3) \
683 grad_row[j] = (unsigned char) (CLIP((float)config.frame_range * in_row[j * components + channel] / max, 0.0F, config.frame_range)); \
684 else if(components == 4) \
685 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)); \
689 #define SETALPHA(type, max) \
690 for(int i = 0; i < outframes[0]->get_h(); i++) \
692 type *out_row = (type *)outframes[0]->get_rows()[i]; \
693 for(int j = 0; j < outframes[0]->get_w(); j++) \
695 out_row[j * 4 + 3] = max; \
699 #define GRADIENTTOPICTURE(type, inttype, components, max, invertion) \
700 for(int i = 0; i < height; i++) \
702 type *out_row = (type *)outframes[0]->get_rows()[i]; \
703 unsigned char *grad_row = gradient->get_rows()[i]; \
704 for (int j = 0; j < width; j++) \
706 out_row[0] = (inttype)max * (invertion grad_row[0]) / config.frame_range; \
707 out_row[1] = (inttype)max * (invertion grad_row[0]) / config.frame_range; \
708 out_row[2] = (inttype)max * (invertion grad_row[0]) / config.frame_range; \
709 if (components == 4) \
711 out_row += components; \
716 #define GRADIENTTOYUVPICTURE(type, inttype, components, max, invertion) \
717 for(int i = 0; i < height; i++) \
719 type *out_row = (type *)outframes[0]->get_rows()[i]; \
720 unsigned char *grad_row = gradient->get_rows()[i]; \
721 for (int j = 0; j < width; j++) \
723 out_row[0] = (inttype)max * (invertion grad_row[0]) / config.frame_range; \
724 out_row[1] = max/2; \
725 out_row[2] = max/2; \
726 if (components == 4) \
728 out_row += components; \
733 #define COMPOSITEIMAGE(type, components, invertion) \
734 for (int i = 0; i < height; i++) \
736 type *out_row = (type *)outframes[0]->get_rows()[i]; \
737 unsigned char *gradient_row = gradient->get_rows()[i]; \
738 for (int j = 0; j < width; j++) \
740 unsigned int choice = invertion gradient_row[j]; \
742 out_row[0] = framelist[choice]->get_rows()[i][j * components + 0]; \
743 out_row[1] = framelist[choice]->get_rows()[i][j * components + 1]; \
744 out_row[2] = framelist[choice]->get_rows()[i][j * components + 2]; \
745 if (components == 4) \
746 out_row[3] = framelist[choice]->get_rows()[i][j * components + 3]; \
748 out_row += components; \
754 int TimeFrontMain::process_buffer(VFrame **frame,
755 int64_t start_position,
757 //int TimeFrontMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr)
759 VFrame **outframes = frame;
760 VFrame *(framelist[1024]);
761 framelist[0] = new VFrame (0, outframes[0]->get_w(), outframes[0]->get_h(), outframes[0]->get_color_model());
762 read_frame(framelist[0],
766 this->input = framelist[0];
767 this->output = outframes[0];
768 need_reconfigure |= load_configuration();
769 if (config.shape == TimeFrontConfig::OTHERTRACK)
771 // this->output = frame[1];
772 if (get_total_buffers() != 2)
774 // FIXME, maybe this should go to some other notification area?
775 printf("ERROR: TimeFront plugin - If you are using another track for timefront, you have to have it under shared effects\n");
778 if (outframes[0]->get_w() != outframes[1]->get_w() || outframes[0]->get_h() != outframes[1]->get_h())
780 printf("Sizes of master track and timefront track do not match\n");
785 // Generate new gradient
788 need_reconfigure = 0;
790 if(!gradient) gradient = new VFrame(0,
791 outframes[0]->get_w(),
792 outframes[0]->get_h(),
796 if (config.shape != TimeFrontConfig::OTHERTRACK &&
797 config.shape != TimeFrontConfig::ALPHA)
799 if(!engine) engine = new TimeFrontServer(this,
800 get_project_smp() + 1,
801 get_project_smp() + 1);
802 engine->process_packages();
806 if (config.shape == TimeFrontConfig::ALPHA)
808 if(!gradient) gradient = new VFrame(0,
809 outframes[0]->get_w(),
810 outframes[0]->get_h(),
812 VFrame *tfframe = framelist[0];
813 switch (tfframe->get_color_model())
817 GRADIENTFROMCHANNEL(unsigned char, 4, 255, 3);
822 GRADIENTFROMCHANNEL(float, 4, 1.0f, 3);
827 printf("TimeFront plugin error: ALPHA used, but project color model does not have alpha\n");
834 if (config.shape == TimeFrontConfig::OTHERTRACK)
836 if(!gradient) gradient = new VFrame(0,
837 outframes[0]->get_w(),
838 outframes[0]->get_h(),
840 VFrame *tfframe = outframes[1];
845 if (config.track_usage == TimeFrontConfig::OTHERTRACK_INTENSITY)
847 switch (tfframe->get_color_model())
850 GRADIENTFROMAVG(unsigned char, unsigned short, 4, 255); // Has to be 2 ranges bigger, sice we need precision for alpha
853 GRADIENTFROMAVG(unsigned char, unsigned short, 3, 255);
856 GRADIENTFROMAVG(float, float, 3, 1.0f);
859 GRADIENTFROMAVG(float, float, 4, 1.0f);
861 case BC_YUV888: // We cheat and take Y component as intensity
862 GRADIENTFROMCHANNEL(unsigned char, 3, 255, 0);
865 GRADIENTFROMCHANNEL(unsigned char, 4, 255, 0);
871 if (config.track_usage == TimeFrontConfig::OTHERTRACK_ALPHA)
873 switch (tfframe->get_color_model())
877 GRADIENTFROMCHANNEL(unsigned char, 4, 255, 3);
882 GRADIENTFROMCHANNEL(float, 4, 1.0f, 3);
887 printf("TimeFront plugin error: ALPHA track used, but project color model does not have alpha\n");
894 printf("TimeFront plugin error: unsupported track_usage parameter\n");
899 if (!config.show_grayscale)
901 for (int i = 1; i <= config.frame_range; i++)
903 framelist[i] = new VFrame (0, outframes[0]->get_w(), outframes[0]->get_h(), outframes[0]->get_color_model());
905 read_frame(framelist[i],
913 int width = outframes[0]->get_w();
914 int height = outframes[0]->get_h();
915 if (config.show_grayscale)
919 switch (outframes[0]->get_color_model())
922 GRADIENTTOPICTURE(unsigned char, unsigned short, 3, 255, );
925 GRADIENTTOPICTURE(unsigned char, unsigned short, 4, 255, );
928 GRADIENTTOYUVPICTURE(unsigned char, unsigned short, 3, 255, );
931 GRADIENTTOYUVPICTURE(unsigned char, unsigned short, 4, 255, );
934 GRADIENTTOPICTURE(float, float, 3, 1.0f, );
937 GRADIENTTOPICTURE(float, float, 4, 1.0f, );
944 switch (outframes[0]->get_color_model())
947 GRADIENTTOPICTURE(unsigned char, unsigned short, 3, 255, config.frame_range -);
950 GRADIENTTOPICTURE(unsigned char, unsigned short, 4, 255, config.frame_range -);
953 GRADIENTTOYUVPICTURE(unsigned char, unsigned short, 3, 255, config.frame_range -);
956 GRADIENTTOYUVPICTURE(unsigned char, unsigned short, 4, 255, config.frame_range -);
959 GRADIENTTOPICTURE(float, float, 3, 1.0f, config.frame_range -);
962 GRADIENTTOPICTURE(float, float, 4, 1.0f, config.frame_range -);
971 switch (outframes[0]->get_color_model())
974 COMPOSITEIMAGE(unsigned char, 3, );
977 COMPOSITEIMAGE(unsigned char, 4, );
980 COMPOSITEIMAGE(unsigned char, 3, );
983 COMPOSITEIMAGE(unsigned char, 4, );
986 COMPOSITEIMAGE(float, 3, );
989 COMPOSITEIMAGE(float, 4, );
997 switch (outframes[0]->get_color_model())
1000 COMPOSITEIMAGE(unsigned char, 3, config.frame_range -);
1003 COMPOSITEIMAGE(unsigned char, 4, config.frame_range -);
1006 COMPOSITEIMAGE(unsigned char, 3, config.frame_range -);
1009 COMPOSITEIMAGE(unsigned char, 4, config.frame_range -);
1012 COMPOSITEIMAGE(float, 3, config.frame_range -);
1015 COMPOSITEIMAGE(float, 4, config.frame_range -);
1022 if (config.shape == TimeFrontConfig::ALPHA)
1025 switch (outframes[0]->get_color_model())
1029 SETALPHA(unsigned char, 255);
1032 SETALPHA(float, 1.0f);
1040 delete framelist[0];
1041 if (!config.show_grayscale)
1043 for (int i = 1; i <= config.frame_range; i++)
1044 delete framelist[i];
1050 void TimeFrontMain::update_gui()
1054 if(load_configuration())
1056 thread->window->lock_window("TimeFrontMain::update_gui");
1057 thread->window->frame_range->update(config.frame_range);
1058 thread->window->shape->set_text(TimeFrontShape::to_text(config.shape));
1059 thread->window->show_grayscale->update(config.show_grayscale);
1060 thread->window->invert->update(config.invert);
1061 thread->window->shape->set_text(TimeFrontShape::to_text(config.shape));
1062 if (thread->window->rate)
1063 thread->window->rate->set_text(TimeFrontRate::to_text(config.rate));
1064 if (thread->window->in_radius)
1065 thread->window->in_radius->update(config.in_radius);
1066 if (thread->window->out_radius)
1067 thread->window->out_radius->update(config.out_radius);
1068 if (thread->window->track_usage)
1069 thread->window->track_usage->set_text(TimeFrontTrackUsage::to_text(config.track_usage));
1070 if(thread->window->angle)
1071 thread->window->angle->update(config.angle);
1072 if(thread->window->center_x)
1073 thread->window->center_x->update(config.center_x);
1074 if(thread->window->center_y)
1075 thread->window->center_y->update(config.center_y);
1077 thread->window->update_shape();
1078 thread->window->unlock_window();
1084 int TimeFrontMain::load_defaults()
1086 char directory[1024], string[1024];
1087 // set the default directory
1088 sprintf(directory, "%stimefront.rc", BCASTDIR);
1090 // load the defaults
1091 defaults = new BC_Hash(directory);
1094 // printf("TimeFrontMain::load_defaults %d %d %d %d\n",
1099 config.angle = defaults->get("ANGLE", config.angle);
1100 config.in_radius = defaults->get("IN_RADIUS", config.in_radius);
1101 config.out_radius = defaults->get("OUT_RADIUS", config.out_radius);
1102 config.frame_range = defaults->get("FRAME_RANGE", config.frame_range);
1103 config.shape = defaults->get("SHAPE", config.shape);
1104 config.shape = defaults->get("TRACK_USAGE", config.track_usage);
1105 config.rate = defaults->get("RATE", config.rate);
1106 config.center_x = defaults->get("CENTER_X", config.center_x);
1107 config.center_y = defaults->get("CENTER_Y", config.center_y);
1108 config.invert = defaults->get("INVERT", config.invert);
1109 config.show_grayscale = defaults->get("SHOW_GRAYSCALE", config.show_grayscale);
1114 int TimeFrontMain::save_defaults()
1116 defaults->update("ANGLE", config.angle);
1117 defaults->update("IN_RADIUS", config.in_radius);
1118 defaults->update("OUT_RADIUS", config.out_radius);
1119 defaults->update("FRAME_RANGE", config.frame_range);
1120 defaults->update("RATE", config.rate);
1121 defaults->update("SHAPE", config.shape);
1122 defaults->update("TRACK_USAGE", config.track_usage);
1123 defaults->update("CENTER_X", config.center_x);
1124 defaults->update("CENTER_Y", config.center_y);
1125 defaults->update("INVERT", config.invert);
1126 defaults->update("SHOW_GRAYSCALE", config.show_grayscale);
1133 void TimeFrontMain::save_data(KeyFrame *keyframe)
1137 // cause data to be stored directly in text
1138 output.set_shared_string(keyframe->data, MESSAGESIZE);
1139 output.tag.set_title("TIMEFRONT");
1141 output.tag.set_property("ANGLE", config.angle);
1142 output.tag.set_property("IN_RADIUS", config.in_radius);
1143 output.tag.set_property("OUT_RADIUS", config.out_radius);
1144 output.tag.set_property("FRAME_RANGE", config.frame_range);
1145 output.tag.set_property("SHAPE", config.shape);
1146 output.tag.set_property("TRACK_USAGE", config.track_usage);
1147 output.tag.set_property("RATE", config.rate);
1148 output.tag.set_property("CENTER_X", config.center_x);
1149 output.tag.set_property("CENTER_Y", config.center_y);
1150 output.tag.set_property("INVERT", config.invert);
1151 output.tag.set_property("SHOW_GRAYSCALE", config.show_grayscale);
1152 output.append_tag();
1153 output.terminate_string();
1156 void TimeFrontMain::read_data(KeyFrame *keyframe)
1160 input.set_shared_string(keyframe->data, strlen(keyframe->data));
1166 result = input.read_tag();
1170 if(input.tag.title_is("TIMEFRONT"))
1172 config.angle = input.tag.get_property("ANGLE", config.angle);
1173 config.rate = input.tag.get_property("RATE", config.rate);
1174 config.in_radius = input.tag.get_property("IN_RADIUS", config.in_radius);
1175 config.out_radius = input.tag.get_property("OUT_RADIUS", config.out_radius);
1176 config.frame_range = input.tag.get_property("FRAME_RANGE", config.frame_range);
1177 config.shape = input.tag.get_property("SHAPE", config.shape);
1178 config.track_usage = input.tag.get_property("TRACK_USAGE", config.track_usage);
1179 config.center_x = input.tag.get_property("CENTER_X", config.center_x);
1180 config.center_y = input.tag.get_property("CENTER_Y", config.center_y);
1181 config.invert = input.tag.get_property("INVERT", config.invert);
1182 config.show_grayscale = input.tag.get_property("SHOW_GRAYSCALE", config.show_grayscale);
1193 TimeFrontPackage::TimeFrontPackage()
1201 TimeFrontUnit::TimeFrontUnit(TimeFrontServer *server, TimeFrontMain *plugin)
1202 : LoadClient(server)
1204 this->plugin = plugin;
1205 this->server = server;
1209 #define SQR(x) ((x) * (x))
1212 #define CREATE_GRADIENT \
1214 /* Synthesize linear gradient for lookups */ \
1216 a_table = (unsigned char *)malloc(sizeof(unsigned char) * gradient_size); \
1218 for(int i = 0; i < gradient_size; i++) \
1221 float transparency; \
1222 switch(plugin->config.rate) \
1224 case TimeFrontConfig::LINEAR: \
1228 if(i >= out_radius) \
1231 opacity = (float)(i - in_radius) / (out_radius - in_radius); \
1233 case TimeFrontConfig::LOG: \
1234 opacity = 1 - exp(LOG_RANGE * -(float)(i - in_radius) / (out_radius - in_radius)); \
1236 case TimeFrontConfig::SQUARE: \
1237 opacity = SQR((float)(i - in_radius) / (out_radius - in_radius)); \
1241 CLAMP(opacity, 0, 1); \
1242 transparency = 1.0 - opacity; \
1243 a_table[i] = (unsigned char)(out4 * opacity + in4 * transparency); \
1246 for(int i = pkg->y1; i < pkg->y2; i++) \
1248 unsigned char *out_row = plugin->gradient->get_rows()[i]; \
1250 switch(plugin->config.shape) \
1252 case TimeFrontConfig::LINEAR: \
1253 for(int j = 0; j < w; j++) \
1255 int x = j - half_w; \
1256 int y = -(i - half_h); \
1258 /* Rotate by effect angle */ \
1259 int input_y = (int)(gradient_size / 2 - \
1260 (x * sin_angle + y * cos_angle) + \
1263 /* Get gradient value from these coords */ \
1267 out_row[0] = out4; \
1270 if(input_y >= gradient_size) \
1276 out_row[0] = a_table[input_y]; \
1283 case TimeFrontConfig::RADIAL: \
1284 for(int j = 0; j < w; j++) \
1286 double x = j - center_x; \
1287 double y = i - center_y; \
1288 double magnitude = hypot(x, y); \
1289 int input_y = (int)magnitude; \
1290 out_row[0] = a_table[input_y]; \
1298 void TimeFrontUnit::process_package(LoadPackage *package)
1300 TimeFrontPackage *pkg = (TimeFrontPackage*)package;
1301 int h = plugin->input->get_h();
1302 int w = plugin->input->get_w();
1305 int gradient_size = (int)(ceil(hypot(w, h)));
1306 int in_radius = (int)(plugin->config.in_radius / 100 * gradient_size);
1307 int out_radius = (int)(plugin->config.out_radius / 100 * gradient_size);
1308 double sin_angle = sin(plugin->config.angle * (M_PI / 180));
1309 double cos_angle = cos(plugin->config.angle * (M_PI / 180));
1310 double center_x = plugin->config.center_x * w / 100;
1311 double center_y = plugin->config.center_y * h / 100;
1312 unsigned char *a_table = 0;
1314 if(in_radius > out_radius)
1316 in_radius ^= out_radius;
1317 out_radius ^= in_radius;
1318 in_radius ^= out_radius;
1322 int in4 = plugin->config.frame_range;
1326 if(a_table) free(a_table);
1334 TimeFrontServer::TimeFrontServer(TimeFrontMain *plugin,
1337 : LoadServer(total_clients, total_packages)
1339 this->plugin = plugin;
1342 void TimeFrontServer::init_packages()
1344 for(int i = 0; i < get_total_packages(); i++)
1346 TimeFrontPackage *package = (TimeFrontPackage*)get_package(i);
1347 package->y1 = plugin->input->get_h() *
1349 get_total_packages();
1350 package->y2 = plugin->input->get_h() *
1352 get_total_packages();
1356 LoadClient* TimeFrontServer::new_client()
1358 return new TimeFrontUnit(this, plugin);
1361 LoadPackage* TimeFrontServer::new_package()
1363 return new TimeFrontPackage;