+
+/*
+ * CINELERRA
+ * Copyright (C) 2010 Adam Williams <broadcast at earthling dot net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "bchash.h"
+#include "bcsignals.h"
+#include "clip.h"
+#include "cstrdup.h"
+#include "filexml.h"
+#include "keyframe.h"
+
+#include <stdio.h>
+#include <string.h>
+
+
+
+KeyFrame::KeyFrame()
+ : Auto()
+{
+ data[0] = 0;
+}
+
+KeyFrame::KeyFrame(EDL *edl, KeyFrames *autos)
+ : Auto(edl, (Autos*)autos)
+{
+ data[0] = 0;
+}
+
+KeyFrame::~KeyFrame()
+{
+}
+
+void KeyFrame::load(FileXML *file)
+{
+//printf("KeyFrame::load 1\n");
+// Shouldn't be necessary
+// position = file->tag.get_property((char*)"POSITION", position);
+//printf("KeyFrame::load 1\n");
+
+ int len = file->read_data_until((char*)"/KEYFRAME", data, MESSAGESIZE-1);
+ data[len] = 0;
+//printf("KeyFrame::load 2 data=\n%s\nend of data\n", data);
+}
+
+void KeyFrame::copy(int64_t start, int64_t end, FileXML *file, int default_auto)
+{
+//printf("KeyFrame::copy 1 %d\n%s\n", position - start, data);
+ file->tag.set_title((char*)"KEYFRAME");
+ if(default_auto)
+ file->tag.set_property((char*)"POSITION", 0);
+ else
+ file->tag.set_property((char*)"POSITION", position - start);
+// default_auto converts a default auto to a normal auto
+ if(is_default && !default_auto)
+ file->tag.set_property((char*)"DEFAULT", 1);
+ file->append_tag();
+// Can't put newlines in because these would be reimported and resaved along
+// with new newlines.
+// file->append_newline();
+
+ file->append_data(data, strlen(data));
+// file->append_newline();
+
+ file->tag.set_title((char*)"/KEYFRAME");
+ file->append_tag();
+ file->append_newline();
+}
+
+
+void KeyFrame::copy_from(Auto *that)
+{
+ copy_from((KeyFrame*)that);
+}
+
+void KeyFrame::copy_from(KeyFrame *that)
+{
+ Auto::copy_from(that);
+ KeyFrame *keyframe = (KeyFrame*)that;
+ strcpy(data, keyframe->data);
+ position = keyframe->position;
+}
+
+void KeyFrame::copy_data(KeyFrame *src)
+{
+ strcpy(data, src->data);
+}
+
+int KeyFrame::identical(KeyFrame *src)
+{
+ return !strcasecmp(src->data, data);
+}
+
+void KeyFrame::get_contents(BC_Hash *ptr, char **text, char **extra)
+{
+ FileXML input;
+ input.set_shared_input(data, strlen(data));
+ int result = 0;
+ char *this_text = 0;
+ char *this_extra = 0;
+ while(!result)
+ {
+ result = input.read_tag();
+ if(!result)
+ {
+ for(int i = 0; i < input.tag.properties.size(); i++)
+ {
+ const char *key = input.tag.get_property_text(i);
+ const char *value = input.tag.get_property(key);
+ ptr->update(key, value);
+ }
+
+// Read any text after tag
+ this_text = input.read_text();
+ (*text) = cstrdup(this_text);
+
+// Read remaining data
+ this_extra = input.get_data();
+ (*extra) = cstrdup(this_extra);
+ break;
+ }
+ }
+}
+
+void KeyFrame::update_parameter(BC_Hash *params,
+ const char *text,
+ char *extra)
+{
+ FileXML output;
+ FileXML input;
+ input.set_shared_input(get_data(), strlen(get_data()));
+ int result = 0;
+ BC_Hash this_params;
+ char *this_text = 0;
+ char *this_extra = 0;
+ int got_it = 0;
+
+// printf("KeyFrame::update_parameter %d %p %p %p \n",
+// __LINE__,
+// params,
+// text,
+// extra);
+
+
+ get_contents(&this_params, &this_text, &this_extra);
+
+
+// printf("KeyFrame::update_parameter %d params=%p\n", __LINE__, params);
+// if(params) params->dump();
+// printf("KeyFrame::update_parameter %d\n", __LINE__);
+// this_params.dump();
+
+// Get first tag
+ while(!result)
+ {
+ result = input.read_tag();
+ if(!result)
+ {
+// Replicate first tag
+ output.tag.set_title(input.tag.get_title());
+
+// Get each parameter from this keyframe
+ for(int i = 0; i < this_params.size(); i++)
+ {
+ const char *key = this_params.get_key(i);
+ const char *value = this_params.get_value(i);
+
+// Get new value from the params argument
+ got_it = 1;
+ if(params)
+ {
+ got_it = 0;
+ for(int j = 0; j < params->size(); j++)
+ {
+ if(!strcmp(params->get_key(j), key))
+ {
+ got_it = 1;
+ value = params->get_value(j);
+ break;
+ }
+ }
+ }
+
+// Set parameter in output.
+ output.tag.set_property(key, value);
+ }
+
+// Get each parameter from params argument
+ if(params)
+ {
+ for(int i = 0; i < params->size(); i++)
+ {
+ const char *key = params->get_key(i);
+//printf("KeyFrame::update_parameter %d %s\n", __LINE__, key);
+
+ got_it = 0;
+ for(int j = 0; j < this_params.size(); j++)
+ {
+ if(!strcmp(this_params.get_key(j), key))
+ {
+ got_it = 1;
+ break;
+ }
+ }
+//printf("KeyFrame::update_parameter %d %s\n", __LINE__, key);
+
+// If it wasn't found in output, set new parameter in output.
+ if(!got_it)
+ {
+ output.tag.set_property(key, params->get_value(i));
+//printf("KeyFrame::update_parameter %d %s\n", __LINE__, key);
+ }
+ }
+ }
+
+// Append parameters to output
+ output.append_tag();
+// Write anonymous text & duplicate the rest
+ output.append_text(text ? text : this_text);
+// Append remaining previous data
+ output.append_data(extra ? extra : this_extra);
+// Move output to input
+ output.terminate_string();
+ strcpy(this->data, output.string());
+ break;
+ }
+ }
+
+ delete [] this_text;
+ delete [] this_extra;
+}
+
+
+void KeyFrame::get_diff(KeyFrame *src,
+ BC_Hash **params,
+ char **text,
+ char **extra)
+{
+ const int debug = 0;
+ FileXML input;
+ input.set_shared_input(data, strlen(data));
+ BC_Hash this_params;
+ char *this_text = 0;
+ char *this_extra = 0;
+ BC_Hash src_parameters;
+ char *src_text = 0;
+ char *src_extra = 0;
+
+ get_contents(&this_params, &this_text, &this_extra);
+ src->get_contents(&src_parameters, &src_text, &src_extra);
+
+if(debug) printf("KeyFrame::get_diff %d %d %d\n",
+__LINE__,
+this_params.size(),
+src_parameters.size());
+
+// Capture changed parameters
+ char this_value[BCTEXTLEN];
+ for(int i = 0; i < MIN(this_params.size(), src_parameters.size()); i++)
+ {
+ const char *src_key = src_parameters.get_key(i);
+ const char *src_value = src_parameters.get_value(i);
+ this_value[0] = 0;
+ this_params.get(src_key, this_value);
+if(debug) printf("KeyFrame::get_diff %d %s %s %s\n",
+__LINE__,
+src_key,
+src_value,
+this_value);
+// Capture values which differ
+ if(strcmp(src_value, this_value))
+ {
+ if(!(*params)) (*params) = new BC_Hash;
+ (*params)->update(src_key, src_value);
+ }
+ }
+
+
+// Capture text which differs
+ if( !this_text || strcmp(this_text, src_text))
+ (*text) = cstrdup(src_text);
+
+ if( !this_extra || strcmp(this_extra, src_extra))
+ (*extra) = cstrdup(src_extra);
+
+
+ delete [] this_text;
+ delete [] this_extra;
+ delete [] src_text;
+ delete [] src_extra;
+}
+
+int KeyFrame::operator==(Auto &that)
+{
+ return identical((KeyFrame*)&that);
+}
+
+int KeyFrame::operator==(KeyFrame &that)
+{
+ return identical(&that);
+}
+
+char* KeyFrame::get_data()
+{
+ return data;
+}
+
+void KeyFrame::set_data(char *data)
+{
+ strcpy(this->data, data);
+}
+
+void KeyFrame::dump(FILE *fp)
+{
+ fprintf(fp," position: %jd\n", position);
+ fprintf(fp," data: %s\n", data);
+}
+