4 * Copyright (C) 2010 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
23 #include "bcsignals.h"
28 #include "keyframes.h"
29 #include "transportque.inc"
39 xbuf = new XMLBuffer();
42 KeyFrame::KeyFrame(const char *buf, long len)
45 xbuf = new XMLBuffer(buf, len, 0);
48 KeyFrame::KeyFrame(EDL *edl, KeyFrames *autos)
49 : Auto(edl, (Autos*)autos)
51 xbuf = new XMLBuffer();
59 void KeyFrame::load(FileXML *file)
61 //printf("KeyFrame::load 1\n");
62 // Shouldn't be necessary
63 // position = file->tag.get_property((char*)"POSITION", position);
64 //printf("KeyFrame::load 1\n");
65 xbuf->iseek(0); xbuf->oseek(0);
66 file->read_data_until((char*)"/KEYFRAME", xbuf, 1);
69 void KeyFrame::copy(int64_t start, int64_t end, FileXML *file, int default_auto)
71 file->tag.set_title((char*)"KEYFRAME");
73 file->tag.set_property((char*)"POSITION", 0);
75 file->tag.set_property((char*)"POSITION", position - start);
76 // default_auto converts a default auto to a normal auto
77 if(is_default && !default_auto)
78 file->tag.set_property((char*)"DEFAULT", 1);
80 // Can't put newlines in because these would be reimported and resaved along
82 char *data = (char*)xbuf->cstr();
83 file->append_data(data, strlen(data));
85 file->tag.set_title((char*)"/KEYFRAME");
87 file->append_newline();
91 void KeyFrame::copy_from(Auto *that)
93 copy_from((KeyFrame*)that);
96 void KeyFrame::copy_data(KeyFrame *src)
98 xbuf->copy_from(src->xbuf);
101 void KeyFrame::copy_from(KeyFrame *that)
103 Auto::copy_from(that);
105 position = that->position;
108 int KeyFrame::identical(KeyFrame *src)
110 return !strcasecmp(xbuf->cstr(), src->xbuf->cstr());
113 void KeyFrame::get_contents(BC_Hash *ptr, char **text, char **extra)
116 input.set_shared_input(xbuf);
117 char *this_text = 0, *this_extra = 0;
118 if( !input.read_tag() ) {
119 for( int i=0; i<input.tag.properties.size(); ++i ) {
120 const char *key = input.tag.get_property_text(i);
121 const char *value = input.tag.get_property(key);
122 ptr->update(key, value);
125 // Read any text after tag
126 this_text = input.read_text();
127 (*text) = cstrdup(this_text);
129 // Read remaining data
130 this_extra = input.get_data();
131 (*extra) = cstrdup(this_extra);
135 void KeyFrame::update_parameter(BC_Hash *params,
136 const char *text, const char *extra)
139 char *this_text = 0, *this_extra = 0;
140 get_contents(&this_params, &this_text, &this_extra);
142 FileXML input, output;
143 input.set_shared_input(xbuf);
144 if( !input.read_tag() ) {
146 output.tag.set_title(input.tag.get_title());
148 // Get each parameter from this keyframe
149 for( int i=0; i<this_params.size(); ++i ) {
150 const char *key = this_params.get_key(i);
151 const char *value = this_params.get_value(i);
152 // Get new value from the params argument
154 for( int j=0; j<params->size(); ++j ) {
155 if( !strcmp(params->get_key(j), key) ) {
156 value = params->get_value(j);
162 output.tag.set_property(key, value);
165 // Get each parameter from params argument
167 for( int i=0; i<params->size(); ++i ) {
168 const char *key = params->get_key(i);
170 for( int j=0; j<this_params.size(); ++j ) {
171 if( !strcmp(this_params.get_key(j), key) ) {
177 // If it wasn't found in output, set new parameter in output.
179 output.tag.set_property(key, params->get_value(i));
185 // Write anonymous text & duplicate the rest
186 output.append_data(text ? text : this_text);
187 output.append_data(extra ? extra : this_extra);
188 output.terminate_string();
189 // Move output to input
191 xbuf->write(output.string(), output.length());
195 delete [] this_extra;
199 void KeyFrame::get_diff(KeyFrame *src,
200 BC_Hash **params, char **text, char **extra)
202 BC_Hash this_params; char *this_text = 0, *this_extra = 0;
203 BC_Hash src_params; char *src_text = 0, *src_extra = 0;
205 get_contents(&this_params, &this_text, &this_extra);
206 src->get_contents(&src_params, &src_text, &src_extra);
208 // Capture changed parameters
209 char this_value[BCTEXTLEN];
210 int m = MIN(this_params.size(), src_params.size());
211 for( int i=0; i<m; ++i ) {
212 const char *src_key = src_params.get_key(i);
213 const char *src_value = src_params.get_value(i);
215 this_params.get(src_key, this_value);
216 // Capture values which differ
217 if( strcmp(src_value, this_value) ) {
218 if(!(*params)) (*params) = new BC_Hash;
219 (*params)->update(src_key, src_value);
224 // Capture text which differs
225 if( !this_text || strcmp(this_text, src_text) )
226 (*text) = cstrdup(src_text);
228 if( !this_extra || strcmp(this_extra, src_extra) )
229 (*extra) = cstrdup(src_extra);
232 delete [] this_extra;
237 void KeyFrame::span_keyframes(int64_t start, int64_t end)
240 char *text = 0, *extra = 0;
241 // The first one determines the changed parameters since it is the one displayed
242 KeyFrames *keyframes = (KeyFrames *)autos;
243 KeyFrame *current = keyframes->get_prev_keyframe(start, PLAY_FORWARD);
244 current->get_diff(this, ¶ms, &text, &extra);
245 // Always update the first one
246 current->update_parameter(params, text, extra);
248 // Replace changed parameter in all selected keyframes.
249 for( current = (KeyFrame*)NEXT; current; current = (KeyFrame*)NEXT ) {
250 if( current->position >= end ) break;
251 current->update_parameter(params, text, extra);
258 int KeyFrame::operator==(Auto &that)
260 return identical((KeyFrame*)&that);
263 int KeyFrame::operator==(KeyFrame &that)
265 return identical(&that);
268 char *KeyFrame::get_data(int64_t sz)
270 if( sz >= 0 ) xbuf->demand(sz);
274 void KeyFrame::set_data(char *data)
277 xbuf->write(data, strlen(data));
280 void KeyFrame::dump(FILE *fp)
282 fprintf(fp," position: %jd\n", position);
283 fprintf(fp," data: %s\n", xbuf->cstr());