4 * Copyright (C) 2001-2007 Krzysztof Foltman
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (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 GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General
17 * Public License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
30 #include <calf/preset.h>
31 #include <calf/giface.h>
32 #include <calf/utils.h>
35 using namespace calf_plugins
;
36 using namespace calf_utils
;
38 extern calf_plugins::preset_list
&calf_plugins::get_builtin_presets()
40 static calf_plugins::preset_list plist
;
44 extern calf_plugins::preset_list
&calf_plugins::get_user_presets()
46 static calf_plugins::preset_list plist
;
50 std::string
plugin_preset::to_xml()
53 ss
<< "<preset bank=\"" << bank
<< "\" program=\"" << program
<< "\" plugin=\"" << xml_escape(plugin
) << "\" name=\"" << xml_escape(name
) << "\">\n";
54 for (unsigned int i
= 0; i
< values
.size(); i
++) {
55 if (i
< param_names
.size())
56 ss
<< " <param name=\"" << xml_escape(param_names
[i
]) << "\" value=\"" << values
[i
] << "\" />\n";
58 ss
<< " <param value=\"" << values
[i
] << "\" />\n";
60 for (map
<string
, string
>::iterator i
= variables
.begin(); i
!= variables
.end(); i
++)
62 ss
<< " <var name=\"" << xml_escape(i
->first
) << "\">" << xml_escape(i
->second
) << "</var>\n";
68 string
plugin_preset::get_safe_name()
71 for (size_t i
= 0; i
< name
.length(); i
++)
73 if (isdigit(name
[i
]) || isalpha(name
[i
]))
79 void plugin_preset::activate(plugin_ctl_iface
*plugin
)
81 // First, clear everything to default values (in case some parameters or variables are missing)
82 plugin
->clear_preset();
84 map
<string
, int> names
;
85 int count
= plugin
->get_param_count();
86 // this is deliberately done in two separate loops - if you wonder why, just think for a while :)
87 for (int i
= 0; i
< count
; i
++)
88 names
[plugin
->get_param_props(i
)->name
] = i
;
89 for (int i
= 0; i
< count
; i
++)
90 names
[plugin
->get_param_props(i
)->short_name
] = i
;
91 // no support for unnamed parameters... tough luck :)
92 for (unsigned int i
= 0; i
< min(param_names
.size(), values
.size()); i
++)
94 map
<string
, int>::iterator pos
= names
.find(param_names
[i
]);
95 if (pos
== names
.end()) {
96 // XXXKF should have a mechanism for notifying a GUI
97 printf("Warning: unknown parameter %s for plugin %s\n", param_names
[i
].c_str(), this->plugin
.c_str());
100 plugin
->set_param_value(pos
->second
, values
[i
]);
102 for (map
<string
, string
>::iterator i
= variables
.begin(); i
!= variables
.end(); i
++)
104 printf("configure %s: %s\n", i
->first
.c_str(), i
->second
.c_str());
105 plugin
->configure(i
->first
.c_str(), i
->second
.c_str());
109 void plugin_preset::get_from(plugin_ctl_iface
*plugin
)
111 int count
= plugin
->get_param_count();
112 for (int i
= 0; i
< count
; i
++) {
113 if ((plugin
->get_param_props(i
)->flags
& PF_TYPEMASK
) >= PF_STRING
)
115 param_names
.push_back(plugin
->get_param_props(i
)->short_name
);
116 values
.push_back(plugin
->get_param_value(i
));
118 struct store_obj
: public send_configure_iface
120 map
<string
, string
> *data
;
121 void send_configure(const char *key
, const char *value
)
123 (*data
)[key
] = value
;
127 tmp
.data
= &variables
;
128 plugin
->send_configures(&tmp
);
131 string
calf_plugins::preset_list::get_preset_filename(bool builtin
)
135 return PKGLIBDIR
"/presets.xml";
139 const char *home
= getenv("HOME");
140 return string(home
)+"/.calfpresets";
144 void preset_list::xml_start_element_handler(void *user_data
, const char *name
, const char *attrs
[])
146 preset_list
&self
= *(preset_list
*)user_data
;
147 parser_state
&state
= self
.state
;
148 plugin_preset
&parser_preset
= self
.parser_preset
;
152 if (!strcmp(name
, "presets")) {
158 if (!strcmp(name
, "preset")) {
160 parser_preset
.bank
= parser_preset
.program
= 0;
161 parser_preset
.name
= "";
162 parser_preset
.plugin
= "";
163 parser_preset
.param_names
.clear();
164 parser_preset
.values
.clear();
165 parser_preset
.variables
.clear();
166 for(; *attrs
; attrs
+= 2) {
167 if (!strcmp(attrs
[0], "name")) self
.parser_preset
.name
= attrs
[1];
169 if (!strcmp(attrs
[0], "plugin")) self
.parser_preset
.plugin
= attrs
[1];
171 // autonumbering of programs for DSSI
172 if (!self
.last_preset_ids
.count(self
.parser_preset
.plugin
))
173 self
.last_preset_ids
[self
.parser_preset
.plugin
] = 0;
174 self
.parser_preset
.program
= ++self
.last_preset_ids
[self
.parser_preset
.plugin
];
175 self
.parser_preset
.bank
= (self
.parser_preset
.program
>> 7);
176 self
.parser_preset
.program
&= 127;
182 if (!strcmp(name
, "param")) {
185 for(; *attrs
; attrs
+= 2) {
186 if (!strcmp(attrs
[0], "name")) name
= attrs
[1];
188 if (!strcmp(attrs
[0], "value")) {
189 istringstream
str(attrs
[1]);
193 self
.parser_preset
.param_names
.push_back(name
);
194 self
.parser_preset
.values
.push_back(value
);
198 if (!strcmp(name
, "var")) {
199 self
.current_key
= "";
200 for(; *attrs
; attrs
+= 2) {
201 if (!strcmp(attrs
[0], "name")) self
.current_key
= attrs
[1];
203 if (self
.current_key
.empty())
204 throw preset_exception("No name specified for preset variable", "", 0);
205 self
.parser_preset
.variables
[self
.current_key
].clear();
211 // no nested elements allowed inside <param>
214 // no nested elements allowed inside <var>
217 // g_warning("Invalid XML element: %s", name);
218 throw preset_exception("Invalid XML element: %s", name
, 0);
221 void preset_list::xml_end_element_handler(void *user_data
, const char *name
)
223 preset_list
&self
= *(preset_list
*)user_data
;
224 preset_vector
&presets
= self
.presets
;
225 parser_state
&state
= self
.state
;
231 if (!strcmp(name
, "presets")) {
237 if (!strcmp(name
, "preset")) {
238 presets
.push_back(self
.parser_preset
);
244 if (!strcmp(name
, "param")) {
250 if (!strcmp(name
, "var")) {
256 throw preset_exception("Invalid XML element close: %s", name
, 0);
259 void preset_list::xml_character_data_handler(void *user_data
, const XML_Char
*data
, int len
)
261 preset_list
&self
= *(preset_list
*)user_data
;
262 parser_state
&state
= self
.state
;
265 self
.parser_preset
.variables
[self
.current_key
] += string(data
, len
);
270 bool preset_list::load_defaults(bool builtin
)
274 string name
= preset_list::get_preset_filename(builtin
);
275 if (!stat(name
.c_str(), &st
)) {
277 if (!presets
.empty())
281 catch(preset_exception
&ex
)
288 void preset_list::parse(const std::string
&data
)
291 XML_Parser parser
= XML_ParserCreate("UTF-8");
292 XML_SetUserData(parser
, this);
293 XML_SetElementHandler(parser
, xml_start_element_handler
, xml_end_element_handler
);
294 XML_SetCharacterDataHandler(parser
, xml_character_data_handler
);
295 XML_Status status
= XML_Parse(parser
, data
.c_str(), data
.length(), 1);
296 if (status
== XML_STATUS_ERROR
) {
297 string err
= string("Parse error: ") + XML_ErrorString(XML_GetErrorCode(parser
))+ " in ";
298 XML_ParserFree(parser
);
299 throw preset_exception(err
, "string", errno
);
301 XML_ParserFree(parser
);
304 void preset_list::load(const char *filename
)
307 XML_Parser parser
= XML_ParserCreate("UTF-8");
308 XML_SetUserData(parser
, this);
309 int fd
= open(filename
, O_RDONLY
);
311 throw preset_exception("Could not load the presets from ", filename
, errno
);
312 XML_SetElementHandler(parser
, xml_start_element_handler
, xml_end_element_handler
);
313 XML_SetCharacterDataHandler(parser
, xml_character_data_handler
);
317 int len
= read(fd
, buf
, 4096);
318 // XXXKF not an optimal error/EOF handling :)
321 XML_Status status
= XML_Parse(parser
, buf
, len
, 0);
322 if (status
== XML_STATUS_ERROR
)
323 throw preset_exception(string("Parse error: ") + XML_ErrorString(XML_GetErrorCode(parser
))+ " in ", filename
, errno
);
325 XML_Status status
= XML_Parse(parser
, buf
, 0, 1);
327 if (status
== XML_STATUS_ERROR
)
329 string err
= string("Parse error: ") + XML_ErrorString(XML_GetErrorCode(parser
))+ " in ";
330 XML_ParserFree(parser
);
331 throw preset_exception(err
, filename
, errno
);
333 XML_ParserFree(parser
);
336 void preset_list::save(const char *filename
)
338 string xml
= "<presets>\n";
339 for (unsigned int i
= 0; i
< presets
.size(); i
++)
341 xml
+= presets
[i
].to_xml();
344 int fd
= open(filename
, O_CREAT
| O_WRONLY
| O_TRUNC
, 0640);
345 if (fd
< 0 || ((unsigned)write(fd
, xml
.c_str(), xml
.length()) != xml
.length()))
346 throw preset_exception("Could not save the presets in ", filename
, errno
);
350 void preset_list::get_for_plugin(preset_vector
&vec
, const char *plugin
)
352 for (unsigned int i
= 0; i
< presets
.size(); i
++)
354 if (presets
[i
].plugin
== plugin
)
355 vec
.push_back(presets
[i
]);
359 void preset_list::add(const plugin_preset
&sp
)
361 for (unsigned int i
= 0; i
< presets
.size(); i
++)
363 if (presets
[i
].plugin
== sp
.plugin
&& presets
[i
].name
== sp
.name
)
369 presets
.push_back(sp
);