~ubuntu-branches/debian/stretch/gnac/stretch

« back to all changes in this revision

Viewing changes to src/profiles/gnac-profiles-xml-engine.c

  • Committer: Package Import Robot
  • Author(s): Khalid El Fathi
  • Date: 2012-04-14 20:15:31 UTC
  • Revision ID: package-import@ubuntu.com-20120414201531-2gcfq8fs94kgp9qr
Tags: upstream-0.2.4
ImportĀ upstreamĀ versionĀ 0.2.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is part of GNAC - Gnome Audio Converter
 
3
 *
 
4
 * Copyright (C) 2007 - 2012 Gnac
 
5
 *    
 
6
 *    - DUPASQUIER  Benoit    <bdupasqu@src.gnome.org>
 
7
 *    - JOAQUIM     David     <djoaquim@src.gnome.org>
 
8
 *    - ROUX        Alexandre <alexroux@src.gnome.org>
 
9
 *
 
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.
 
14
 *
 
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.
 
19
 *
 
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
 
24
 */
 
25
 
 
26
#ifdef HAVE_CONFIG_H
 
27
#include "config.h"
 
28
#endif
 
29
 
 
30
#include <glib/gi18n.h>
 
31
#include <glib/gstdio.h>
 
32
 
 
33
#include <libxml/xpath.h>
 
34
 
 
35
#include "gnac-profiles-xml-engine.h"
 
36
#include "gnac-profiles-utils.h"
 
37
#include "gnac-utils.h"
 
38
 
 
39
 
 
40
XMLDoc *
 
41
gnac_profiles_xml_engine_load_doc_xpath(const gchar *filename)
 
42
{
 
43
  xmlDocPtr doc = xmlParseFile(filename);
 
44
  if (!doc) return NULL;
 
45
 
 
46
  xmlXPathContextPtr xpath_context = xmlXPathNewContext(doc);
 
47
  if (!xpath_context) {
 
48
    xmlFreeDoc(doc);
 
49
    return NULL;
 
50
  }
 
51
 
 
52
  XMLDoc *dx = g_malloc(sizeof(XMLDoc));
 
53
  dx->doc = doc;
 
54
  dx->xpath_context = xpath_context;
 
55
 
 
56
  return dx;
 
57
}
 
58
 
 
59
 
 
60
static xmlXPathObjectPtr
 
61
gnac_profiles_xml_engine_evaluate_query(const gchar        *query,
 
62
                                        xmlXPathContextPtr  xpath_context)
 
63
{
 
64
  return xmlXPathEvalExpression(BAD_CAST query, xpath_context);
 
65
}
 
66
 
 
67
 
 
68
static gchar *
 
69
gnac_profiles_xml_engine_get_property(XMLDoc      *doc,
 
70
                                      const gchar *query,
 
71
                                      const gchar *property_name)
 
72
{
 
73
  xmlXPathObjectPtr xpath_obj = gnac_profiles_xml_engine_evaluate_query(
 
74
      query, doc->xpath_context);
 
75
  if (!xpath_obj) return NULL;
 
76
 
 
77
  xmlNodeSetPtr nodes = xpath_obj->nodesetval;
 
78
  if (xmlXPathNodeSetIsEmpty(nodes)) {
 
79
    xmlXPathFreeObject(xpath_obj);
 
80
    return NULL;
 
81
  }
 
82
 
 
83
  xmlChar *property = xmlGetProp(nodes->nodeTab[0], (xmlChar *) property_name);
 
84
 
 
85
  xmlXPathFreeObject(xpath_obj);
 
86
 
 
87
  return (gchar *) property;
 
88
}
 
89
 
 
90
 
 
91
gchar *
 
92
gnac_profiles_xml_engine_get_format_id(XMLDoc *doc)
 
93
{
 
94
  return gnac_profiles_xml_engine_get_property(doc, "//profiles/profile", "id");
 
95
}
 
96
 
 
97
 
 
98
gchar *
 
99
gnac_profiles_xml_engine_get_variable_type(XMLDoc      *doc,
 
100
                                           const gchar *expr)
 
101
{
 
102
  return gnac_profiles_xml_engine_get_property(doc, expr, "type");
 
103
}
 
104
 
 
105
 
 
106
gchar *
 
107
gnac_profiles_xml_engine_get_text_node(XMLDoc      *doc,
 
108
                                       const gchar *expr)
 
109
{
 
110
  xmlXPathObjectPtr xpath_obj = gnac_profiles_xml_engine_evaluate_query(
 
111
      expr, doc->xpath_context);
 
112
  if (!xpath_obj) return NULL;
 
113
 
 
114
  xmlNodeSetPtr nodes = xpath_obj->nodesetval;
 
115
  if (xmlXPathNodeSetIsEmpty(nodes)) {
 
116
    xmlXPathFreeObject(xpath_obj);
 
117
    return NULL;
 
118
  }
 
119
 
 
120
  xmlNodePtr node = nodes->nodeTab[0];
 
121
  if (!node || !(node->children)) {
 
122
    xmlXPathFreeObject(xpath_obj);
 
123
    return NULL;
 
124
  }
 
125
 
 
126
  xmlXPathFreeObject(xpath_obj);
 
127
 
 
128
  xmlChar *content = xmlNodeGetContent(node->children);
 
129
  gchar *translated = g_strdup(gettext((gchar *) content));
 
130
  xmlFree(content);
 
131
 
 
132
  return translated;
 
133
}
 
134
 
 
135
 
 
136
gchar *
 
137
gnac_profiles_xml_engine_query_name(XMLDoc      *doc,
 
138
                                    const gchar *format)
 
139
{
 
140
  gchar *query = g_strconcat("//profile[@id='", format, "']/name", NULL);
 
141
  gchar *name = gnac_profiles_xml_engine_get_text_node(doc, query);
 
142
  g_free(query);
 
143
  return name;
 
144
}
 
145
 
 
146
 
 
147
gchar *
 
148
gnac_profiles_xml_engine_query_extension(XMLDoc      *doc,
 
149
                                         const gchar *format)
 
150
{
 
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);
 
154
  g_free(query);
 
155
  return extension;
 
156
}
 
157
 
 
158
 
 
159
gchar *
 
160
gnac_profiles_xml_engine_query_description(XMLDoc      *doc,
 
161
                                           const gchar *format)
 
162
{
 
163
  gchar *query = g_strconcat("//profile[@id='", format, "']/description", NULL);
 
164
  gchar *description = gnac_profiles_xml_engine_get_text_node(doc, query);
 
165
  g_free(query);
 
166
  return description;
 
167
}
 
168
 
 
169
 
 
170
static gboolean
 
171
gnac_profiles_xml_engine_str_equal(const xmlChar *str1,
 
172
                                   const gchar   *str2)
 
173
{
 
174
  return gnac_utils_str_equal((const gchar *) str1, str2);
 
175
}
 
176
 
 
177
 
 
178
static gboolean
 
179
gnac_profiles_xml_engine_node_name_equal(xmlNode     *node,
 
180
                                         const gchar *name)
 
181
{
 
182
  return gnac_profiles_xml_engine_str_equal(node->name, name);
 
183
}
 
184
 
 
185
 
 
186
static gboolean
 
187
gnac_profiles_xml_engine_is_i18n_node(xmlNodePtr node)
 
188
{
 
189
  return gnac_profiles_xml_engine_str_equal(node->properties->name, "lang");
 
190
}
 
191
 
 
192
 
 
193
GList *
 
194
gnac_profiles_xml_engine_get_list_values(XMLDoc      *doc,
 
195
                                         const gchar *expr)
 
196
{
 
197
  xmlXPathObjectPtr  xpath_obj = gnac_profiles_xml_engine_evaluate_query(
 
198
      expr, doc->xpath_context);
 
199
  if (!xpath_obj) return NULL;
 
200
 
 
201
  xmlNodeSetPtr nodes = xpath_obj->nodesetval;
 
202
  if (xmlXPathNodeSetIsEmpty(nodes)) {
 
203
    xmlXPathFreeObject(xpath_obj);
 
204
    return NULL;
 
205
  }
 
206
 
 
207
  gint i;
 
208
  GList *list = NULL;
 
209
 
 
210
  for (i = 0; i < nodes->nodeNr; i++) {
 
211
    xmlNode *current_node = nodes->nodeTab[i];
 
212
    
 
213
    if (!gnac_profiles_xml_engine_is_i18n_node(current_node)) {
 
214
      Value *val = g_malloc(sizeof(Value));
 
215
      val->name = gettext(
 
216
          (gchar *) xmlNodeGetContent(current_node->children));
 
217
      val->value =
 
218
          (gchar *) xmlNodeGetContent(current_node->properties->children);
 
219
      list = g_list_prepend(list, val);
 
220
    }
 
221
  }
 
222
 
 
223
  xmlXPathFreeObject(xpath_obj);
 
224
 
 
225
  return g_list_reverse(list);
 
226
}
 
227
 
 
228
 
 
229
ComboValues *
 
230
gnac_profiles_xml_engine_get_combo_values(XMLDoc      *doc,
 
231
                                          const gchar *expr)
 
232
{
 
233
  xmlXPathObjectPtr xpath_obj = gnac_profiles_xml_engine_evaluate_query(
 
234
      expr, doc->xpath_context);
 
235
  if (!xpath_obj) return NULL;
 
236
 
 
237
  xmlNodeSetPtr nodes = xpath_obj->nodesetval;
 
238
  if (xmlXPathNodeSetIsEmpty(nodes)) {
 
239
    xmlXPathFreeObject(xpath_obj);
 
240
    return NULL;
 
241
  }
 
242
 
 
243
  xmlNode *values_first = NULL;
 
244
  xmlNode *values_last = NULL;
 
245
  gchar   *default_value = NULL;
 
246
  gchar   *variable_name = NULL;
 
247
 
 
248
  xmlNodePtr current_node = nodes->nodeTab[0]->children;
 
249
 
 
250
  while ((current_node = current_node->next)) {
 
251
    gchar *content = (gchar *) xmlNodeGetContent(current_node->children);
 
252
 
 
253
    if (gnac_profiles_xml_engine_node_name_equal(current_node,
 
254
        "variable-name"))
 
255
    {
 
256
      variable_name = g_strdup(content);
 
257
    }
 
258
    else if (gnac_profiles_xml_engine_node_name_equal(current_node,
 
259
        "default-value"))
 
260
    {
 
261
      default_value = g_strdup(content);
 
262
    }
 
263
    else if (gnac_profiles_xml_engine_node_name_equal(current_node,
 
264
        "possible-values"))
 
265
    {
 
266
      values_first = current_node->children->next;
 
267
      values_last = current_node->last;
 
268
    }
 
269
 
 
270
    g_free(content);
 
271
  }
 
272
 
 
273
  if (values_first && values_last && default_value && variable_name) {
 
274
    GList *values = NULL;
 
275
    GList *names = NULL;
 
276
 
 
277
    xmlNode *current_node = values_first;
 
278
 
 
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)));
 
285
        xmlFree(content);
 
286
      }
 
287
 
 
288
      current_node = current_node->next;
 
289
 
 
290
      if (xmlNodeIsText(current_node)) {
 
291
        current_node = current_node->next;
 
292
      }
 
293
    }
 
294
 
 
295
    xmlXPathFreeObject(xpath_obj);
 
296
 
 
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;
 
302
 
 
303
    return combo_values;
 
304
  }
 
305
  
 
306
  xmlXPathFreeObject(xpath_obj);
 
307
 
 
308
  return NULL;
 
309
}
 
310
 
 
311
 
 
312
SliderValues *
 
313
gnac_profiles_xml_engine_get_slider_values(XMLDoc      *doc,
 
314
                                          const gchar  *expr)
 
315
{
 
316
  xmlXPathObjectPtr xpath_obj = gnac_profiles_xml_engine_evaluate_query(
 
317
      expr, doc->xpath_context);
 
318
  if (!xpath_obj) return NULL;
 
319
 
 
320
  xmlNodeSetPtr nodes = xpath_obj->nodesetval;
 
321
  if (xmlXPathNodeSetIsEmpty(nodes)) {
 
322
    xmlXPathFreeObject(xpath_obj);
 
323
    return NULL;
 
324
  }
 
325
 
 
326
  gdouble  min = 0.0;
 
327
  gdouble  max = 0.0;
 
328
  gdouble  step = 0.0;
 
329
  gdouble  default_value = 0.0;
 
330
  gchar   *variable_name = NULL;
 
331
 
 
332
  xmlNodePtr current_node = nodes->nodeTab[0]->children;
 
333
 
 
334
  while ((current_node = current_node->next)) {
 
335
    gchar *content = (gchar *) xmlNodeGetContent(current_node->children);
 
336
 
 
337
    if (gnac_profiles_xml_engine_node_name_equal(current_node,
 
338
        "variable-name"))
 
339
    {
 
340
      variable_name = g_strdup(content);
 
341
    }
 
342
    else if (gnac_profiles_xml_engine_node_name_equal(current_node,
 
343
        "default-value"))
 
344
    {
 
345
      default_value = gnac_profiles_utils_gchararray_to_gdouble(content);
 
346
    }
 
347
    else if (gnac_profiles_xml_engine_node_name_equal(current_node,
 
348
        "min-value"))
 
349
    {
 
350
      min = gnac_profiles_utils_gchararray_to_gdouble(content);
 
351
    }
 
352
    else if (gnac_profiles_xml_engine_node_name_equal(current_node,
 
353
        "max-value"))
 
354
    {
 
355
      max = gnac_profiles_utils_gchararray_to_gdouble(content);
 
356
    }
 
357
    else if (gnac_profiles_xml_engine_node_name_equal(current_node,
 
358
        "step-value"))
 
359
    {
 
360
      step = gnac_profiles_utils_gchararray_to_gdouble(content);
 
361
    }
 
362
 
 
363
    g_free(content);
 
364
  }
 
365
 
 
366
  if (variable_name) {
 
367
    xmlXPathFreeObject(xpath_obj);
 
368
 
 
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;
 
375
 
 
376
    return slider_values;
 
377
  }
 
378
 
 
379
  xmlXPathFreeObject(xpath_obj);
 
380
 
 
381
  return NULL;
 
382
}
 
383
 
 
384
 
 
385
CheckValues *
 
386
gnac_profiles_xml_engine_get_check_values(XMLDoc      *doc,
 
387
                                          const gchar *expr)
 
388
{
 
389
  xmlXPathObjectPtr xpath_obj = gnac_profiles_xml_engine_evaluate_query(
 
390
      expr, doc->xpath_context);
 
391
  if (!xpath_obj) return NULL;
 
392
 
 
393
  xmlNodeSetPtr nodes = xpath_obj->nodesetval;
 
394
  if (xmlXPathNodeSetIsEmpty(nodes)) {
 
395
    xmlXPathFreeObject(xpath_obj);
 
396
    return NULL;
 
397
  }
 
398
 
 
399
  gchar    *variable_name = NULL;
 
400
  gboolean  default_value = FALSE;
 
401
 
 
402
  xmlNodePtr current_node = nodes->nodeTab[0]->children;
 
403
 
 
404
  while ((current_node = current_node->next)) {
 
405
    gchar *content = (gchar *) xmlNodeGetContent(current_node->children);
 
406
 
 
407
    if (gnac_profiles_xml_engine_node_name_equal(current_node,
 
408
        "variable-name"))
 
409
    {
 
410
      variable_name = g_strdup(content);
 
411
    }
 
412
    else if (gnac_profiles_xml_engine_node_name_equal(current_node,
 
413
        "default-value"))
 
414
    {
 
415
      default_value = gnac_utils_str_equal(content, "true");
 
416
    }
 
417
 
 
418
    g_free(content);
 
419
  }
 
420
 
 
421
  if (variable_name) {
 
422
    xmlXPathFreeObject(xpath_obj);
 
423
 
 
424
    CheckValues *check_values = g_malloc(sizeof(CheckValues));
 
425
    check_values->default_value = default_value;
 
426
    check_values->variable_name = variable_name;
 
427
 
 
428
    return check_values;
 
429
  }
 
430
 
 
431
  xmlXPathFreeObject(xpath_obj);
 
432
 
 
433
  return NULL;
 
434
}
 
435
 
 
436
 
 
437
void
 
438
gnac_profiles_xml_engine_modify_values(XMLDoc      *doc,
 
439
                                       const gchar *expr,
 
440
                                       ...)
 
441
{
 
442
  xmlXPathObjectPtr  xpath_obj = gnac_profiles_xml_engine_evaluate_query(
 
443
      expr, doc->xpath_context);
 
444
  if (!xpath_obj) return;
 
445
 
 
446
  xmlNodeSetPtr nodes = xpath_obj->nodesetval;
 
447
  if (xmlXPathNodeSetIsEmpty(nodes)) {
 
448
    xmlXPathFreeObject(xpath_obj);
 
449
    return;
 
450
  }
 
451
  
 
452
  va_list ap;
 
453
  va_start(ap, expr);
 
454
 
 
455
  gint i;
 
456
  const gchar *value = va_arg(ap, const gchar *);
 
457
 
 
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);
 
462
    
 
463
    if (nodes->nodeTab[i]->type != XML_NAMESPACE_DECL) {
 
464
      nodes->nodeTab[i] = NULL;
 
465
    }
 
466
    
 
467
    value = va_arg(ap, const gchar *);
 
468
  }
 
469
 
 
470
  xmlXPathFreeObject(xpath_obj);
 
471
}
 
472
 
 
473
 
 
474
void
 
475
gnac_profiles_xml_engine_add_values(XMLDoc *doc, ...)
 
476
{
 
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;
 
481
  
 
482
  xmlNodeSetPtr nodes = xpath_obj->nodesetval;
 
483
  if (xmlXPathNodeSetIsEmpty(nodes)) {
 
484
    xmlXPathFreeObject(xpath_obj);
 
485
    return;
 
486
  }
 
487
 
 
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 "  "));
 
493
 
 
494
  va_list ap;
 
495
  va_start(ap, doc);
 
496
 
 
497
  const xmlChar *name = va_arg(ap, const xmlChar *);
 
498
 
 
499
  while (name) {
 
500
    const gchar *value = va_arg(ap, const gchar *);
 
501
    xmlNodePtr node = xmlNewNode(format_node->ns, name);
 
502
    node = xmlAddChild(format_node, node);
 
503
 
 
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);
 
507
      g_free(formatted);
 
508
    }
 
509
    
 
510
    name = va_arg(ap, const xmlChar *);
 
511
    xmlAddChild(format_node, xmlNewText(name ? properties_indent : base_indent));
 
512
  }
 
513
 
 
514
  va_end(ap);
 
515
 
 
516
  g_free(properties_indent);
 
517
  xmlXPathFreeObject(xpath_obj);
 
518
}
 
519
 
 
520
 
 
521
gchar *
 
522
gnac_profiles_xml_engine_format_text_to_xml(const gchar *text)
 
523
{
 
524
  if (!text) return NULL;
 
525
 
 
526
  return g_markup_escape_text(text, -1);
 
527
}
 
528
 
 
529
 
 
530
void
 
531
gnac_profiles_xml_engine_save_doc(XMLDoc      *doc,
 
532
                                  const gchar *filename)
 
533
{
 
534
  gchar *path = g_strconcat(GNAC_SAVED_PROFILES_URL_WITH_EXT(filename), NULL);
 
535
  xmlSaveFormatFile(path, doc->doc, 0);
 
536
  g_free(path);
 
537
}
 
538
 
 
539
 
 
540
void
 
541
gnac_profiles_xml_engine_free_doc_xpath(XMLDoc *doc)
 
542
{
 
543
  if (!doc) return;
 
544
 
 
545
  xmlXPathFreeContext(doc->xpath_context);
 
546
  xmlFreeDoc(doc->doc);
 
547
  g_free(doc);
 
548
}
 
549
 
 
550
 
 
551
void
 
552
gnac_profiles_xml_engine_free_combo_values(ComboValues *values)
 
553
{
 
554
  if (!values) return;
 
555
 
 
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);
 
560
  g_free(values);
 
561
}
 
562
 
 
563
 
 
564
void
 
565
gnac_profiles_xml_engine_free_slider_values(SliderValues *values)
 
566
{
 
567
  if (!values) return;
 
568
 
 
569
  g_free(values->variable_name);
 
570
  g_free(values);
 
571
}
 
572
 
 
573
 
 
574
void
 
575
gnac_profiles_xml_engine_free_check_values(CheckValues *values)
 
576
{
 
577
  if (!values) return;
 
578
 
 
579
  g_free(values->variable_name);
 
580
  g_free(values);
 
581
}