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., 59 Temple Place, Suite 330,
19 * Boston, MA 02111-1307, 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 void plugin_preset::activate(plugin_ctl_iface
*plugin
)
70 // First, clear everything to default values (in case some parameters or variables are missing)
71 plugin
->clear_preset();
73 map
<string
, int> names
;
74 int count
= plugin
->get_param_count();
75 // this is deliberately done in two separate loops - if you wonder why, just think for a while :)
76 for (int i
= 0; i
< count
; i
++)
77 names
[plugin
->get_param_props(i
)->name
] = i
;
78 for (int i
= 0; i
< count
; i
++)
79 names
[plugin
->get_param_props(i
)->short_name
] = i
;
80 // no support for unnamed parameters... tough luck :)
81 for (unsigned int i
= 0; i
< min(param_names
.size(), values
.size()); i
++)
83 map
<string
, int>::iterator pos
= names
.find(param_names
[i
]);
84 if (pos
== names
.end()) {
85 // XXXKF should have a mechanism for notifying a GUI
86 printf("Warning: unknown parameter %s for plugin %s\n", param_names
[i
].c_str(), this->plugin
.c_str());
89 plugin
->set_param_value(pos
->second
, values
[i
]);
91 for (map
<string
, string
>::iterator i
= variables
.begin(); i
!= variables
.end(); i
++)
93 printf("configure %s: %s\n", i
->first
.c_str(), i
->second
.c_str());
94 plugin
->configure(i
->first
.c_str(), i
->second
.c_str());
98 void plugin_preset::get_from(plugin_ctl_iface
*plugin
)
100 int count
= plugin
->get_param_count();
101 for (int i
= 0; i
< count
; i
++) {
102 if ((plugin
->get_param_props(i
)->flags
& PF_TYPEMASK
) >= PF_STRING
)
104 param_names
.push_back(plugin
->get_param_props(i
)->short_name
);
105 values
.push_back(plugin
->get_param_value(i
));
107 struct store_obj
: public send_configure_iface
109 map
<string
, string
> *data
;
110 void send_configure(const char *key
, const char *value
)
112 (*data
)[key
] = value
;
116 tmp
.data
= &variables
;
117 plugin
->send_configures(&tmp
);
120 string
calf_plugins::preset_list::get_preset_filename(bool builtin
)
124 return PKGLIBDIR
"/presets.xml";
128 const char *home
= getenv("HOME");
129 return string(home
)+"/.calfpresets";
133 void preset_list::xml_start_element_handler(void *user_data
, const char *name
, const char *attrs
[])
135 preset_list
&self
= *(preset_list
*)user_data
;
136 parser_state
&state
= self
.state
;
137 plugin_preset
&parser_preset
= self
.parser_preset
;
141 if (!strcmp(name
, "presets")) {
147 if (!strcmp(name
, "preset")) {
149 parser_preset
.bank
= parser_preset
.program
= 0;
150 parser_preset
.name
= "";
151 parser_preset
.plugin
= "";
152 parser_preset
.param_names
.clear();
153 parser_preset
.values
.clear();
154 parser_preset
.variables
.clear();
155 for(; *attrs
; attrs
+= 2) {
156 if (!strcmp(attrs
[0], "name")) self
.parser_preset
.name
= attrs
[1];
158 if (!strcmp(attrs
[0], "plugin")) self
.parser_preset
.plugin
= attrs
[1];
160 // autonumbering of programs for DSSI
161 if (!self
.last_preset_ids
.count(self
.parser_preset
.plugin
))
162 self
.last_preset_ids
[self
.parser_preset
.plugin
] = 0;
163 self
.parser_preset
.program
= ++self
.last_preset_ids
[self
.parser_preset
.plugin
];
164 self
.parser_preset
.bank
= (self
.parser_preset
.program
>> 7);
165 self
.parser_preset
.program
&= 127;
171 if (!strcmp(name
, "param")) {
174 for(; *attrs
; attrs
+= 2) {
175 if (!strcmp(attrs
[0], "name")) name
= attrs
[1];
177 if (!strcmp(attrs
[0], "value")) {
178 istringstream
str(attrs
[1]);
182 self
.parser_preset
.param_names
.push_back(name
);
183 self
.parser_preset
.values
.push_back(value
);
187 if (!strcmp(name
, "var")) {
188 self
.current_key
= "";
189 for(; *attrs
; attrs
+= 2) {
190 if (!strcmp(attrs
[0], "name")) self
.current_key
= attrs
[1];
192 if (self
.current_key
.empty())
193 throw preset_exception("No name specified for preset variable", "", 0);
194 self
.parser_preset
.variables
[self
.current_key
].clear();
200 // no nested elements allowed inside <param>
203 // no nested elements allowed inside <var>
206 // g_warning("Invalid XML element: %s", name);
207 throw preset_exception("Invalid XML element: %s", name
, 0);
210 void preset_list::xml_end_element_handler(void *user_data
, const char *name
)
212 preset_list
&self
= *(preset_list
*)user_data
;
213 preset_vector
&presets
= self
.presets
;
214 parser_state
&state
= self
.state
;
220 if (!strcmp(name
, "presets")) {
226 if (!strcmp(name
, "preset")) {
227 presets
.push_back(self
.parser_preset
);
233 if (!strcmp(name
, "param")) {
239 if (!strcmp(name
, "var")) {
245 throw preset_exception("Invalid XML element close: %s", name
, 0);
248 void preset_list::xml_character_data_handler(void *user_data
, const XML_Char
*data
, int len
)
250 preset_list
&self
= *(preset_list
*)user_data
;
251 parser_state
&state
= self
.state
;
254 self
.parser_preset
.variables
[self
.current_key
] += string(data
, len
);
259 bool preset_list::load_defaults(bool builtin
)
263 string name
= preset_list::get_preset_filename(builtin
);
264 if (!stat(name
.c_str(), &st
)) {
266 if (!presets
.empty())
270 catch(preset_exception
&ex
)
277 void preset_list::parse(const std::string
&data
)
280 XML_Parser parser
= XML_ParserCreate("UTF-8");
281 XML_SetUserData(parser
, this);
282 XML_SetElementHandler(parser
, xml_start_element_handler
, xml_end_element_handler
);
283 XML_SetCharacterDataHandler(parser
, xml_character_data_handler
);
284 XML_Status status
= XML_Parse(parser
, data
.c_str(), data
.length(), 1);
285 if (status
== XML_STATUS_ERROR
) {
286 string err
= string("Parse error: ") + XML_ErrorString(XML_GetErrorCode(parser
))+ " in ";
287 XML_ParserFree(parser
);
288 throw preset_exception(err
, "string", errno
);
290 XML_ParserFree(parser
);
293 void preset_list::load(const char *filename
)
296 XML_Parser parser
= XML_ParserCreate("UTF-8");
297 XML_SetUserData(parser
, this);
298 int fd
= open(filename
, O_RDONLY
);
300 throw preset_exception("Could not load the presets from ", filename
, errno
);
301 XML_SetElementHandler(parser
, xml_start_element_handler
, xml_end_element_handler
);
302 XML_SetCharacterDataHandler(parser
, xml_character_data_handler
);
306 int len
= read(fd
, buf
, 4096);
307 // XXXKF not an optimal error/EOF handling :)
310 XML_Status status
= XML_Parse(parser
, buf
, len
, 0);
311 if (status
== XML_STATUS_ERROR
)
312 throw preset_exception(string("Parse error: ") + XML_ErrorString(XML_GetErrorCode(parser
))+ " in ", filename
, errno
);
314 XML_Status status
= XML_Parse(parser
, buf
, 0, 1);
316 if (status
== XML_STATUS_ERROR
)
318 string err
= string("Parse error: ") + XML_ErrorString(XML_GetErrorCode(parser
))+ " in ";
319 XML_ParserFree(parser
);
320 throw preset_exception(err
, filename
, errno
);
322 XML_ParserFree(parser
);
325 void preset_list::save(const char *filename
)
327 string xml
= "<presets>\n";
328 for (unsigned int i
= 0; i
< presets
.size(); i
++)
330 xml
+= presets
[i
].to_xml();
333 int fd
= open(filename
, O_CREAT
| O_WRONLY
| O_TRUNC
, 0640);
334 if (fd
< 0 || ((unsigned)write(fd
, xml
.c_str(), xml
.length()) != xml
.length()))
335 throw preset_exception("Could not save the presets in ", filename
, errno
);
339 void preset_list::get_for_plugin(preset_vector
&vec
, const char *plugin
)
341 for (unsigned int i
= 0; i
< presets
.size(); i
++)
343 if (presets
[i
].plugin
== plugin
)
344 vec
.push_back(presets
[i
]);
348 void preset_list::add(const plugin_preset
&sp
)
350 for (unsigned int i
= 0; i
< presets
.size(); i
++)
352 if (presets
[i
].plugin
== sp
.plugin
&& presets
[i
].name
== sp
.name
)
358 presets
.push_back(sp
);