1 /* -*- Mode: C ; c-basic-offset: 4 -*- */
3 Copyright (C) 2007,2008,2011 Nedko Arnaudov
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #if defined(HAVE_CONFIG_H)
26 #include <sys/types.h>
34 #include <dbus/dbus.h>
36 #include "controller_internal.h"
40 jack_controller_settings_init(void)
46 jack_controller_settings_uninit(void)
52 struct jack_controller
*controller_ptr
;
54 bool option_value_capture
;
55 char option
[JACK_PARAM_STRING_MAX
+1];
57 const char * address
[PARAM_ADDRESS_SIZE
];
63 #define context_ptr ((struct parse_context *)data)
66 jack_controller_settings_callback_chrdata(void *data
, const XML_Char
*s
, int len
)
68 if (context_ptr
->error
)
73 if (context_ptr
->option_value_capture
)
75 if (context_ptr
->option_used
+ len
>= JACK_PARAM_STRING_MAX
)
77 jack_error("xml parse max char data length reached");
78 context_ptr
->error
= XML_TRUE
;
82 memcpy(context_ptr
->option
+ context_ptr
->option_used
, s
, len
);
83 context_ptr
->option_used
+= len
;
88 jack_controller_settings_callback_elstart(void *data
, const char *el
, const char **attr
)
90 if (context_ptr
->error
)
95 if (context_ptr
->address_index
>= PARAM_ADDRESS_SIZE
)
97 assert(context_ptr
->address_index
== PARAM_ADDRESS_SIZE
);
98 jack_error("xml param address max depth reached");
99 context_ptr
->error
= XML_TRUE
;
103 //jack_info("<%s>", el);
105 if (strcmp(el
, "jack") == 0)
110 if (strcmp(el
, PTNODE_ENGINE
) == 0)
112 context_ptr
->address
[context_ptr
->address_index
++] = PTNODE_ENGINE
;
116 if (strcmp(el
, PTNODE_DRIVERS
) == 0)
118 context_ptr
->address
[context_ptr
->address_index
++] = PTNODE_DRIVERS
;
122 if (strcmp(el
, PTNODE_INTERNALS
) == 0)
124 context_ptr
->address
[context_ptr
->address_index
++] = PTNODE_INTERNALS
;
128 if (strcmp(el
, "driver") == 0 ||
129 strcmp(el
, "internal") == 0)
131 if ((attr
[0] == NULL
|| attr
[2] != NULL
) || strcmp(attr
[0], "name") != 0)
133 jack_error("<%s> XML element must contain exactly one attribute, named \"name\"", el
);
134 context_ptr
->error
= XML_TRUE
;
138 context_ptr
->container
= strdup(attr
[1]);
139 if (context_ptr
->container
== NULL
)
141 jack_error("strdup() failed");
142 context_ptr
->error
= XML_TRUE
;
146 context_ptr
->address
[context_ptr
->address_index
++] = context_ptr
->container
;
151 if (strcmp(el
, "option") == 0)
153 if ((attr
[0] == NULL
|| attr
[2] != NULL
) || strcmp(attr
[0], "name") != 0)
155 jack_error("<option> XML element must contain exactly one attribute, named \"name\"");
156 context_ptr
->error
= XML_TRUE
;
160 context_ptr
->name
= strdup(attr
[1]);
161 if (context_ptr
->name
== NULL
)
163 jack_error("strdup() failed");
164 context_ptr
->error
= XML_TRUE
;
168 context_ptr
->address
[context_ptr
->address_index
++] = context_ptr
->name
;
169 context_ptr
->option_value_capture
= true;
170 context_ptr
->option_used
= 0;
174 jack_error("unknown element \"%s\"", el
);
175 context_ptr
->error
= XML_TRUE
;
179 jack_controller_settings_callback_elend(void *data
, const char *el
)
183 if (context_ptr
->error
)
188 //jack_info("</%s> (depth = %d)", el, context_ptr->address_index);
190 if (strcmp(el
, "option") == 0)
192 assert(context_ptr
->option_value_capture
);
193 context_ptr
->option
[context_ptr
->option_used
] = 0;
195 for (i
= context_ptr
->address_index
; i
< PARAM_ADDRESS_SIZE
; i
++)
197 context_ptr
->address
[context_ptr
->address_index
] = NULL
;
200 jack_controller_deserialize_parameter_value(context_ptr
->controller_ptr
, context_ptr
->address
, context_ptr
->option
);
202 free(context_ptr
->name
);
203 context_ptr
->name
= NULL
;
204 context_ptr
->option_value_capture
= false;
205 context_ptr
->address_index
--;
207 else if (context_ptr
->container
!= NULL
)
209 //jack_info("'%s'", context_ptr->container);
210 free(context_ptr
->container
);
211 context_ptr
->container
= NULL
;
212 context_ptr
->address_index
--;
214 else if (strcmp(el
, PTNODE_ENGINE
) == 0 ||
215 strcmp(el
, PTNODE_DRIVERS
) == 0 ||
216 strcmp(el
, PTNODE_INTERNALS
) == 0)
218 context_ptr
->address_index
--;
222 //jack_info("no depth decrement");
229 jack_controller_settings_load(
230 struct jack_controller
* controller_ptr
)
239 enum XML_Status xmls
;
240 struct parse_context context
;
242 conf_len
= strlen(JACKDBUS_CONF
);
244 filename
= malloc(g_jackdbus_config_dir_len
+ conf_len
+ 1);
245 if (filename
== NULL
)
247 jack_error("Out of memory.");
251 memcpy(filename
, g_jackdbus_config_dir
, g_jackdbus_config_dir_len
);
252 memcpy(filename
+ g_jackdbus_config_dir_len
, JACKDBUS_CONF
, conf_len
);
253 filename
[g_jackdbus_config_dir_len
+ conf_len
] = 0;
255 jack_info("Loading settings from \"%s\" using %s ...", filename
, XML_ExpatVersion());
257 if (stat(filename
, &st
) != 0)
259 jack_error("failed to stat \"%s\", error is %d (%s)", filename
, errno
, strerror(errno
));
262 fd
= open(filename
, O_RDONLY
);
265 jack_error("open() failed to open conf filename.");
266 goto exit_free_filename
;
269 parser
= XML_ParserCreate(NULL
);
272 jack_error("XML_ParserCreate() failed to create parser object.");
273 goto exit_close_file
;
276 //jack_info("conf file size is %llu bytes", (unsigned long long)st.st_size);
278 /* we are expecting that conf file has small enough size to fit in memory */
280 buffer
= XML_GetBuffer(parser
, st
.st_size
);
283 jack_error("XML_GetBuffer() failed.");
284 goto exit_free_parser
;
287 bytes_read
= read(fd
, buffer
, st
.st_size
);
288 if (bytes_read
!= st
.st_size
)
290 jack_error("read() returned unexpected result.");
291 goto exit_free_parser
;
294 context
.controller_ptr
= controller_ptr
;
295 context
.error
= XML_FALSE
;
296 context
.option_value_capture
= false;
297 context
.address_index
= 0;
299 context
.container
= NULL
;
301 XML_SetElementHandler(parser
, jack_controller_settings_callback_elstart
, jack_controller_settings_callback_elend
);
302 XML_SetCharacterDataHandler(parser
, jack_controller_settings_callback_chrdata
);
303 XML_SetUserData(parser
, &context
);
305 xmls
= XML_ParseBuffer(parser
, bytes_read
, XML_TRUE
);
308 free(context
.container
);
310 if (xmls
== XML_STATUS_ERROR
)
312 jack_error("XML_ParseBuffer() failed.");
313 goto exit_free_parser
;
317 XML_ParserFree(parser
);