dynamic keyframes, textbox rework, andrea ffmpeg.opts, perpetual chkpt undo, lv2...
[goodguy/history.git] / cinelerra-5.1 / plugins / zoom / zoom.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #include "bchash.h"
23 #include "clip.h"
24 #include "filexml.h"
25 #include "zoom.h"
26 #include "edl.inc"
27 #include "overlayframe.h"
28 #include "language.h"
29 #include "theme.h"
30 #include "vframe.h"
31
32 #include <stdint.h>
33 #include <string.h>
34
35 REGISTER_PLUGIN(ZoomMain)
36
37
38
39 #define MIN_MAGNIFICATION 1.0
40 #define MAX_MAGNIFICATION 100.0
41
42
43 ZoomLimit::ZoomLimit(ZoomMain *plugin,
44         ZoomWindow *window,
45         float *output,
46         int x,
47         int y,
48         int w)
49  : BC_TumbleTextBox(window,
50         *output,
51         (float)MIN_MAGNIFICATION,
52         (float)MAX_MAGNIFICATION,
53         x,
54         y,
55         w)
56 {
57         this->output = output;
58         this->plugin = plugin;
59 }
60
61 int ZoomLimit::handle_event()
62 {
63         *output = atof(get_text());
64         plugin->send_configure_change();
65         return 1;
66 }
67
68
69
70
71
72
73
74
75 ZoomWindow::ZoomWindow(ZoomMain *plugin)
76  : PluginClientWindow(plugin,
77         250,
78         125,
79         250,
80         125,
81         0)
82 {
83         this->plugin = plugin;
84 }
85
86 ZoomWindow::~ZoomWindow()
87 {
88 }
89
90
91
92 void ZoomWindow::create_objects()
93 {
94         BC_Title *title = 0;
95         lock_window("ZoomWindow::create_objects");
96         int widget_border = plugin->get_theme()->widget_border;
97         int window_border = plugin->get_theme()->window_border;
98         int x = window_border, y = window_border;
99
100         add_subwindow(title = new BC_Title(x, y, _("X Magnification:")));
101         y += title->get_h() + widget_border;
102         limit_x = new ZoomLimit(plugin,
103                 this,
104                 &plugin->max_magnification_x,
105                 x,
106                 y,
107                 get_w() - window_border * 2 - widget_border - BC_Tumbler::calculate_w());
108         limit_x->create_objects();
109         y += limit_x->get_h() + widget_border;
110         add_subwindow(title = new BC_Title(x, y, _("Y Magnification:")));
111         y += title->get_h() + widget_border;
112         limit_y = new ZoomLimit(plugin,
113                 this,
114                 &plugin->max_magnification_y,
115                 x,
116                 y,
117                 get_w() - window_border * 2 - widget_border - BC_Tumbler::calculate_w());
118         limit_y->create_objects();
119
120         show_window();
121         unlock_window();
122 }
123
124
125
126
127
128
129
130
131
132 ZoomMain::ZoomMain(PluginServer *server)
133  : PluginVClient(server)
134 {
135         overlayer = 0;
136         temp = 0;
137         max_magnification_x = 10;
138         max_magnification_y = 10;
139 }
140
141 ZoomMain::~ZoomMain()
142 {
143         delete overlayer;
144         delete temp;
145 }
146
147 const char* ZoomMain::plugin_title() { return N_("Zoom"); }
148 int ZoomMain::is_video() { return 1; }
149 int ZoomMain::is_transition() { return 1; }
150 int ZoomMain::uses_gui() { return 1; }
151
152
153
154
155
156 void ZoomMain::save_data(KeyFrame *keyframe)
157 {
158         FileXML output;
159         output.set_shared_output(keyframe->xbuf);
160         output.tag.set_title("ZOOMTRANSITION");
161         output.tag.set_property("MAGNIFICATION_X", max_magnification_x);
162         output.tag.set_property("MAGNIFICATION_Y", max_magnification_y);
163         output.append_tag();
164         output.tag.set_title("/ZOOMTRANSITION");
165         output.append_tag();
166         output.terminate_string();
167 }
168
169 void ZoomMain::read_data(KeyFrame *keyframe)
170 {
171         FileXML input;
172
173         input.set_shared_input(keyframe->xbuf);
174
175         while(!input.read_tag())
176         {
177                 if(input.tag.title_is("ZOOMTRANSITION"))
178                 {
179                         max_magnification_x = input.tag.get_property("MAGNIFICATION_X", max_magnification_x);
180                         max_magnification_y = input.tag.get_property("MAGNIFICATION_Y", max_magnification_y);
181                 }
182         }
183 }
184
185 int ZoomMain::load_configuration()
186 {
187         read_data(get_prev_keyframe(get_source_position()));
188         return 1;
189 }
190
191
192 NEW_WINDOW_MACRO(ZoomMain, ZoomWindow);
193
194 int ZoomMain::process_realtime(VFrame *incoming, VFrame *outgoing)
195 {
196         int half = PluginClient::get_total_len() / 2;
197         int position = half - labs(PluginClient::get_source_position() - half);
198         float fraction = (float)position / half;
199         is_before = PluginClient::get_source_position() < half;
200         int w = incoming->get_w();
201         int h = incoming->get_h();
202
203         load_configuration();
204         this->max_magnification_x = MAX(MIN_MAGNIFICATION, this->max_magnification_x);
205         this->max_magnification_y = MAX(MIN_MAGNIFICATION, this->max_magnification_y);
206         CLAMP(this->max_magnification_x, MIN_MAGNIFICATION, MAX_MAGNIFICATION);
207         CLAMP(this->max_magnification_y, MIN_MAGNIFICATION, MAX_MAGNIFICATION);
208
209         float min_magnification_x = MIN(1.0, this->max_magnification_x);
210         float max_magnification_x = MAX(1.0, this->max_magnification_x);
211         float min_magnification_y = MIN(1.0, this->max_magnification_y);
212         float max_magnification_y = MAX(1.0, this->max_magnification_y);
213
214         if(fraction > 0)
215         {
216                 in_w = (float)w / ((float)fraction *
217                         (max_magnification_x - min_magnification_x) +
218                         min_magnification_x);
219                 in_x = (float)w / 2 - in_w / 2;
220                 in_h = (float)h / ((float)fraction *
221                         (max_magnification_y - min_magnification_y) +
222                         min_magnification_y);
223                 in_y = (float)h / 2 - in_h / 2;
224         }
225         else
226         {
227                 in_w = w;
228                 in_h = h;
229                 in_x = 0;
230                 in_y = 0;
231         }
232
233 // printf("ZoomMain::process_realtime %f %f %f %f\n",
234 // fraction,
235 // ((float)fraction *
236 // (max_magnification_x - min_magnification_x) +
237 // min_magnification_x),
238 // in_x,
239 // in_y,
240 // in_x + in_w,
241 // in_y + in_h);
242
243
244 // Use hardware
245         if(get_use_opengl())
246         {
247                 run_opengl();
248                 return 0;
249         }
250
251 // Use software
252         if(!overlayer) overlayer = new OverlayFrame(get_project_smp() + 1);
253
254         if(is_before)
255         {
256                 if(!temp) temp = new VFrame(outgoing->get_w(), outgoing->get_h(),
257                         outgoing->get_color_model(), 0);
258                 temp->clear_frame();
259                 overlayer->overlay(temp, outgoing,
260                         in_x, in_y, in_x + in_w, in_y + in_h,
261                         0, 0, temp->get_w(), temp->get_h(),
262                         1.0, TRANSFER_REPLACE, CUBIC_LINEAR);
263                 outgoing->copy_from(temp);
264         }
265         else
266         {
267                 outgoing->clear_frame();
268                 overlayer->overlay(outgoing, incoming,
269                         in_x, in_y, in_x + in_w, in_y + in_h,
270                         0, 0, outgoing->get_w(), outgoing->get_h(),
271                         1.0, TRANSFER_REPLACE, CUBIC_LINEAR);
272         }
273
274         return 0;
275 }
276
277
278 int ZoomMain::handle_opengl()
279 {
280 #ifdef HAVE_GL
281
282         if(is_before)
283         {
284 // Read images from RAM
285                 get_output()->to_texture();
286
287 // Create output pbuffer
288                 get_output()->enable_opengl();
289                 VFrame::init_screen(get_output()->get_w(), get_output()->get_h());
290
291 // Enable output texture
292                 get_output()->bind_texture(0);
293 // Draw output texture
294 // printf("ZoomMain::handle_opengl %f %f %f %f\n",
295 // in_x,
296 // in_y,
297 // in_x + in_w,
298 // in_y + in_h);
299                 get_output()->draw_texture(in_x,
300                         in_y,
301                         in_x + in_w,
302                         in_y + in_h,
303                         0,
304                         0,
305                         get_output()->get_w(),
306                         get_output()->get_h());
307         }
308         else
309         {
310 // Read images from RAM
311                 get_input()->to_texture();
312
313 // Create output pbuffer
314                 get_output()->enable_opengl();
315                 VFrame::init_screen(get_output()->get_w(), get_output()->get_h());
316
317 // Enable output texture
318                 get_input()->bind_texture(0);
319 // Draw input texture on output pbuffer
320                 get_output()->draw_texture(in_x,
321                         in_y,
322                         in_x + in_w,
323                         in_y + in_h,
324                         0,
325                         0,
326                         get_output()->get_w(),
327                         get_output()->get_h());
328         }
329
330         get_output()->set_opengl_state(VFrame::SCREEN);
331
332         return 1;
333
334 #endif
335
336         return 0;
337 }
338
339