fixes and accomodations for other operating systems by Andrew
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / presets.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 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 "bcsignals.h"
23 #include "bcwindowbase.inc"
24 #include "file.h"
25 #include "filesystem.h"
26 #include "filexml.h"
27 #include "keyframe.h"
28 #include "messages.inc"
29 #include "mwindow.h"
30 #include "pluginserver.h"
31 #include "preferences.inc"
32 #include "presets.h"
33
34 #include <errno.h>
35 #include <string.h>
36
37 PresetsDB::PresetsDB()
38 {
39 }
40
41 void PresetsDB::clear()
42 {
43         plugins.remove_all_objects();
44 }
45
46 void PresetsDB::load_from_file(char *path, int is_factory, int clear_it)
47 {
48         if( clear_it ) clear();
49         FileXML file;
50
51         file.read_from_file(path, 1);
52         load_common(&file, is_factory);
53 }
54
55 void PresetsDB::load_from_string(char *string, int is_factory, int clear_it)
56 {
57         if( clear_it ) clear();
58         
59         FileXML file;
60         file.read_from_string(string);
61         load_common(&file, is_factory);
62 }
63
64
65
66 void PresetsDB::load_common(FileXML *file, int is_factory)
67 {
68         int result = 0;
69         char string[BCTEXTLEN];
70
71         do {
72                 result = file->read_tag();
73                 if( ! result  ) {
74                         if( file->tag.title_is("PLUGIN") ) {
75                                 PresetsDBPlugin *plugin = 0;
76                                 sprintf(string, "Unknown");
77                                 const char *title = file->tag.get_property("TITLE", string);
78
79 // Search for existing plugin
80                                 for( int i=0; i<plugins.size(); ++i ) {
81                                         if( !strcasecmp(plugins[i]->title, title) ) {
82                                                 plugin = plugins[i];
83                                                 break;
84                                         }
85                                 }
86
87 // Create new plugin
88                                 if( !plugin ) {
89                                         plugin = new PresetsDBPlugin(title);
90                                         plugins.append(plugin);
91                                 }
92
93                                 plugin->load(file, is_factory);
94                         }
95                 }
96         } while(!result);
97 }
98
99
100 void PresetsDB::save()
101 {
102         FileXML file;
103         for( int i=0; i<plugins.size(); ++i ) {
104                 PresetsDBPlugin *plugin = plugins[i];
105                 if( plugin->get_total_presets(1) > 0 ) {
106                         plugin->save(&file);
107                 }
108         }
109         file.terminate_string();
110
111         char path[BCTEXTLEN];
112         sprintf(path, "%s/%s", File::get_config_path(), PRESETS_FILE);
113         FileSystem fs;
114         fs.complete_path(path);
115         file.write_to_file(path);
116 }
117
118
119 int PresetsDB::get_total_presets(char *plugin_title, int user_only)
120 {
121         for( int i=0; i<plugins.size(); ++i ) {
122                 PresetsDBPlugin *plugin = plugins[i];
123                 if( !strcasecmp(plugin->title, plugin_title) ) {
124                         return plugin->get_total_presets(user_only);
125                 }
126         }
127
128         return 0;
129 }
130
131
132 // move factory presets to the start, followed by sorted preset titles
133 void PresetsDB::sort(char *plugin_title)
134 {
135         PresetsDBPlugin *plugin = 0;
136         for( int i=0; !plugin && i<plugins.size(); ++i ) {
137                 if( !strcasecmp(plugins[i]->title, plugin_title) )
138                         plugin = plugins[i];
139         }
140
141         if( plugin ) {
142                 int done = 0;
143                 int total_presets = plugin->get_total_presets(0);
144                 while( !done ) {
145                         done = 1;
146                         for( int i=0; i<total_presets-1; ++i ) {
147                                 PresetsDBKeyframe *keyframe1 = plugin->keyframes[i];
148                                 PresetsDBKeyframe *keyframe2 = plugin->keyframes[i+1];
149
150                                 if( (keyframe2->is_factory && !keyframe1->is_factory) ||
151                                     (keyframe2->is_factory == keyframe1->is_factory &&
152                                      strcmp(keyframe2->title, keyframe1->title) < 0) ) {
153                                         plugin->keyframes.set(i, keyframe2);
154                                         plugin->keyframes.set(i + 1, keyframe1);
155                                         done = 0;
156                                 }
157                         }
158                 }
159         }
160 }
161
162
163 char* PresetsDB::get_preset_title(char *plugin_title, int number)
164 {
165         for( int i=0; i<plugins.size(); ++i ) {
166                 PresetsDBPlugin *plugin = plugins[i];
167                 if( !strcasecmp(plugin->title, plugin_title) ) {
168                         if( number < plugin->keyframes.size() )
169                                 return plugin->keyframes[number]->title;
170                         printf("PresetsDB::get_preset_title %d buffer overrun\n", __LINE__);
171                         break;
172                 }
173         }
174         return 0;
175 }
176
177
178 int PresetsDB::get_is_factory(char *plugin_title, int number)
179 {
180         for( int i=0; i<plugins.size(); ++i ) {
181                 PresetsDBPlugin *plugin = plugins[i];
182                 if( !strcasecmp(plugin->title, plugin_title) ) {
183                         if( number < plugin->keyframes.size() )
184                                 return plugin->keyframes[number]->is_factory;
185                         printf("PresetsDB::get_preset_title %d buffer overrun\n", __LINE__);
186                         break;
187                 }
188         }
189         return 0;
190 }
191
192
193 char* PresetsDB::get_preset_data(char *plugin_title, int number)
194 {
195         for( int i=0; i<plugins.size(); ++i ) {
196                 PresetsDBPlugin *plugin = plugins[i];
197                 if( !strcasecmp(plugin->title, plugin_title) ) {
198                         if( number < plugin->keyframes.size() )
199                                 return plugin->keyframes[number]->data;
200                         printf("PresetsDB::get_preset_data %d buffer overrun\n", __LINE__);
201                         break;
202                 }
203         }
204         return 0;
205 }
206
207 PresetsDBPlugin* PresetsDB::get_plugin(const char *plugin_title)
208 {
209         for( int i=0; i<plugins.size(); ++i ) {
210                 PresetsDBPlugin *plugin = plugins[i];
211                 if( !strcasecmp(plugin->title, plugin_title) )
212                         return plugin;
213         }
214         return 0;
215 }
216
217 PresetsDBPlugin* PresetsDB::new_plugin(const char *plugin_title)
218 {
219         PresetsDBPlugin *result = new PresetsDBPlugin(plugin_title);
220         plugins.append(result);
221         return result;
222 }
223
224
225 void PresetsDB::save_preset(const char *plugin_title, 
226         const char *preset_title, 
227         char *data)
228 {
229         PresetsDBPlugin *plugin = get_plugin(plugin_title);
230         if( !plugin ) plugin = new_plugin(plugin_title);
231         PresetsDBKeyframe *keyframe = plugin->get_keyframe(preset_title, 0);
232         if( !keyframe ) keyframe = plugin->new_keyframe(preset_title);
233         keyframe->set_data(data);
234         save();
235
236 }
237
238
239 void PresetsDB::delete_preset(const char *plugin_title, 
240         const char *preset_title,
241         int is_factory)
242 {
243         PresetsDBPlugin *plugin = get_plugin(plugin_title);
244         if( plugin ) {
245                 plugin->delete_keyframe(preset_title);
246         }
247         save();
248 }
249
250 void PresetsDB::load_preset(const char *plugin_title,
251         const char *preset_title, 
252         KeyFrame *keyframe,
253         int is_factory)
254 {
255         PresetsDBPlugin *plugin = get_plugin(plugin_title);
256         if( plugin ) {
257                 plugin->load_preset(preset_title, keyframe, is_factory);
258         }
259 }
260
261 int PresetsDB::preset_exists(const char *plugin_title, 
262         const char *preset_title,
263         int is_factory)
264 {
265         PresetsDBPlugin *plugin = get_plugin(plugin_title);
266         if( plugin ) {
267                 return plugin->preset_exists(preset_title, is_factory);
268         }
269         return 0;
270 }
271
272
273
274
275 PresetsDBKeyframe::PresetsDBKeyframe(const char *title, int is_factory)
276 {
277         this->title = strdup(title);
278         data = 0;
279         this->is_factory = is_factory;
280 }
281
282 PresetsDBKeyframe::~PresetsDBKeyframe()
283 {
284         delete [] title;
285         delete [] data;
286 }
287
288 void PresetsDBKeyframe::set_data(char *data)
289 {
290         delete [] this->data;
291         this->data = new char[strlen(data) + 1];
292         strcpy(this->data, data);
293 }
294
295
296 PresetsDBPlugin::PresetsDBPlugin(const char *title)
297 {
298         this->title = strdup(title);
299 }
300
301 PresetsDBPlugin::~PresetsDBPlugin()
302 {
303         keyframes.remove_all_objects();
304         delete [] title;
305 }
306
307 int PresetsDBPlugin::get_total_presets(int user_only)
308 {
309         if( !user_only )
310                 return keyframes.size();
311         int result = 0;
312         for( int j=0; j<keyframes.size(); ++j )
313                 if( !keyframes[j]->is_factory ) ++result;
314         return result;
315 }
316
317 void PresetsDBPlugin::load(FileXML *file, int is_factory)
318 {
319         int result = 0;
320         char string[BCTEXTLEN];
321
322         do {
323                 result = file->read_tag();
324                 if( !result ) {
325                         if( file->tag.title_is("/PLUGIN") ) break;
326                         else
327                         if( file->tag.title_is("KEYFRAME") ) {
328                                 sprintf(string, "Unknown");
329                                 const char *keyframe_title = file->tag.get_property("TITLE", string);
330                                 PresetsDBKeyframe *keyframe = new PresetsDBKeyframe(keyframe_title, is_factory);
331                                 XMLBuffer data;
332                                 file->read_data_until("/KEYFRAME", &data);
333                                 keyframe->set_data(data.cstr());
334                                 keyframes.append(keyframe);
335                 
336                         }
337                 }
338         } while(!result);
339 }
340
341 void PresetsDBPlugin::save(FileXML *file)
342 {
343         file->tag.set_title("PLUGIN");
344         file->tag.set_property("TITLE", title);
345         file->append_tag();
346         file->append_newline();
347
348         for( int j=0; j<keyframes.size(); ++j ) {
349                 PresetsDBKeyframe *keyframe = keyframes[j];
350                 
351                 if( !keyframe->is_factory ) {
352                         file->tag.set_title("KEYFRAME");
353                         file->tag.set_property("TITLE", keyframe->title);
354                         file->append_tag();
355                         file->append_data(keyframe->data);
356                         file->tag.set_title("/KEYFRAME");
357                         file->append_tag();
358                         file->append_newline();
359                 }
360         }
361
362         file->tag.set_title("/PLUGIN");
363         file->append_tag();
364         file->append_newline();
365 }
366
367 PresetsDBKeyframe* PresetsDBPlugin::get_keyframe(const char *title, 
368         int is_factory)
369 {
370         for( int i=0; i<keyframes.size(); ++i ) {
371                 PresetsDBKeyframe *keyframe = keyframes[i];
372                 if( !strcasecmp(keyframe->title, title) && 
373                     keyframe->is_factory == is_factory )
374                         return keyframe;
375         }
376         return 0;
377 }
378
379 void PresetsDBPlugin::delete_keyframe(const char *title)
380 {
381         for( int i=0; i<keyframes.size(); ++i ) {
382                 PresetsDBKeyframe *keyframe = keyframes[i];
383                 if( !strcasecmp(keyframe->title, title) && !keyframe->is_factory ) {
384                         keyframes.remove_object_number(i);
385                         return;
386                 }
387         }
388 }
389
390
391 PresetsDBKeyframe* PresetsDBPlugin::new_keyframe(const char *title)
392 {
393         PresetsDBKeyframe *keyframe = new PresetsDBKeyframe(title, 0);
394         keyframes.append(keyframe);
395         return keyframe;
396 }
397
398 void PresetsDBPlugin::load_preset(const char *preset_title, 
399         KeyFrame *keyframe,
400         int is_factory)
401 {
402         PresetsDBKeyframe *src = get_keyframe(preset_title, is_factory);
403         if( src ) {
404                 keyframe->set_data(src->data);
405 // Save as the plugin's default, Need the path
406 //printf("PresetsDBPlugin::load_preset %d %s\n", __LINE__, title);
407                 PluginServer *server = MWindow::scan_plugindb(title, -1);
408                 if( server ) {
409                         char path[BCTEXTLEN];
410                         server->get_defaults_path(path);
411                         FileSystem fs;
412                         fs.complete_path(path);
413
414                         FILE *fd = fopen(path, "w");
415                         if( fd ) {
416                                 if( !fwrite(src->data, strlen(src->data), 1, fd) ) {
417                                         fprintf(stderr, "PresetsDBPlugin::load_preset %d \"%s\": %s\n",
418                                                 __LINE__,
419                                                 path,
420                                                 strerror(errno));
421                                 }
422
423                                 fclose(fd);
424                         }
425                         else {
426                                 fprintf(stderr, "PresetsDBPlugin::load_preset %d \"%s\": %s\n",
427                                         __LINE__, path, strerror(errno));
428                         }
429                 }
430         }
431 }
432
433 int PresetsDBPlugin::preset_exists(const char *preset_title, int is_factory)
434 {
435         PresetsDBKeyframe *src = get_keyframe(preset_title, is_factory);
436         return src ? 1 : 0;
437 }
438