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
27 RumblerConfig::RumblerConfig()
32 void RumblerConfig::reset()
41 void RumblerConfig::copy_from(RumblerConfig &that)
43 time_rumble = that.time_rumble;
44 time_rate = that.time_rate;
45 space_rumble = that.space_rumble;
46 space_rate = that.space_rate;
47 sequence = that.sequence;
50 int RumblerConfig::equivalent(RumblerConfig &that)
52 return time_rumble == that.time_rumble &&
53 time_rate == that.time_rate &&
54 space_rumble == that.space_rumble &&
55 space_rate == that.space_rate &&
56 sequence == that.sequence;
59 void RumblerConfig::interpolate(RumblerConfig &prev, RumblerConfig &next,
60 int64_t prev_frame, int64_t next_frame, int64_t current_frame)
62 double next_scale = (double)(current_frame - prev_frame) / (next_frame - prev_frame);
63 double prev_scale = (double)(next_frame - current_frame) / (next_frame - prev_frame);
64 this->time_rumble = prev.time_rumble * prev_scale + next.time_rumble * next_scale;
65 this->time_rate = prev.time_rate * prev_scale + next.time_rate * next_scale;
66 this->space_rumble = prev.space_rumble * prev_scale + next.space_rumble * next_scale;
67 this->space_rate = prev.space_rate * prev_scale + next.space_rate * next_scale;
68 this->sequence = prev.sequence;
71 RumblerWindow::RumblerWindow(Rumbler *plugin)
72 : PluginClientWindow(plugin, xS(300), yS(150), xS(300), yS(150), 0)
74 this->plugin = plugin;
77 RumblerWindow::~RumblerWindow()
81 void RumblerWindow::create_objects()
83 int xs10 = xS(10), xs64 = xS(64), xs100 = xS(100);
84 int ys10 = yS(10), ys35 = yS(35);
85 int x = xs10, x1 = x + xs64, x2 = x1 + xs100;
89 add_subwindow(title = new BC_Title(x1, y, _("rumble")));
90 add_subwindow(title = new BC_Title(x2, y, _("rate")));
91 y += title->get_h() + ys10;
92 add_subwindow(title = new BC_Title(x, y, _("time:")));
93 add_subwindow(time_rumble = new RumblerRate(plugin, this, plugin->config.time_rumble, x1, y));
94 add_subwindow(time_rate = new RumblerRate(plugin, this, plugin->config.time_rate, x2, y));
95 y += title->get_h() + ys10;
96 add_subwindow(title = new BC_Title(x, y, _("space:")));
97 add_subwindow(space_rumble = new RumblerRate(plugin, this, plugin->config.space_rumble, x1, y));
98 add_subwindow(space_rate = new RumblerRate(plugin, this, plugin->config.space_rate, x2, y));
99 y += title->get_h() + ys10;
100 add_subwindow(title = new BC_Title(x, y, _("seq:")));
101 add_subwindow(seq = new RumblerSeq(plugin, this, plugin->config.sequence, x1, y));
103 add_subwindow(reset = new RumblerReset(plugin, this, x, y));
110 void RumblerWindow::update()
112 time_rumble->update(plugin->config.time_rumble);
113 time_rate->update(plugin->config.time_rate);
114 space_rumble->update(plugin->config.space_rumble);
115 space_rate->update(plugin->config.space_rate);
116 seq->update((int64_t)(plugin->config.sequence));
120 RumblerRate::RumblerRate(Rumbler *plugin, RumblerWindow *gui,
121 float &value, int x, int y)
122 : BC_TextBox(x, y, xS(90), 1, value)
124 this->plugin = plugin;
125 this->value = &value;
129 int RumblerRate::handle_event()
131 *value = atof(get_text());
132 plugin->send_configure_change();
136 RumblerSeq::RumblerSeq(Rumbler *plugin, RumblerWindow *gui,
137 int &value, int x, int y)
138 : BC_TextBox(x, y, xS(72), 1, value)
140 this->plugin = plugin;
141 this->value = &value;
145 int RumblerSeq::handle_event()
147 *value = atoi(get_text());
148 plugin->send_configure_change();
153 RumblerReset::RumblerReset(Rumbler *plugin, RumblerWindow *gui, int x, int y)
154 : BC_GenericButton(x, y, _("Reset"))
156 this->plugin = plugin;
159 RumblerReset::~RumblerReset()
162 int RumblerReset::handle_event()
164 plugin->config.reset();
166 plugin->send_configure_change();
171 REGISTER_PLUGIN(Rumbler)
173 Rumbler::Rumbler(PluginServer *server)
174 : PluginVClient(server)
185 double Rumbler::rumble(int64_t seq, double cur, double per, double amp)
187 if( !per || !amp ) return 0.;
188 int64_t t = cur / per;
191 static const int64_t rmax1 = ((int64_t)RAND_MAX) + 1;
192 double prev = (double)random() / rmax1 - 0.5;
194 double next = (double)random() / rmax1 - 0.5;
195 double v = (cur-t0) / per, u = 1. - v;
196 return amp*(u*prev + v*next);
199 int Rumbler::process_buffer(VFrame *frame, int64_t start_position, double frame_rate)
201 load_configuration();
204 double cur = frame_rate > 0 ? start_position / frame_rate : 0;
205 double per = config.time_rate > 0 ? 1./config.time_rate : 0;
206 double rum = config.time_rumble;
207 int seq = config.sequence;
208 int64_t pos = rumble(seq+0x0000000, cur, per, rum) + start_position;
209 read_frame(frame, 0, pos, frame_rate, 0);
210 cur = frame_rate > 0 ? start_position / frame_rate : 0;
211 per = config.space_rate > 0 ? 1./config.space_rate : 0;
212 rum = config.space_rumble;
213 x1 = rumble(seq+0x1000000, cur, per, rum) + 0;
214 y1 = rumble(seq+0x2000000, cur, per, rum) + 0;
215 x2 = rumble(seq+0x3000000, cur, per, rum) + 100;
216 y2 = rumble(seq+0x4000000, cur, per, rum) + 0;
217 x3 = rumble(seq+0x5000000, cur, per, rum) + 100;
218 y3 = rumble(seq+0x6000000, cur, per, rum) + 100;
219 x4 = rumble(seq+0x7000000, cur, per, rum) + 0;
220 y4 = rumble(seq+0x8000000, cur, per, rum) + 100;
222 int cpus = get_project_smp() + 1;
223 engine = new AffineEngine(cpus, cpus);
226 if( get_use_opengl() )
229 int w = frame->get_w(), h = frame->get_h();
230 int color_model = frame->get_color_model();
231 input = new_temp(w, h, color_model);
232 input->copy_from(frame);
233 output->clear_frame();
234 engine->process(output, input, input,
235 AffineEngine::PERSPECTIVE,
236 x1, y1, x2, y2, x3, y3, x4, y4, 1);
241 int Rumbler::handle_opengl()
244 engine->set_opengl(1);
245 engine->process(output, input, input,
246 AffineEngine::PERSPECTIVE,
247 x1, y1, x2, y2, x3, y3, x4, y4, 1);
248 engine->set_opengl(0);
254 const char* Rumbler::plugin_title() { return N_("Rumbler"); }
255 int Rumbler::is_realtime() { return 1; }
257 NEW_WINDOW_MACRO(Rumbler, RumblerWindow)
259 LOAD_CONFIGURATION_MACRO(Rumbler, RumblerConfig)
261 void Rumbler::save_data(KeyFrame *keyframe)
265 output.set_shared_output(keyframe->xbuf);
266 output.tag.set_title("RUMBLER");
267 output.tag.set_property("TIME_RUMBLE", config.time_rumble);
268 output.tag.set_property("TIME_RATE", config.time_rate);
269 output.tag.set_property("SPACE_RUMBLE", config.space_rumble);
270 output.tag.set_property("SPACE_RATE", config.space_rate);
271 output.tag.set_property("SEQUENCE", config.sequence);
273 output.tag.set_title("/RUMBLER");
275 output.append_newline();
276 output.terminate_string();
279 void Rumbler::read_data(KeyFrame *keyframe)
283 input.set_shared_input(keyframe->xbuf);
285 while( !input.read_tag() ) {
286 if( input.tag.title_is("RUMBLER") ) {
287 config.time_rumble = input.tag.get_property("TIME_RUMBLE", config.time_rumble);
288 config.time_rate = input.tag.get_property("TIME_RATE", config.time_rate);
289 config.space_rumble = input.tag.get_property("SPACE_RUMBLE", config.space_rumble);
290 config.space_rate = input.tag.get_property("SPACE_RATE", config.space_rate);
291 config.sequence = input.tag.get_property("SEQUENCE", config.sequence);
296 void Rumbler::update_gui()
298 if( !thread ) return;
299 if( !load_configuration() ) return;
300 RumblerWindow *window = (RumblerWindow*)thread->window;
301 window->lock_window("Rumbler::update_gui");
302 window->time_rumble->update(config.time_rumble);
303 window->time_rate->update(config.time_rate);
304 window->space_rumble->update(config.space_rumble);
305 window->space_rate->update(config.space_rate);
306 window->seq->update((float)config.sequence);
307 window->unlock_window();