Condense the xml-cleanup into a short feature-branch
[cinelerra_cv/mob.git] / plugins / loopvideo / loopvideo.C
blob2986e3d23b23523cbacee7bc8e9b386eb1ac143e
1 #include "bcdisplayinfo.h"
2 #include "clip.h"
3 #include "bchash.h"
4 #include "filexml.h"
5 #include "guicast.h"
6 #include "language.h"
7 #include "pluginvclient.h"
8 #include "transportque.h"
10 #include <string.h>
12 class LoopVideo;
14 class LoopVideoConfig
16 public:
17         LoopVideoConfig();
18         int64_t frames;
22 class LoopVideoFrames : public BC_TextBox
24 public:
25         LoopVideoFrames(LoopVideo *plugin,
26                 int x,
27                 int y);
28         int handle_event();
29         LoopVideo *plugin;
32 class LoopVideoWindow : public BC_Window
34 public:
35         LoopVideoWindow(LoopVideo *plugin, int x, int y);
36         ~LoopVideoWindow();
37         void create_objects();
38         int close_event();
39         LoopVideo *plugin;
40         LoopVideoFrames *frames;
43 PLUGIN_THREAD_HEADER(LoopVideo, LoopVideoThread, LoopVideoWindow)
45 class LoopVideo : public PluginVClient
47 public:
48         LoopVideo(PluginServer *server);
49         ~LoopVideo();
51         PLUGIN_CLASS_MEMBERS(LoopVideoConfig, LoopVideoThread)
53         int load_defaults();
54         int save_defaults();
55         void save_data(KeyFrame *keyframe);
56         void read_data(KeyFrame *keyframe);
57         void update_gui();
58         int is_realtime();
59         int is_synthesis();
60         int process_buffer(VFrame *frame,
61                 int64_t start_position,
62                 double frame_rate);
71 REGISTER_PLUGIN(LoopVideo);
75 LoopVideoConfig::LoopVideoConfig()
77         frames = 30;
84 LoopVideoWindow::LoopVideoWindow(LoopVideo *plugin, int x, int y)
85  : BC_Window(plugin->gui_string, 
86         x, 
87         y, 
88         210, 
89         160, 
90         200, 
91         160, 
92         0, 
93         0,
94         1)
96         this->plugin = plugin;
99 LoopVideoWindow::~LoopVideoWindow()
103 void LoopVideoWindow::create_objects()
105         int x = 10, y = 10;
107         add_subwindow(new BC_Title(x, y, _("Frames to loop:")));
108         y += 20;
109         add_subwindow(frames = new LoopVideoFrames(plugin, 
110                 x, 
111                 y));
112         show_window();
113         flush();
116 WINDOW_CLOSE_EVENT(LoopVideoWindow)
119 PLUGIN_THREAD_OBJECT(LoopVideo, LoopVideoThread, LoopVideoWindow)
126 LoopVideoFrames::LoopVideoFrames(LoopVideo *plugin, 
127         int x, 
128         int y)
129  : BC_TextBox(x, 
130         y, 
131         100,
132         1,
133         plugin->config.frames)
135         this->plugin = plugin;
138 int LoopVideoFrames::handle_event()
140         plugin->config.frames = atol(get_text());
141         plugin->config.frames = MAX(1, plugin->config.frames);
142         plugin->send_configure_change();
143         return 1;
154 LoopVideo::LoopVideo(PluginServer *server)
155  : PluginVClient(server)
157         PLUGIN_CONSTRUCTOR_MACRO
161 LoopVideo::~LoopVideo()
163         PLUGIN_DESTRUCTOR_MACRO
166 char* LoopVideo::plugin_title() { return N_("Loop video"); }
167 int LoopVideo::is_realtime() { return 1; }
168 int LoopVideo::is_synthesis() { return 1; }
170 #include "picon_png.h"
171 NEW_PICON_MACRO(LoopVideo)
173 SHOW_GUI_MACRO(LoopVideo, LoopVideoThread)
175 RAISE_WINDOW_MACRO(LoopVideo)
177 SET_STRING_MACRO(LoopVideo);
180 int LoopVideo::process_buffer(VFrame *frame,
181                 int64_t start_position,
182                 double frame_rate)
184         int64_t current_loop_position;
186 // Truncate to next keyframe
187         if(get_direction() == PLAY_FORWARD)
188         {
189 // Get start of current loop
190                 KeyFrame *prev_keyframe = get_prev_keyframe(start_position);
191                 int64_t prev_position = edl_to_local(prev_keyframe->position);
192                 if(prev_position == 0)
193                         prev_position = get_source_start();
194                 read_data(prev_keyframe);
196 // Get start of fragment in current loop
197                 current_loop_position = prev_position +
198                         ((start_position - prev_position) % 
199                                 config.frames);
200                 while(current_loop_position < prev_position) current_loop_position += config.frames;
201                 while(current_loop_position >= prev_position + config.frames) current_loop_position -= config.frames;
202         }
203         else
204         {
205                 KeyFrame *prev_keyframe = get_next_keyframe(start_position);
206                 int64_t prev_position = edl_to_local(prev_keyframe->position);
207                 if(prev_position == 0)
208                         prev_position = get_source_start() + get_total_len();
209                 read_data(prev_keyframe);
211                 current_loop_position = prev_position - 
212                         ((prev_position - start_position) %
213                                   config.frames);
214                 while(current_loop_position <= prev_position - config.frames) current_loop_position += config.frames;
215                 while(current_loop_position > prev_position) current_loop_position -= config.frames;
216         }
219 // printf("LoopVideo::process_buffer 100 %lld %lld %lld %d\n", 
220 // current_position, current_loop_position, current_loop_end, fragment_size);
221         read_frame(frame,
222                 0,
223                 current_loop_position,
224                 frame_rate);
226         return 0;
232 int LoopVideo::load_configuration()
234         KeyFrame *prev_keyframe;
235         int64_t old_frames = config.frames;
236         prev_keyframe = get_prev_keyframe(get_source_position());
237         read_data(prev_keyframe);
238         config.frames = MAX(config.frames, 1);
239         return old_frames != config.frames;
242 int LoopVideo::load_defaults()
244         char directory[BCTEXTLEN];
245 // set the default directory
246         sprintf(directory, "%sloopaudio.rc", BCASTDIR);
248 // load the defaults
249         defaults = new BC_Hash(directory);
250         defaults->load();
252         config.frames = defaults->get("FRAMES", config.frames);
253         return 0;
256 int LoopVideo::save_defaults()
258         defaults->update("FRAMES", config.frames);
259         defaults->save();
260         return 0;
263 void LoopVideo::save_data(KeyFrame *keyframe)
265         FileXML output;
267 // cause data to be stored directly in text
268         output.set_shared_string(keyframe->data, MESSAGESIZE);
269         output.tag.set_title("LOOPVIDEO");
270         output.tag.set_property("FRAMES", config.frames);
271         output.append_tag();
272         output.tag.set_title("/LOOPVIDEO");
273         output.append_tag();
274         output.terminate_string();
277 void LoopVideo::read_data(KeyFrame *keyframe)
279         FileXML input;
281         input.set_shared_string(keyframe->data, strlen(keyframe->data));
283         int result = 0;
285         while(!input.read_tag())
286         {
287                 if(input.tag.title_is("LOOPVIDEO"))
288                 {
289                         config.frames = input.tag.get_property("FRAMES", config.frames);
290                 }
291         }
294 void LoopVideo::update_gui()
296         if(thread)
297         {
298                 load_configuration();
299                 thread->window->lock_window();
300                 thread->window->frames->update(config.frames);
301                 thread->window->unlock_window();
302         }