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