2
* This file is part of GNAC - Gnome Audio Converter
4
* Copyright (C) 2007 - 2012 Gnac
6
* - DUPASQUIER Benoit <bdupasqu@src.gnome.org>
7
* - JOAQUIM David <djoaquim@src.gnome.org>
8
* - ROUX Alexandre <alexroux@src.gnome.org>
10
* GNAC is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License as published by
12
* the Free Software Foundation; either version 3 of the License, or
13
* (at your option) any later version.
15
* GNAC is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
* GNU General Public License for more details.
20
* You should have received a copy of the GNU General Public License
21
* along with GNAC; if not, write to the Free Software
22
* Foundation, Inc., 51 Franklin St, Fifth Floor,
23
* Boston, MA 02110-1301 USA
30
#include <glib/gi18n.h>
31
#include <glib/gstdio.h>
33
#include <libxml/xpath.h>
35
#include "gnac-profiles-xml-engine.h"
36
#include "gnac-profiles-utils.h"
37
#include "gnac-utils.h"
41
gnac_profiles_xml_engine_load_doc_xpath(const gchar *filename)
43
xmlDocPtr doc = xmlParseFile(filename);
44
if (!doc) return NULL;
46
xmlXPathContextPtr xpath_context = xmlXPathNewContext(doc);
52
XMLDoc *dx = g_malloc(sizeof(XMLDoc));
54
dx->xpath_context = xpath_context;
60
static xmlXPathObjectPtr
61
gnac_profiles_xml_engine_evaluate_query(const gchar *query,
62
xmlXPathContextPtr xpath_context)
64
return xmlXPathEvalExpression(BAD_CAST query, xpath_context);
69
gnac_profiles_xml_engine_get_property(XMLDoc *doc,
71
const gchar *property_name)
73
xmlXPathObjectPtr xpath_obj = gnac_profiles_xml_engine_evaluate_query(
74
query, doc->xpath_context);
75
if (!xpath_obj) return NULL;
77
xmlNodeSetPtr nodes = xpath_obj->nodesetval;
78
if (xmlXPathNodeSetIsEmpty(nodes)) {
79
xmlXPathFreeObject(xpath_obj);
83
xmlChar *property = xmlGetProp(nodes->nodeTab[0], (xmlChar *) property_name);
85
xmlXPathFreeObject(xpath_obj);
87
return (gchar *) property;
92
gnac_profiles_xml_engine_get_format_id(XMLDoc *doc)
94
return gnac_profiles_xml_engine_get_property(doc, "//profiles/profile", "id");
99
gnac_profiles_xml_engine_get_variable_type(XMLDoc *doc,
102
return gnac_profiles_xml_engine_get_property(doc, expr, "type");
107
gnac_profiles_xml_engine_get_text_node(XMLDoc *doc,
110
xmlXPathObjectPtr xpath_obj = gnac_profiles_xml_engine_evaluate_query(
111
expr, doc->xpath_context);
112
if (!xpath_obj) return NULL;
114
xmlNodeSetPtr nodes = xpath_obj->nodesetval;
115
if (xmlXPathNodeSetIsEmpty(nodes)) {
116
xmlXPathFreeObject(xpath_obj);
120
xmlNodePtr node = nodes->nodeTab[0];
121
if (!node || !(node->children)) {
122
xmlXPathFreeObject(xpath_obj);
126
xmlXPathFreeObject(xpath_obj);
128
xmlChar *content = xmlNodeGetContent(node->children);
129
gchar *translated = g_strdup(gettext((gchar *) content));
137
gnac_profiles_xml_engine_query_name(XMLDoc *doc,
140
gchar *query = g_strconcat("//profile[@id='", format, "']/name", NULL);
141
gchar *name = gnac_profiles_xml_engine_get_text_node(doc, query);
148
gnac_profiles_xml_engine_query_extension(XMLDoc *doc,
151
gchar *query = g_strconcat("//profile[@id='", format,
152
"']/output-file-extension", NULL);
153
gchar *extension = gnac_profiles_xml_engine_get_text_node(doc, query);
160
gnac_profiles_xml_engine_query_description(XMLDoc *doc,
163
gchar *query = g_strconcat("//profile[@id='", format, "']/description", NULL);
164
gchar *description = gnac_profiles_xml_engine_get_text_node(doc, query);
171
gnac_profiles_xml_engine_str_equal(const xmlChar *str1,
174
return gnac_utils_str_equal((const gchar *) str1, str2);
179
gnac_profiles_xml_engine_node_name_equal(xmlNode *node,
182
return gnac_profiles_xml_engine_str_equal(node->name, name);
187
gnac_profiles_xml_engine_is_i18n_node(xmlNodePtr node)
189
return gnac_profiles_xml_engine_str_equal(node->properties->name, "lang");
194
gnac_profiles_xml_engine_get_list_values(XMLDoc *doc,
197
xmlXPathObjectPtr xpath_obj = gnac_profiles_xml_engine_evaluate_query(
198
expr, doc->xpath_context);
199
if (!xpath_obj) return NULL;
201
xmlNodeSetPtr nodes = xpath_obj->nodesetval;
202
if (xmlXPathNodeSetIsEmpty(nodes)) {
203
xmlXPathFreeObject(xpath_obj);
210
for (i = 0; i < nodes->nodeNr; i++) {
211
xmlNode *current_node = nodes->nodeTab[i];
213
if (!gnac_profiles_xml_engine_is_i18n_node(current_node)) {
214
Value *val = g_malloc(sizeof(Value));
216
(gchar *) xmlNodeGetContent(current_node->children));
218
(gchar *) xmlNodeGetContent(current_node->properties->children);
219
list = g_list_prepend(list, val);
223
xmlXPathFreeObject(xpath_obj);
225
return g_list_reverse(list);
230
gnac_profiles_xml_engine_get_combo_values(XMLDoc *doc,
233
xmlXPathObjectPtr xpath_obj = gnac_profiles_xml_engine_evaluate_query(
234
expr, doc->xpath_context);
235
if (!xpath_obj) return NULL;
237
xmlNodeSetPtr nodes = xpath_obj->nodesetval;
238
if (xmlXPathNodeSetIsEmpty(nodes)) {
239
xmlXPathFreeObject(xpath_obj);
243
xmlNode *values_first = NULL;
244
xmlNode *values_last = NULL;
245
gchar *default_value = NULL;
246
gchar *variable_name = NULL;
248
xmlNodePtr current_node = nodes->nodeTab[0]->children;
250
while ((current_node = current_node->next)) {
251
gchar *content = (gchar *) xmlNodeGetContent(current_node->children);
253
if (gnac_profiles_xml_engine_node_name_equal(current_node,
256
variable_name = g_strdup(content);
258
else if (gnac_profiles_xml_engine_node_name_equal(current_node,
261
default_value = g_strdup(content);
263
else if (gnac_profiles_xml_engine_node_name_equal(current_node,
266
values_first = current_node->children->next;
267
values_last = current_node->last;
273
if (values_first && values_last && default_value && variable_name) {
274
GList *values = NULL;
277
xmlNode *current_node = values_first;
279
while (current_node && current_node != values_last) {
280
if (!gnac_profiles_xml_engine_is_i18n_node(current_node)) {
281
values = g_list_prepend(values,
282
xmlNodeGetContent(current_node->properties->children));
283
xmlChar *content = xmlNodeGetContent(current_node->children);
284
names = g_list_prepend(names, g_strdup(gettext((gchar *) content)));
288
current_node = current_node->next;
290
if (xmlNodeIsText(current_node)) {
291
current_node = current_node->next;
295
xmlXPathFreeObject(xpath_obj);
297
ComboValues *combo_values = g_malloc(sizeof(ComboValues));
298
combo_values->names = g_list_reverse(names);
299
combo_values->values = g_list_reverse(values);
300
combo_values->default_value = default_value;
301
combo_values->variable_name = variable_name;
306
xmlXPathFreeObject(xpath_obj);
313
gnac_profiles_xml_engine_get_slider_values(XMLDoc *doc,
316
xmlXPathObjectPtr xpath_obj = gnac_profiles_xml_engine_evaluate_query(
317
expr, doc->xpath_context);
318
if (!xpath_obj) return NULL;
320
xmlNodeSetPtr nodes = xpath_obj->nodesetval;
321
if (xmlXPathNodeSetIsEmpty(nodes)) {
322
xmlXPathFreeObject(xpath_obj);
329
gdouble default_value = 0.0;
330
gchar *variable_name = NULL;
332
xmlNodePtr current_node = nodes->nodeTab[0]->children;
334
while ((current_node = current_node->next)) {
335
gchar *content = (gchar *) xmlNodeGetContent(current_node->children);
337
if (gnac_profiles_xml_engine_node_name_equal(current_node,
340
variable_name = g_strdup(content);
342
else if (gnac_profiles_xml_engine_node_name_equal(current_node,
345
default_value = gnac_profiles_utils_gchararray_to_gdouble(content);
347
else if (gnac_profiles_xml_engine_node_name_equal(current_node,
350
min = gnac_profiles_utils_gchararray_to_gdouble(content);
352
else if (gnac_profiles_xml_engine_node_name_equal(current_node,
355
max = gnac_profiles_utils_gchararray_to_gdouble(content);
357
else if (gnac_profiles_xml_engine_node_name_equal(current_node,
360
step = gnac_profiles_utils_gchararray_to_gdouble(content);
367
xmlXPathFreeObject(xpath_obj);
369
SliderValues *slider_values = g_malloc(sizeof(SliderValues));
370
slider_values->min = min;
371
slider_values->max = max;
372
slider_values->step = step;
373
slider_values->default_value = default_value;
374
slider_values->variable_name = variable_name;
376
return slider_values;
379
xmlXPathFreeObject(xpath_obj);
386
gnac_profiles_xml_engine_get_check_values(XMLDoc *doc,
389
xmlXPathObjectPtr xpath_obj = gnac_profiles_xml_engine_evaluate_query(
390
expr, doc->xpath_context);
391
if (!xpath_obj) return NULL;
393
xmlNodeSetPtr nodes = xpath_obj->nodesetval;
394
if (xmlXPathNodeSetIsEmpty(nodes)) {
395
xmlXPathFreeObject(xpath_obj);
399
gchar *variable_name = NULL;
400
gboolean default_value = FALSE;
402
xmlNodePtr current_node = nodes->nodeTab[0]->children;
404
while ((current_node = current_node->next)) {
405
gchar *content = (gchar *) xmlNodeGetContent(current_node->children);
407
if (gnac_profiles_xml_engine_node_name_equal(current_node,
410
variable_name = g_strdup(content);
412
else if (gnac_profiles_xml_engine_node_name_equal(current_node,
415
default_value = gnac_utils_str_equal(content, "true");
422
xmlXPathFreeObject(xpath_obj);
424
CheckValues *check_values = g_malloc(sizeof(CheckValues));
425
check_values->default_value = default_value;
426
check_values->variable_name = variable_name;
431
xmlXPathFreeObject(xpath_obj);
438
gnac_profiles_xml_engine_modify_values(XMLDoc *doc,
442
xmlXPathObjectPtr xpath_obj = gnac_profiles_xml_engine_evaluate_query(
443
expr, doc->xpath_context);
444
if (!xpath_obj) return;
446
xmlNodeSetPtr nodes = xpath_obj->nodesetval;
447
if (xmlXPathNodeSetIsEmpty(nodes)) {
448
xmlXPathFreeObject(xpath_obj);
456
const gchar *value = va_arg(ap, const gchar *);
458
for (i = nodes->nodeNr-1; i >= 0; i--) {
459
gchar *value_formatted = gnac_profiles_xml_engine_format_text_to_xml(value);
460
xmlNodeSetContent(nodes->nodeTab[i], BAD_CAST value_formatted);
461
g_free(value_formatted);
463
if (nodes->nodeTab[i]->type != XML_NAMESPACE_DECL) {
464
nodes->nodeTab[i] = NULL;
467
value = va_arg(ap, const gchar *);
470
xmlXPathFreeObject(xpath_obj);
475
gnac_profiles_xml_engine_add_values(XMLDoc *doc, ...)
477
const gchar *expr = "/audio-profile/format-specific";
478
xmlXPathObjectPtr xpath_obj = gnac_profiles_xml_engine_evaluate_query(
479
expr, doc->xpath_context);
480
if (!xpath_obj) return;
482
xmlNodeSetPtr nodes = xpath_obj->nodesetval;
483
if (xmlXPathNodeSetIsEmpty(nodes)) {
484
xmlXPathFreeObject(xpath_obj);
488
xmlNodePtr format_node = nodes->nodeTab[0];
489
const xmlChar *base_indent = format_node->prev->content;
490
xmlChar *properties_indent = (xmlChar *)
491
g_strconcat((const gchar *) base_indent, " ", NULL);
492
xmlAddChild(format_node, xmlNewText(BAD_CAST " "));
497
const xmlChar *name = va_arg(ap, const xmlChar *);
500
const gchar *value = va_arg(ap, const gchar *);
501
xmlNodePtr node = xmlNewNode(format_node->ns, name);
502
node = xmlAddChild(format_node, node);
504
if (!gnac_utils_string_is_null_or_empty(value)) {
505
gchar *formatted = gnac_profiles_xml_engine_format_text_to_xml(value);
506
xmlNodeSetContent(node, BAD_CAST formatted);
510
name = va_arg(ap, const xmlChar *);
511
xmlAddChild(format_node, xmlNewText(name ? properties_indent : base_indent));
516
g_free(properties_indent);
517
xmlXPathFreeObject(xpath_obj);
522
gnac_profiles_xml_engine_format_text_to_xml(const gchar *text)
524
if (!text) return NULL;
526
return g_markup_escape_text(text, -1);
531
gnac_profiles_xml_engine_save_doc(XMLDoc *doc,
532
const gchar *filename)
534
gchar *path = g_strconcat(GNAC_SAVED_PROFILES_URL_WITH_EXT(filename), NULL);
535
xmlSaveFormatFile(path, doc->doc, 0);
541
gnac_profiles_xml_engine_free_doc_xpath(XMLDoc *doc)
545
xmlXPathFreeContext(doc->xpath_context);
546
xmlFreeDoc(doc->doc);
552
gnac_profiles_xml_engine_free_combo_values(ComboValues *values)
556
g_list_free_full(values->values, (GDestroyNotify) xmlFree);
557
g_list_free_full(values->names, (GDestroyNotify) g_free);
558
g_free(values->default_value);
559
g_free(values->variable_name);
565
gnac_profiles_xml_engine_free_slider_values(SliderValues *values)
569
g_free(values->variable_name);
575
gnac_profiles_xml_engine_free_check_values(CheckValues *values)
579
g_free(values->variable_name);