initial commit
[goodguy/history.git] / cinelerra-5.0 / cinelerra / keyframe.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2010 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 "bcsignals.h"
24 #include "clip.h"
25 #include "cstrdup.h"
26 #include "filexml.h"
27 #include "format.inc"
28 #include "keyframe.h"
29
30 #include <stdio.h>
31 #include <string.h>
32
33
34
35 KeyFrame::KeyFrame()
36  : Auto()
37 {
38         data[0] = 0;
39 }
40
41 KeyFrame::KeyFrame(EDL *edl, KeyFrames *autos)
42  : Auto(edl, (Autos*)autos)
43 {
44         data[0] = 0;
45 }
46
47 KeyFrame::~KeyFrame()
48 {
49 }
50
51 void KeyFrame::load(FileXML *file)
52 {
53 //printf("KeyFrame::load 1\n");
54 // Shouldn't be necessary
55 //      position = file->tag.get_property((char*)"POSITION", position);
56 //printf("KeyFrame::load 1\n");
57
58         int len = file->read_data_until((char*)"/KEYFRAME", data, MESSAGESIZE-1);
59         data[len] = 0;
60 //printf("KeyFrame::load 2 data=\n%s\nend of data\n", data);
61 }
62
63 void KeyFrame::copy(int64_t start, int64_t end, FileXML *file, int default_auto)
64 {
65 //printf("KeyFrame::copy 1 %d\n%s\n", position - start, data);
66         file->tag.set_title((char*)"KEYFRAME");
67         if(default_auto)
68                 file->tag.set_property((char*)"POSITION", 0);
69         else
70                 file->tag.set_property((char*)"POSITION", position - start);
71 // default_auto converts a default auto to a normal auto
72         if(is_default && !default_auto)
73                 file->tag.set_property((char*)"DEFAULT", 1);
74         file->append_tag();
75 // Can't put newlines in because these would be reimported and resaved along
76 // with new newlines.
77 //      file->append_newline();
78
79         file->append_data(data, strlen(data));
80 //      file->append_newline();
81
82         file->tag.set_title((char*)"/KEYFRAME");
83         file->append_tag();
84         file->append_newline();
85 }
86
87
88 void KeyFrame::copy_from(Auto *that)
89 {
90         copy_from((KeyFrame*)that);
91 }
92
93 void KeyFrame::copy_from(KeyFrame *that)
94 {
95         Auto::copy_from(that);
96         KeyFrame *keyframe = (KeyFrame*)that;
97         strcpy(data, keyframe->data);
98         position = keyframe->position;
99 }
100
101 void KeyFrame::copy_data(KeyFrame *src)
102 {
103         strcpy(data, src->data);
104 }
105
106 int KeyFrame::identical(KeyFrame *src)
107 {
108         return !strcasecmp(src->data, data);
109 }
110
111
112 void KeyFrame::get_contents(BC_Hash *ptr, char **text, char **extra)
113 {
114         FileXML input;
115         input.set_shared_input(data, strlen(data));
116         int result = 0;
117         char *this_text = 0;
118         char *this_extra = 0;
119         while(!result)
120         {
121                 result = input.read_tag();
122                 if(!result)
123                 {
124                         for(int i = 0; i < input.tag.properties.size(); i++)
125                         {
126                                 const char *key = input.tag.get_property_text(i);
127                                 const char *value = input.tag.get_property(key);
128                                 ptr->update(key, value);
129                         }
130
131 // Read any text after tag
132                         this_text = input.read_text();
133                         (*text) = cstrdup(this_text);
134
135 // Read remaining data
136                         this_extra = input.get_data();
137                         (*extra) = cstrdup(this_extra);
138                         break;
139                 }
140         }
141 }
142
143 void KeyFrame::update_parameter(BC_Hash *params, 
144         const char *text,
145         char *extra)
146 {
147         FileXML output;
148         FileXML input;
149         input.set_shared_input(get_data(), strlen(get_data()));
150         int result = 0;
151         BC_Hash this_params;
152         char *this_text = 0;
153         char *this_extra = 0;
154         int got_it = 0;
155
156 // printf("KeyFrame::update_parameter %d %p %p %p \n", 
157 // __LINE__,
158 // params,
159 // text,
160 // extra);
161
162
163         get_contents(&this_params, &this_text, &this_extra);
164
165
166 // printf("KeyFrame::update_parameter %d params=%p\n", __LINE__, params);
167 // if(params) params->dump();
168 // printf("KeyFrame::update_parameter %d\n", __LINE__);
169 // this_params.dump();
170
171 // Get first tag
172         while(!result)
173         {
174                 result = input.read_tag();
175                 if(!result)
176                 {
177 // Replicate first tag
178                         output.tag.set_title(input.tag.get_title());
179
180 // Get each parameter from this keyframe
181                         for(int i = 0; i < this_params.size(); i++)
182                         {
183                                 const char *key = this_params.get_key(i);
184                                 const char *value = this_params.get_value(i);
185
186 // Get new value from the params argument
187                                 got_it = 1;
188                                 if(params)
189                                 {
190                                         got_it = 0;
191                                         for(int j = 0; j < params->size(); j++)
192                                         {
193                                                 if(!strcmp(params->get_key(j), key))
194                                                 {
195                                                         got_it = 1;
196                                                         value = params->get_value(j);
197                                                         break;
198                                                 }
199                                         }
200                                 }
201
202 // Set parameter in output.
203                                 output.tag.set_property(key, value);
204                         }
205
206 // Get each parameter from params argument
207                         if(params)
208                         {
209                                 for(int i = 0; i < params->size(); i++)
210                                 {
211                                         const char *key = params->get_key(i);
212 //printf("KeyFrame::update_parameter %d %s\n", __LINE__, key);
213                                         
214                                         got_it = 0;
215                                         for(int j = 0; j < this_params.size(); j++)
216                                         {
217                                                 if(!strcmp(this_params.get_key(j), key))
218                                                 {
219                                                         got_it = 1;
220                                                         break;
221                                                 }
222                                         }
223 //printf("KeyFrame::update_parameter %d %s\n", __LINE__, key);
224
225 // If it wasn't found in output, set new parameter in output.
226                                         if(!got_it)
227                                         {
228                                                 output.tag.set_property(key, params->get_value(i));
229 //printf("KeyFrame::update_parameter %d %s\n", __LINE__, key);
230                                         }
231                                 }
232                         }
233
234
235
236 // Append parameters to output
237                         output.append_tag();
238
239 // Write anonymous text & duplicate the rest
240                         if(text)
241                         {
242                                 output.append_text(text);
243                         }
244                         else
245                         {
246                                 output.append_text(this_text);
247                         }
248
249 // Append remaining previous data
250                         if(extra)
251                         {
252                                 output.append_text(extra);
253                         }
254                         else
255                         {
256                                 output.append_text(this_extra);
257                         }
258
259 // Move output to input
260                         output.terminate_string();
261                         strcpy(this->data, output.string());
262                         break;
263                 }
264         }
265
266         delete [] this_text;
267         delete [] this_extra;
268 }
269
270
271 void KeyFrame::get_diff(KeyFrame *src, 
272         BC_Hash **params, 
273         char **text, 
274         char **extra)
275 {
276         const int debug = 0;
277         FileXML input;
278         input.set_shared_input(data, strlen(data));
279         BC_Hash this_params;
280         char *this_text = 0;
281         char *this_extra = 0;
282         BC_Hash src_parameters;
283         char *src_text = 0;
284         char *src_extra = 0;
285
286         get_contents(&this_params, &this_text, &this_extra);
287         src->get_contents(&src_parameters, &src_text, &src_extra);
288
289 if(debug) printf("KeyFrame::get_diff %d %d %d\n", 
290 __LINE__, 
291 this_params.size(), 
292 src_parameters.size());
293
294 // Capture changed parameters
295         char this_value[BCTEXTLEN];
296         for(int i = 0; i < MIN(this_params.size(), src_parameters.size()); i++)
297         {
298                 const char *src_key = src_parameters.get_key(i);
299                 const char *src_value = src_parameters.get_value(i);
300                 this_value[0] = 0;
301                 this_params.get(src_key, this_value);
302 if(debug) printf("KeyFrame::get_diff %d %s %s %s\n", 
303 __LINE__, 
304 src_key,
305 src_value, 
306 this_value);
307 // Capture values which differ
308                 if(strcmp(src_value, this_value))
309                 {
310                         if(!(*params)) (*params) = new BC_Hash;
311                         (*params)->update(src_key, src_value);
312                 }
313         }
314
315
316 // Capture text which differs
317         if( !this_text || strcmp(this_text, src_text))
318                 (*text) = cstrdup(src_text);
319
320         if( !this_extra || strcmp(this_extra, src_extra))
321                 (*extra) = cstrdup(src_extra);
322
323         
324         delete [] this_text;
325         delete [] this_extra;
326         delete [] src_text;
327         delete [] src_extra;
328 }
329
330 int KeyFrame::operator==(Auto &that)
331 {
332         return identical((KeyFrame*)&that);
333 }
334
335 int KeyFrame::operator==(KeyFrame &that)
336 {
337         return identical(&that);
338 }
339
340 char* KeyFrame::get_data()
341 {
342         return data;
343 }
344
345 void KeyFrame::set_data(char *data)
346 {
347         strcpy(this->data, data);
348 }
349
350
351 void KeyFrame::dump(FILE *fp)
352 {
353         fprintf(fp,"     position: " _LD "\n", position);
354         fprintf(fp,"     data: %s\n", data);
355 }