sequencer load/save with treestore
[faros-demo] / src / seq.cc
1 #include <stdio.h>
2 #include <string.h>
3 #include <vector>
4 #include <treestore.h>
5 #include "seq.h"
6 #include "track.h"
7
8 struct SeqTrack {
9         char *name;
10         Track *track;
11 };
12
13 static std::vector<SeqTrack> tracks;
14
15
16 static Track *load_track(struct ts_node *tnode);
17 static InterpMode str2interp(const char *str);
18 static ExtrapMode str2extrap(const char *str);
19
20
21 bool init_seq()
22 {
23         return true;
24 }
25
26 void destroy_seq()
27 {
28         int ntrk = tracks.size();
29         for(int i=0; i<ntrk; i++) {
30                 delete tracks[i].track;
31                 delete [] tracks[i].name;
32         }
33         tracks.clear();
34 }
35
36 int add_seq_track(const char *name, InterpMode inmode, ExtrapMode exmode, float defval)
37 {
38         int idx = find_seq_track(name);
39         if(idx >= 0) return idx;
40
41         SeqTrack st;
42         st.name = new char[strlen(name) + 1];
43         strcpy(st.name, name);
44         st.track = new Track;
45         st.track->defval = defval;
46         st.track->interp = inmode;
47         st.track->extrap = exmode;
48         tracks.push_back(st);
49         return tracks.size() - 1;
50 }
51
52 int find_seq_track(const char *name)
53 {
54         int ntrk = tracks.size();
55         for(int i=0; i<ntrk; i++) {
56                 if(strcmp(tracks[i].name, name) == 0) {
57                         return i;
58                 }
59         }
60         return -1;
61 }
62
63 Track *get_seq_track(int idx)
64 {
65         return tracks[idx].track;
66 }
67
68 void clear_seq_track(int idx)
69 {
70         tracks[idx].track->clear();
71 }
72
73 void clear_seq_track(const char *name)
74 {
75         int idx = find_seq_track(name);
76         if(idx >= 0) {
77                 tracks[idx].track->clear();
78         }
79 }
80
81 void set_seq_value(int idx, long tm, float val)
82 {
83         tracks[idx].track->set_value(tm, val);
84 }
85
86 void set_seq_value(const char *name, long tm, float val)
87 {
88         int idx = find_seq_track(name);
89         if(idx >= 0) {
90                 tracks[idx].track->set_value(tm, val);
91         }
92 }
93
94 float get_seq_value(int idx, long tm)
95 {
96         return (*tracks[idx].track)(tm);
97 }
98
99 float get_seq_value(const char *name, long tm)
100 {
101         int idx = find_seq_track(name);
102         if(idx < 0) {
103                 return 0.0f;
104         }
105         return (*tracks[idx].track)(tm);
106 }
107
108 bool load_seq(const char *fname)
109 {
110         struct ts_node *tree;
111         if(!(tree = ts_load(fname))) {
112                 return false;
113         }
114         if(strcmp(tree->name, "faros") != 0) {
115                 fprintf(stderr, "invalid sequence file: %s\n", fname);
116                 ts_free_tree(tree);
117                 return false;
118         }
119
120         struct ts_node *node = tree->child_list;
121         while(node) {
122                 if(strcmp(node->name, "track") == 0) {
123                         Track *track = load_track(node);
124                         const char *name = ts_get_attr_str(node, "name", 0);
125                         if(!name) {
126                                 char buf[64];
127                                 static int foo;
128                                 sprintf(buf, "unnamed%03d", foo++);
129                                 name = buf;
130                         }
131
132                         int idx = find_seq_track(name);
133                         if(idx == -1) {
134                                 SeqTrack st;
135                                 st.track = track;
136                                 st.name = new char[strlen(name) + 1];
137                                 strcpy(st.name, name);
138                                 tracks.push_back(st);
139                         } else {
140                                 delete tracks[idx].track;
141                                 tracks[idx].track = track;
142                         }
143                 }
144
145                 node = node->next;
146         }
147
148         ts_free_tree(tree);
149         return true;
150 }
151
152 static Track *load_track(struct ts_node *tnode)
153 {
154         Track *track = new Track;
155         track->defval = ts_get_attr_num(tnode, "default", 0.0f);
156         track->interp = str2interp(ts_get_attr_str(tnode, "interpolation", ""));
157         track->extrap = str2extrap(ts_get_attr_str(tnode, "extrapolation", ""));
158
159         struct ts_node *keynode = tnode->child_list;
160         while(keynode) {
161                 long tm = ts_get_attr_int(keynode, "time", 0);
162                 float val = ts_get_attr_num(keynode, "value", 0.0f);
163                 track->set_value(tm, val);
164                 keynode = keynode->next;
165         }
166
167         return track;
168 }
169
170 static InterpMode str2interp(const char *str)
171 {
172         if(strcmp(str, "step") == 0) {
173                 return INTERP_STEP;
174         } else if(strcmp(str, "sigmoid") == 0) {
175                 return INTERP_SIGMOID;
176         }
177         return INTERP_LINEAR;
178 }
179
180 static ExtrapMode str2extrap(const char *str)
181 {
182         if(strcmp(str, "repeat") == 0) {
183                 return EXTRAP_REPEAT;
184         }
185         return EXTRAP_CLAMP;
186 }
187
188 bool dump_seq(const char *fname)
189 {
190         FILE *fp = fopen(fname, "w");
191         if(!fp) {
192                 perror("failed to open sequence dump file");
193                 return false;
194         }
195
196         fprintf(fp, "faros {\n");
197         int ntrk = tracks.size();
198         for(int i=0; i<ntrk; i++) {
199                 fprintf(fp, "  track {\n");
200                 fprintf(fp, "    name = \"%s\"\n", tracks[i].name);
201
202                 int nkeys = tracks[i].track->get_num_keys();
203                 for(int j=0; j<nkeys; j++) {
204                         TrackKey key = (*tracks[i].track)[j];
205                         fprintf(fp, "    key {\n");
206                         fprintf(fp, "      time = %ld\n", key.time);
207                         fprintf(fp, "      value = %g\n", key.value);
208                         fprintf(fp, "    }\n");
209                 }
210                 fprintf(fp, "  }\n\n");
211         }
212         fprintf(fp, "}\n");
213         fclose(fp);
214         return true;
215 }