r125: This commit was manufactured by cvs2svn to create tag 'r1_1_7-last'.
[cinelerra_cv/mob.git] / hvirtual / plugins / rotate / rotate.C
blob73fa8538da5ca7cd5ebb3ddc48a7115ddabd1f80
1 #include "bcdisplayinfo.h"
2 #include "clip.h"
3 #include "defaults.h"
4 #include "filexml.h"
5 #include "guicast.h"
6 #include "picon_png.h"
7 #include "pluginvclient.h"
8 #include "rotateframe.h"
9 #include "vframe.h"
12 #include <string.h>
14 #include <libintl.h>
15 #define _(String) gettext(String)
16 #define gettext_noop(String) String
17 #define N_(String) gettext_noop (String)
20 #define SQR(x) ((x) * (x))
21 #define MAXANGLE 360
24 class RotateEffect;
25 class RotateWindow;
28 class RotateConfig
30 public:
31         RotateConfig();
33         int equivalent(RotateConfig &that);
34         void copy_from(RotateConfig &that);
35         void interpolate(RotateConfig &prev, 
36                 RotateConfig &next, 
37                 long prev_frame, 
38                 long next_frame, 
39                 long current_frame);
41         float angle;
42         int bilinear;
45 class RotateToggle : public BC_Radial
47 public:
48         RotateToggle(RotateWindow *window, 
49                 RotateEffect *plugin, 
50                 int init_value, 
51                 int x, 
52                 int y, 
53                 int value, 
54                 char *string);
55         int handle_event();
57         RotateEffect *plugin;
58     RotateWindow *window;
59     int value;
62 class RotateInterpolate : public BC_CheckBox
64 public:
65         RotateInterpolate(RotateEffect *plugin, int x, int y);
66         int handle_event();
67         RotateEffect *plugin;
70 class RotateFine : public BC_FPot
72 public:
73         RotateFine(RotateWindow *window, 
74                 RotateEffect *plugin, 
75                 int x, 
76                 int y);
77         int handle_event();
79         RotateEffect *plugin;
80     RotateWindow *window;
83 class RotateWindow : public BC_Window
85 public:
86         RotateWindow(RotateEffect *plugin, int x, int y);
88         int create_objects();
89         int close_event();
90         int update();
91         int update_fine();
92         int update_toggles();
94         RotateEffect *plugin;
95         RotateToggle *toggle0;
96         RotateToggle *toggle90;
97         RotateToggle *toggle180;
98         RotateToggle *toggle270;
99         RotateFine *fine;
100         RotateInterpolate *bilinear;
104 PLUGIN_THREAD_HEADER(RotateEffect, RotateThread, RotateWindow)
107 class RotateEffect : public PluginVClient
109 public:
110         RotateEffect(PluginServer *server);
111         ~RotateEffect();
112         
113         int process_realtime(VFrame *input, VFrame *output);
114         int is_realtime();
115         char* plugin_title();
116         VFrame* new_picon();
117         int show_gui();
118         void raise_window();
119         void update_gui();
120         int set_string();
121         int load_configuration();
122         int load_defaults();
123         int save_defaults();
124         void save_data(KeyFrame *keyframe);
125         void read_data(KeyFrame *keyframe);
127         RotateConfig config;
128         RotateFrame *engine;
129         RotateThread *thread;
130         VFrame *temp_frame;
131         Defaults *defaults;
132         int need_reconfigure;
141 REGISTER_PLUGIN(RotateEffect)
160 RotateConfig::RotateConfig()
162         angle = 0;
165 int RotateConfig::equivalent(RotateConfig &that)
167         return EQUIV(angle, that.angle) && bilinear == that.bilinear;
170 void RotateConfig::copy_from(RotateConfig &that)
172         angle = that.angle;
173         bilinear = that.bilinear;
176 void RotateConfig::interpolate(RotateConfig &prev, 
177                 RotateConfig &next, 
178                 long prev_frame, 
179                 long next_frame, 
180                 long current_frame)
182         double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
183         double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
185         this->angle = prev.angle * prev_scale + next.angle * next_scale;
186         bilinear = prev.bilinear;
199 RotateToggle::RotateToggle(RotateWindow *window, 
200         RotateEffect *plugin, 
201         int init_value, 
202         int x, 
203         int y, 
204         int value, 
205         char *string)
206  : BC_Radial(x, y, init_value, string)
208         this->value = value;
209         this->plugin = plugin;
210     this->window = window;
213 int RotateToggle::handle_event()
215         plugin->config.angle = (float)value;
216     window->update();
217         plugin->send_configure_change();
218         return 1;
223 RotateInterpolate::RotateInterpolate(RotateEffect *plugin, int x, int y)
224  : BC_CheckBox(x, y, plugin->config.bilinear, _("Interpolate"))
226         this->plugin = plugin;
228 int RotateInterpolate::handle_event()
230         plugin->config.bilinear = get_value();
231         plugin->send_configure_change();
232         return 1;
238 RotateFine::RotateFine(RotateWindow *window, RotateEffect *plugin, int x, int y)
239  : BC_FPot(x, 
240         y, 
241         (float)plugin->config.angle, 
242         (float)-360, 
243         (float)360)
245         this->window = window;
246         this->plugin = plugin;
247         set_precision(0.01);
250 int RotateFine::handle_event()
252         plugin->config.angle = get_value();
253         window->update_toggles();
254         plugin->send_configure_change();
255         return 1;
267 RotateWindow::RotateWindow(RotateEffect *plugin, int x, int y)
268  : BC_Window(plugin->gui_string, 
269         x,
270         y,
271         250, 
272         170, 
273         250, 
274         170, 
275         0, 
276         0,
277         1)
279         this->plugin = plugin;
282 #define RADIUS 30
284 int RotateWindow::create_objects()
286         int x = 10, y = 10;
291         add_tool(new BC_Title(x, y, _("Rotate")));
292         x += 50;
293         y += 20;
294         add_tool(toggle0 = new RotateToggle(this, 
295                 plugin, 
296                 plugin->config.angle == 0, 
297                 x, 
298                 y, 
299                 0, 
300                 "0"));
301     x += RADIUS;
302     y += RADIUS;
303         add_tool(toggle90 = new RotateToggle(this, 
304                 plugin, 
305                 plugin->config.angle == 90, 
306                 x, 
307                 y, 
308                 90, 
309                 "90"));
310     x -= RADIUS;
311     y += RADIUS;
312         add_tool(toggle180 = new RotateToggle(this, 
313                 plugin, 
314                 plugin->config.angle == 180, 
315                 x, 
316                 y, 
317                 180, 
318                 "180"));
319     x -= RADIUS;
320     y -= RADIUS;
321         add_tool(toggle270 = new RotateToggle(this, 
322                 plugin, 
323                 plugin->config.angle == 270, 
324                 x, 
325                 y, 
326                 270, 
327                 "270"));
328         add_subwindow(bilinear = new RotateInterpolate(plugin, 10, y + 60));
329         x += 110;
330         y -= 50;
331         add_tool(fine = new RotateFine(this, plugin, x, y));
332         y += fine->get_h() + 10;
333         add_tool(new BC_Title(x, y, _("Angle")));
337         show_window();
338         flush();
342         return 0;
345 int RotateWindow::close_event()
347 // Set result to 1 to indicate a client side close
348         set_done(1);
349         return 1;
352 int RotateWindow::update()
354         update_fine();
355         update_toggles();
356         bilinear->update(plugin->config.bilinear);
357         return 0;
360 int RotateWindow::update_fine()
362         fine->update(plugin->config.angle);
363         return 0;
366 int RotateWindow::update_toggles()
368         toggle0->update(EQUIV(plugin->config.angle, 0));
369         toggle90->update(EQUIV(plugin->config.angle, 90));
370         toggle180->update(EQUIV(plugin->config.angle, 180));
371         toggle270->update(EQUIV(plugin->config.angle, 270));
372         return 0;
389 PLUGIN_THREAD_OBJECT(RotateEffect, RotateThread, RotateWindow)
408 RotateEffect::RotateEffect(PluginServer *server)
409  : PluginVClient(server)
411         engine = 0;
412         temp_frame = 0;
413         need_reconfigure = 1;
414         PLUGIN_CONSTRUCTOR_MACRO
417 RotateEffect::~RotateEffect()
419         PLUGIN_DESTRUCTOR_MACRO
420         if(engine) delete engine;
421         if(temp_frame) delete temp_frame;
426 char* RotateEffect::plugin_title() 
428         return _("Rotate");
431 int RotateEffect::is_realtime() 
433         return 1;
436 NEW_PICON_MACRO(RotateEffect)
438 SET_STRING_MACRO(RotateEffect)
440 SHOW_GUI_MACRO(RotateEffect, RotateThread)
442 RAISE_WINDOW_MACRO(RotateEffect)
445 void RotateEffect::update_gui()
447         if(thread)
448         {
449                 load_configuration();
450                 thread->window->lock_window();
451                 thread->window->update();
452                 thread->window->unlock_window();
453         }
456 LOAD_CONFIGURATION_MACRO(RotateEffect, RotateConfig)
460 int RotateEffect::load_defaults()
462         char directory[1024], string[1024];
463 // set the default directory
464         sprintf(directory, "%srotate.rc", BCASTDIR);
466 // load the defaults
467         defaults = new Defaults(directory);
468         defaults->load();
470         config.angle = defaults->get("ANGLE", (float)config.angle);
471         config.bilinear = defaults->get("INTERPOLATE", (int)config.bilinear);
472         return 0;
475 int RotateEffect::save_defaults()
477         defaults->update("ANGLE", (float)config.angle);
478         defaults->update("INTERPOLATE", (int)config.bilinear);
479         defaults->save();
480         return 0;
483 void RotateEffect::save_data(KeyFrame *keyframe)
485         FileXML output;
487 // cause data to be stored directly in text
488         output.set_shared_string(keyframe->data, MESSAGESIZE);
489         output.tag.set_title("ROTATE");
490         output.tag.set_property("ANGLE", (float)config.angle);
491         output.tag.set_property("INTERPOLATE", (int)config.bilinear);
492         output.append_tag();
493         output.terminate_string();
494 // data is now in *text
497 void RotateEffect::read_data(KeyFrame *keyframe)
499         FileXML input;
501         input.set_shared_string(keyframe->data, strlen(keyframe->data));
503         int result = 0;
505         while(!result)
506         {
507                 result = input.read_tag();
509                 if(!result)
510                 {
511                         if(input.tag.title_is("ROTATE"))
512                         {
513                                 config.angle = input.tag.get_property("ANGLE", (float)config.angle);
514                                 config.bilinear = input.tag.get_property("INTERPOLATE", (int)config.bilinear);
515                         }
516                 }
517         }
520 int RotateEffect::process_realtime(VFrame *input, VFrame *output)
522         load_configuration();
525 //printf("RotateEffect::process_realtime 1 %d %f\n", config.bilinear, config.angle);
527         if(!temp_frame)
528                 temp_frame = new VFrame(0, 
529                         input->get_w(), 
530                         input->get_h(), 
531                         input->get_color_model());
533         if(!engine) engine = new RotateFrame(PluginClient::smp + 1, 
534                 input->get_w(), 
535                 input->get_h());
537         temp_frame->copy_from(input);
539         engine->rotate(output, 
540                 temp_frame, 
541                 config.angle,
542                 config.bilinear);
544         return 0;