Use g_str_equal and use long for id's internally
[laugh.git] / src / laugh-dom.c
blob2a592186da4f90be26db798c8abc3d62bef70635
1 /*
2 * Laugh.
4 * An glib SMIL library.
6 * Authored By Koos Vriezen <koos.vriezen@gmail.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
24 /**
25 * SECTION:laugh-io
26 * @short_description: DOM bases classes.
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
33 #include "laugh-dom.h"
34 #include "laugh-io.h"
35 #include "laugh-layout.h"
37 #include <string.h>
38 #include <expat.h>
39 #include <glib/gprintf.h>
41 #define LAUGH_NODE_GET_PRIVATE(obj) \
42 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), LAUGH_TYPE_NODE, LaughNodePrivate))
43 #define LAUGH_DOCUMENT_GET_PRIVATE(obj) \
44 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), LAUGH_TYPE_DOCUMENT, LaughDocumentPrivate))
46 enum
48 INITIALIZED,
49 STARTED,
50 STOPPED,
52 LAST_SIGNAL
55 typedef struct _DocumentBuilder
57 LaughNode *top_node;
58 LaughNode *current;
59 } DocumentBuilder;
61 typedef struct _LaughIdMapping
63 GHashTable *string_id;
64 GHashTable *id_string;
65 long string_unknown;
66 } LaughIdMapping;
68 static guint laugh_node_signals[LAST_SIGNAL] = { 0 };
70 static LaughIdMapping _laugh_tag_map;
71 static LaughIdMapping _laugh_attr_map;
74 struct _LaughNodePrivate
76 GHashTable *attributes;
79 static gpointer laugh_node_parent_class = ((void *)0);
81 static void laugh_node_finalize (GObject *object)
83 G_OBJECT_CLASS (laugh_node_parent_class)->finalize (object);
86 static void laugh_node_dispose (GObject *object)
88 LaughNode *node = LAUGH_NODE(object);
89 LaughNode *child;
91 if (node->priv->attributes)
92 g_hash_table_destroy (node->priv->attributes);
94 for (child = node->first_child; child; ) {
95 LaughNode *tmp = child->next_sibling;
96 g_object_unref (child);
97 child = tmp;
100 G_OBJECT_CLASS (laugh_node_parent_class)->dispose (object);
103 static
104 void _laugh_node_set_attribute (LaughNode *node,
105 LaughNodeAttributeId att, const gchar *val, gpointer *undo)
107 LaughNodePrivate *priv = node->priv;
109 /* TODO: create a dynamic attribute list, create or handle undo */
110 if (priv->attributes)
111 g_hash_table_insert (priv->attributes,
112 (gpointer) (long) att, (gpointer) val);
115 static const gchar *_laugh_node_get_attribute (LaughNode *node,
116 LaughNodeAttributeId att)
118 LaughNodePrivate *priv = node->priv;
120 if (priv->attributes)
121 return (gchar *) g_hash_table_lookup (
122 priv->attributes, (gpointer) (long) att);
123 return NULL;
126 static void _laugh_node_init (LaughNode *node, LaughInitializer *initializer)
128 LaughNode *child;
130 for (child = node->first_child; child; child = child->next_sibling)
131 laugh_node_init (child, initializer);
134 static void _laugh_add_mapping (LaughIdMapping *m, long id, const gchar *s)
136 g_hash_table_insert (m->string_id, (gpointer) s, (gpointer) id);
137 g_hash_table_insert (m->id_string, (gpointer) id, (gpointer) s);
140 static void laugh_node_class_init (LaughNodeClass *klass)
142 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
144 laugh_node_parent_class = g_type_class_peek_parent (klass);
146 gobject_class->finalize = laugh_node_finalize;
147 gobject_class->dispose = laugh_node_dispose;
148 klass->set_attribute = _laugh_node_set_attribute;
149 klass->get_attribute = _laugh_node_get_attribute;
150 klass->init = _laugh_node_init;
152 g_type_class_add_private (gobject_class, sizeof (LaughNodePrivate));
154 laugh_node_signals[INITIALIZED] =
155 g_signal_new ("initialized",
156 G_TYPE_FROM_CLASS (gobject_class),
157 G_SIGNAL_RUN_LAST,
158 G_STRUCT_OFFSET (LaughNodeClass, initialized),
159 NULL, NULL,
160 g_cclosure_marshal_VOID__VOID,
161 G_TYPE_NONE, 0);
163 laugh_node_signals[STARTED] =
164 g_signal_new ("started",
165 G_TYPE_FROM_CLASS (gobject_class),
166 G_SIGNAL_RUN_LAST,
167 G_STRUCT_OFFSET (LaughNodeClass, started),
168 NULL, NULL,
169 g_cclosure_marshal_VOID__VOID,
170 G_TYPE_NONE, 0);
172 laugh_node_signals[STOPPED] =
173 g_signal_new ("stopped",
174 G_TYPE_FROM_CLASS (gobject_class),
175 G_SIGNAL_RUN_LAST,
176 G_STRUCT_OFFSET (LaughNodeClass, stopped),
177 NULL, NULL,
178 g_cclosure_marshal_VOID__VOID,
179 G_TYPE_NONE, 0);
181 _laugh_tag_map.string_id = g_hash_table_new (g_str_hash, g_str_equal);
182 _laugh_tag_map.id_string = g_hash_table_new (NULL, NULL);
183 _laugh_tag_map.string_unknown = LaughTagIdLast;
185 _laugh_attr_map.string_id = g_hash_table_new (g_str_hash, g_str_equal);
186 _laugh_attr_map.id_string = g_hash_table_new (NULL, NULL);
187 _laugh_attr_map.string_unknown = LaughTagIdLast;
189 _laugh_add_mapping (&_laugh_tag_map, LaughTagIdSmil, "smil");
190 _laugh_add_mapping (&_laugh_tag_map, LaughTagIdHead, "head");
191 _laugh_add_mapping (&_laugh_tag_map, LaughTagIdLayout, "layout");
192 _laugh_add_mapping (&_laugh_tag_map, LaughTagIdRootLayout, "root-layout");
193 _laugh_add_mapping (&_laugh_tag_map, LaughTagIdRegion, "region");
194 _laugh_add_mapping (&_laugh_tag_map, LaughTagIdBody, "body");
195 _laugh_add_mapping (&_laugh_tag_map, LaughTagIdSeq, "seq");
196 _laugh_add_mapping (&_laugh_tag_map, LaughTagIdPar, "par");
197 _laugh_add_mapping (&_laugh_tag_map, LaughTagIdExcl, "excl");
198 _laugh_add_mapping (&_laugh_tag_map, LaughTagIdSwitch, "switch");
199 _laugh_add_mapping (&_laugh_tag_map, LaughTagIdAudio, "audio");
200 _laugh_add_mapping (&_laugh_tag_map, LaughTagIdImg, "img");
201 _laugh_add_mapping (&_laugh_tag_map, LaughTagIdRef, "ref");
202 _laugh_add_mapping (&_laugh_tag_map, LaughTagIdText, "text");
203 _laugh_add_mapping (&_laugh_tag_map, LaughTagIdVideo, "video");
205 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdId, "id");
206 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdName, "name");
207 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdLeft, "left");
208 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdTop, "top");
209 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdWidth, "width");
210 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdHeight, "height");
211 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdBgColor, "background-color");
212 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdBgColor1, "backgroundColor");
213 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdBgImage, "backgroundImage");
214 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdShowBg, "showBackground");
215 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdZIndex, "z-index");
216 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdBegin, "begin");
217 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdDur, "dur");
218 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdEnd, "end");
219 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdEndSync, "endSync");
220 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdRepeat, "repeat");
221 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdSrc, "src");
222 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdType, "type");
223 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdSubType, "subType");
224 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdFill, "fil");
225 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdFit, "fit");
226 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdPeers, "peers");
227 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdHigher, "higher");
228 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdLower, "lower");
229 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdPauseDisplay, "pauseDisplay");
230 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdHRef, "href");
231 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdCoord, "coord");
232 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdTransIn, "trans-in");
233 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdTransOut, "trans-out");
234 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdSystemBitrate, "system-bitrate");
235 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdSensitivity, "sensitivity");
236 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdFontColor, "fontColor");
237 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdFontSize, "fontSize");
238 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdHAlign, "hAlign");
239 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdVAlign, "vAlign");
240 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdCharset, "charset");
241 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdBgOpacity, "backgroundOpacity");
242 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdTargetAttr, "targetAttribute");
243 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdTarget, "target");
244 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdAttr, "attribute");
245 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdAttrName, "attributeName");
246 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdTo, "to");
247 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdChangeBy, "changed-by");
248 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdFrom, "from");
249 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdValues, "values");
250 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdCalcMode, "calcMode");
251 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdKeyTimes, "keyTimes");
252 _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdKeySplines, "keySplines");
255 static void laugh_node_instance_init (GTypeInstance *instance, gpointer g_class)
257 LaughNode *self = (LaughNode *)instance;
259 self->priv = LAUGH_NODE_GET_PRIVATE (self);
261 self->parent_node = NULL;
262 self->first_child = NULL;
263 self->previous_sibling = NULL;
264 self->next_sibling = NULL;
265 self->priv->attributes = NULL;
268 GType laugh_node_get_type (void)
270 static GType type = 0;
271 if (type == 0) {
272 static const GTypeInfo info = {
273 sizeof (LaughNodeClass),
274 NULL, /* base_init */
275 NULL, /* base_finalize */
276 (GClassInitFunc) laugh_node_class_init, /* class_init */
277 NULL, /* class_finalize */
278 NULL, /* class_data */
279 sizeof (LaughNode),
280 0, /* n_preallocs */
281 laugh_node_instance_init /* instance_init */
283 type = g_type_register_static (G_TYPE_OBJECT,
284 "LaughNodeType",
285 &info, 0);
287 return type;
290 struct _LaughDocumentPrivate
292 gchar *uri;
293 LaughIO *io;
296 static gpointer laugh_document_parent_class = ((void *)0);
298 static void laugh_document_finalize (GObject *object)
300 G_OBJECT_CLASS (laugh_document_parent_class)->finalize (object);
303 static void laugh_document_dispose (GObject *object)
305 LaughDocument *document = LAUGH_DOCUMENT(object);
307 g_free (document->priv->uri);
309 G_OBJECT_CLASS (laugh_document_parent_class)->dispose (object);
312 static
313 void _lauch_document_mime_type (LaughIO *io, const gchar *mime, gpointer d)
315 g_printf ("lauch_document_mime_type: %s\n", mime);
316 if (strcmp (mime, "application/smil")) {
317 LaughNode *node = LAUGH_NODE (d);
319 g_printerr ("not a smil document\n");
320 laugh_io_cancel (io);
322 g_object_unref (G_OBJECT (io));
324 laugh_node_base_emit_initialized (node);
328 static void
329 _lauch_document_completed (LaughIO *io, gsize sz, gpointer data, gpointer d)
331 LaughNode *node = LAUGH_NODE (d);
333 g_printf ("_lauch_document_completed: %u\n", sz);
334 if (data) {
335 laugh_node_set_inner_xml (node, (const gchar *) data);
337 g_free (data);
339 g_object_unref (G_OBJECT (io));
341 /*TODO init children and wait for initialized signals*/
342 laugh_node_base_emit_initialized (node);
345 static void _laugh_document_init (LaughNode *doc, LaughInitializer *initializer)
347 LaughDocumentPrivate *priv = LAUGH_DOCUMENT (doc)->priv;
349 priv->io = laugh_io_new (priv->uri);
351 g_signal_connect (G_OBJECT (priv->io), "mime-type",
352 (GCallback) _lauch_document_mime_type, (gpointer) doc);
353 g_signal_connect (G_OBJECT (priv->io), "completed",
354 (GCallback) _lauch_document_completed, (gpointer) doc);
356 laugh_io_open (priv->io);
359 static void laugh_document_class_init (LaughDocumentClass *klass)
361 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
362 LaughNodeClass *node_class = (LaughNodeClass *) klass;
364 laugh_document_parent_class = g_type_class_peek_parent (klass);
366 gobject_class->finalize = laugh_document_finalize;
367 gobject_class->dispose = laugh_document_dispose;
368 node_class->init = _laugh_document_init;
370 g_type_class_add_private (gobject_class, sizeof (LaughDocumentPrivate));
373 static
374 void laugh_document_instance_init (GTypeInstance *instance, gpointer g_class)
376 LaughDocument *self = (LaughDocument *)instance;
378 self->priv = LAUGH_DOCUMENT_GET_PRIVATE (self);
381 GType laugh_document_get_type (void)
383 static GType type = 0;
384 if (type == 0) {
385 static const GTypeInfo info = {
386 sizeof (LaughDocumentClass),
387 NULL, /* base_init */
388 NULL, /* base_finalize */
389 (GClassInitFunc) laugh_document_class_init, /* class_init */
390 NULL, /* class_finalize */
391 NULL, /* class_data */
392 sizeof (LaughDocument),
393 0, /* n_preallocs */
394 laugh_document_instance_init /* instance_init */
396 type = g_type_register_static (LAUGH_TYPE_NODE,
397 "LaughDocumentType",
398 &info, 0);
400 return type;
403 static long _laugh_mapping_from_string (LaughIdMapping *map, const gchar *tag)
405 gpointer id = g_hash_table_lookup (map->string_id, (gpointer) tag);
406 if (!id) {
407 id = (gpointer) map->string_unknown++;
408 _laugh_add_mapping (map, (long) id, g_strdup (tag));
410 return (LaughNodeTagId) (long) id;
413 LaughNodeTagId laugh_tag_from_string (const gchar *tag)
415 return (LaughNodeTagId) _laugh_mapping_from_string (&_laugh_tag_map, tag);
418 const gchar *laugh_tag_from_id (LaughNodeTagId id)
420 return (const gchar *) g_hash_table_lookup (_laugh_tag_map.id_string,
421 (gpointer) id);
424 LaughNodeAttributeId laugh_attribute_from_string (const gchar *attr)
426 return (LaughNodeAttributeId)_laugh_mapping_from_string (
427 &_laugh_attr_map, attr);
430 const gchar *laugh_attribute_from_id (LaughNodeAttributeId id)
432 return (const gchar *) g_hash_table_lookup (_laugh_attr_map.id_string,
433 (gpointer) id);
436 LaughNode *laugh_node_new (LaughDocument *document, LaughNodeTagId id,
437 GHashTable *attrs)
439 LaughNode *node = LAUGH_NODE (g_object_new (LAUGH_TYPE_NODE, NULL));
441 laugh_node_base_init (document, node, id, attrs);
443 return node;
446 LaughDocument *laugh_document_new (const gchar *uri)
448 LaughDocument *d = LAUGH_DOCUMENT(g_object_new (LAUGH_TYPE_DOCUMENT, NULL));
449 LaughNode *node = (LaughNode *)d;
451 laugh_node_base_init (d, node, LaughTagIdDocument, NULL);
452 d->priv->uri = g_strdup (uri);
454 return d;
457 void laugh_node_base_init (LaughDocument *document, LaughNode *node,
458 LaughNodeTagId id, GHashTable *attributes)
460 node->id = id;
461 node->document = document;
462 node->priv->attributes = attributes;
465 void laugh_node_base_emit_initialized (LaughNode *node)
467 g_signal_emit (node, laugh_node_signals[INITIALIZED], 0);
470 const gchar *laugh_node_get_attribute (LaughNode *node,
471 LaughNodeAttributeId attribute)
473 LaughNodeClass *klass = LAUGH_NODE_GET_CLASS(node);
475 return klass->get_attribute (node, attribute);
478 void laugh_node_set_attribute (LaughNode *node,
479 LaughNodeAttributeId attr, const gchar *value, gpointer *undo)
481 LaughNodeClass *klass = LAUGH_NODE_GET_CLASS(node);
483 klass->set_attribute (node, attr, value, undo);
486 static
487 void _laugh_xml_start_tag (void *data, const char *tag, const char **attr)
489 DocumentBuilder *builder = (DocumentBuilder *) data;
490 LaughNode *node;
491 GHashTable *attrs = NULL;
492 LaughNodeTagId id = laugh_tag_from_string (tag);
494 if (attr && attr[0]) {
495 int i;
496 attrs = g_hash_table_new_full (
497 NULL, NULL, NULL, (GDestroyNotify) g_free);
498 for (i = 0; attr[i]; i += 2)
499 g_hash_table_insert (attrs,
500 (gpointer) (long) laugh_attribute_from_string (attr[i]),
501 g_strdup (attr[i+1]));
503 switch (id) {
504 case LaughTagIdLayout:
505 case LaughTagIdRootLayout:
506 case LaughTagIdRegion:
507 node = laugh_layout_new (builder->top_node->document, id, attrs);
508 break;
509 default:
510 node = laugh_node_new (builder->top_node->document, id, attrs);
512 laugh_node_append_child (builder->current, node);
514 builder->current = node;
517 static void _laugh_xml_end_tag (void *data, const char *tag)
519 DocumentBuilder *builder = (DocumentBuilder *) data;
521 if (laugh_tag_from_string (tag) != builder->current->id)
522 g_printerr ("unmatched tag %s, expects %s\n",
523 tag, laugh_tag_from_id (builder->current->id));
524 else if (builder->current != builder->top_node)
525 builder->current = builder->current->parent_node;
526 else
527 g_printerr ("spurious end tag %s", tag);
530 void laugh_node_set_inner_xml (LaughNode *node, const gchar *xml)
532 DocumentBuilder builder;
533 XML_Parser parser = XML_ParserCreate (0L);
535 /*TODO: clear all node's child nodes*/
536 builder.top_node = node;
537 builder.current = node;
539 XML_SetUserData (parser, &builder);
540 XML_SetElementHandler (parser, _laugh_xml_start_tag, _laugh_xml_end_tag);
542 if (XML_Parse (parser, xml, strlen (xml), TRUE) == XML_STATUS_ERROR) {
543 /*TODO: clear all*/
546 XML_ParserFree(parser);
549 static void _laugh_node_get_outer_xml (LaughNode *node, GString *buffer, int sp)
551 LaughNodePrivate *priv = node->priv;
552 gchar *indent = "";
554 if (sp > 0) {
555 indent = (gchar *) g_malloc (sp + 1);
556 memset (indent, ' ', sp);
557 indent[sp] = 0;
558 g_string_append (buffer, indent);
561 g_string_append_c (buffer, '<');
562 g_string_append (buffer, laugh_tag_from_id (node->id));
563 if (priv->attributes) {
564 GHashTableIter iter;
565 gpointer key, value;
566 g_hash_table_iter_init (&iter, priv->attributes);
567 while (g_hash_table_iter_next (&iter, &key, &value)) {
568 g_string_append_c (buffer, ' ');
569 g_string_append (buffer, laugh_attribute_from_id ((long) key));
570 g_string_append (buffer, "=\"");
571 g_string_append (buffer, (const gchar *)value);/*TODO escape*/
572 g_string_append_c (buffer, '"');
575 if (node->first_child) {
576 LaughNode *child;
577 g_string_append (buffer, ">\n");
578 for (child = node->first_child; child; child = child->next_sibling)
579 _laugh_node_get_outer_xml (child, buffer, sp+2);
580 g_string_append (buffer, indent);
581 g_string_append (buffer, "</");
582 g_string_append (buffer, laugh_tag_from_id (node->id));
583 g_string_append (buffer, ">\n");
584 } else {
585 g_string_append (buffer, "/>\n");
588 if (*indent)
589 g_free (indent);
592 gchar *laugh_node_get_inner_xml (LaughNode *node)
594 GString *buffer = g_string_new ("");
595 LaughNode *child;
596 gchar *xml;
598 for (child = node->first_child; child; child = child->next_sibling)
599 _laugh_node_get_outer_xml (child, buffer, 0);
601 xml = g_string_free (buffer, FALSE);
603 return xml;
606 void laugh_node_append_child (LaughNode *node, LaughNode *child)
608 LaughNode *n = node->last_child;
610 if (n) {
611 n->next_sibling = child;
612 child->previous_sibling = n;
613 child->next_sibling = NULL;
614 } else {
615 node->first_child = child;
616 child->previous_sibling = NULL;
617 child->next_sibling = NULL;
619 node->last_child = child;
620 child->parent_node = node;
623 void laugh_node_init (LaughNode *node, LaughInitializer *initializer)
625 LaughNodeClass *klass = LAUGH_NODE_GET_CLASS(node);
627 klass->init (node, initializer);
630 #ifdef LAUGH_DOM_TEST
631 /* gcc laugh-dom.c laugh-io.c -o domtest `pkg-config --libs --cflags gio-2.0 glib-2.0 gthread-2.0` -lexpat */
632 #include <unistd.h>
633 #include <sys/types.h>
634 #include <sys/stat.h>
635 #include <fcntl.h>
637 static GMainLoop *mainloop;
639 void initialized_callback (LaughNode *node, gpointer d)
641 gchar *xml = laugh_node_get_inner_xml (node);
642 g_printf ("cb initialized\n%s\n", xml);
644 g_free (xml);
646 g_main_loop_quit (mainloop);
649 int main (int argc, char **argv)
651 LaughDocument *doc;
652 LaughInitializer initializer;
654 if (argc < 2) {
655 g_printerr ("usage %s uri\n", argv[0]);
656 return 1;
659 g_thread_init (NULL);
660 g_type_init ();
662 doc = laugh_document_new (argv[1]);
664 g_signal_connect (G_OBJECT (doc), "initialized",
665 (GCallback) initialized_callback, (gpointer) 0);
667 laugh_node_init (LAUGH_NODE (doc), &initializer);
669 mainloop = g_main_loop_new (NULL, TRUE);
670 g_main_loop_run (mainloop);
672 g_object_unref (G_OBJECT (doc));
674 return 0;
677 #endif