Update to gupnp-av-0.12.4
[profile/ivi/GUPnP-AV.git] / libgupnp-av / gupnp-didl-lite-object.c
1 /*
2  * Copyright (C) 2009 Nokia Corporation.
3  * Copyright (C) 2012 Intel Corporation
4  *
5  * Authors: Zeeshan Ali (Khattak) <zeeshan.ali@nokia.com>
6  *                                <zeeshanak@gnome.org>
7  *          Krzesimir Nowak <krnowak@openismus.com>
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public
20  * License along with this library; if not, write to the
21  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24
25 /**
26  * SECTION:gupnp-didl-lite-object
27  * @short_description: DIDL-Lite Object
28  *
29  * #GUPnPDIDLLiteObject respresent a DIDL-Lite object element.
30  */
31
32 #include <string.h>
33 #include <libgupnp/gupnp.h>
34
35 #include "gupnp-didl-lite-object.h"
36 #include "gupnp-didl-lite-object-private.h"
37 #include "gupnp-didl-lite-resource-private.h"
38 #include "gupnp-didl-lite-descriptor-private.h"
39 #include "gupnp-didl-lite-container.h"
40 #include "gupnp-didl-lite-item.h"
41 #include "gupnp-didl-lite-contributor-private.h"
42 #include "xml-util.h"
43 #include "fragment-util.h"
44 #include "xsd-data.h"
45
46 G_DEFINE_ABSTRACT_TYPE (GUPnPDIDLLiteObject,
47                         gupnp_didl_lite_object,
48                         G_TYPE_OBJECT);
49
50 struct _GUPnPDIDLLiteObjectPrivate {
51         xmlNode     *xml_node;
52         GUPnPXMLDoc *xml_doc;
53
54         xmlNs *upnp_ns;
55         xmlNs *dc_ns;
56         xmlNs *dlna_ns;
57         xmlNs *pv_ns;
58 };
59
60 static XSDData *didl_lite_xsd;
61
62 enum {
63         PROP_0,
64         PROP_XML_NODE,
65         PROP_XML_DOC,
66         PROP_UPNP_NAMESPACE,
67         PROP_DC_NAMESPACE,
68         PROP_DLNA_NAMESPACE,
69         PROP_PV_NAMESPACE,
70         PROP_ID,
71         PROP_PARENT_ID,
72         PROP_RESTRICTED,
73         PROP_TITLE,
74         PROP_UPNP_CLASS,
75         PROP_CREATOR,
76         PROP_ARTIST,
77         PROP_AUTHOR,
78         PROP_GENRE,
79         PROP_WRITE_STATUS,
80         PROP_ALBUM,
81         PROP_ALBUM_ART,
82         PROP_DESCRIPTION,
83         PROP_DATE,
84         PROP_TRACK_NUMBER,
85         PROP_DLNA_MANAGED,
86         PROP_UPDATE_ID
87 };
88
89 static int
90 is_non_transcoded_resource (GUPnPDIDLLiteResource *resource)
91 {
92         GUPnPProtocolInfo *info;
93
94         info = gupnp_didl_lite_resource_get_protocol_info (resource);
95         if (G_UNLIKELY (info == NULL))
96                 return -1;
97
98         return gupnp_protocol_info_get_dlna_conversion (info) &
99                GUPNP_DLNA_CONVERSION_TRANSCODED;
100 }
101
102 static void
103 gupnp_didl_lite_object_init (GUPnPDIDLLiteObject *object)
104 {
105         object->priv = G_TYPE_INSTANCE_GET_PRIVATE
106                                         (object,
107                                          GUPNP_TYPE_DIDL_LITE_OBJECT,
108                                          GUPnPDIDLLiteObjectPrivate);
109 }
110
111 static void
112 gupnp_didl_lite_object_set_property (GObject      *object,
113                                      guint         property_id,
114                                      const GValue *value,
115                                      GParamSpec   *pspec)
116
117 {
118         GUPnPDIDLLiteObject *didl_object;
119
120         didl_object = GUPNP_DIDL_LITE_OBJECT (object);
121
122         switch (property_id) {
123         case PROP_XML_NODE:
124                 didl_object->priv->xml_node = g_value_get_pointer (value);
125                 break;
126         case PROP_XML_DOC:
127                 didl_object->priv->xml_doc = g_value_dup_object (value);
128                 break;
129         case PROP_UPNP_NAMESPACE:
130                 didl_object->priv->upnp_ns = g_value_get_pointer (value);
131                 break;
132         case PROP_DC_NAMESPACE:
133                 didl_object->priv->dc_ns = g_value_get_pointer (value);
134                 break;
135         case PROP_DLNA_NAMESPACE:
136                 didl_object->priv->dlna_ns = g_value_get_pointer (value);
137                 break;
138         case PROP_PV_NAMESPACE:
139                 didl_object->priv->pv_ns = g_value_get_pointer (value);
140                 break;
141         case PROP_ID:
142                 gupnp_didl_lite_object_set_id (didl_object,
143                                                g_value_get_string (value));
144                 break;
145         case PROP_PARENT_ID:
146                 gupnp_didl_lite_object_set_parent_id
147                                         (didl_object,
148                                          g_value_get_string (value));
149                 break;
150         case PROP_RESTRICTED:
151                 gupnp_didl_lite_object_set_restricted
152                                         (didl_object,
153                                          g_value_get_boolean (value));
154                 break;
155         case PROP_TITLE:
156                 gupnp_didl_lite_object_set_title
157                                         (didl_object,
158                                          g_value_get_string (value));
159                 break;
160         case PROP_UPNP_CLASS:
161                 gupnp_didl_lite_object_set_upnp_class
162                                         (didl_object,
163                                          g_value_get_string (value));
164                 break;
165         case PROP_CREATOR:
166                 gupnp_didl_lite_object_set_creator
167                                         (didl_object,
168                                          g_value_get_string (value));
169                 break;
170         case PROP_ARTIST:
171                 gupnp_didl_lite_object_set_artist
172                                         (didl_object,
173                                          g_value_get_string (value));
174                 break;
175         case PROP_AUTHOR:
176                 gupnp_didl_lite_object_set_author
177                                         (didl_object,
178                                          g_value_get_string (value));
179                 break;
180         case PROP_GENRE:
181                 gupnp_didl_lite_object_set_genre
182                                         (didl_object,
183                                          g_value_get_string (value));
184                 break;
185         case PROP_WRITE_STATUS:
186                 gupnp_didl_lite_object_set_write_status
187                                         (didl_object,
188                                          g_value_get_string (value));
189                 break;
190         case PROP_ALBUM:
191                 gupnp_didl_lite_object_set_album
192                                         (didl_object,
193                                          g_value_get_string (value));
194                 break;
195         case PROP_ALBUM_ART:
196                 gupnp_didl_lite_object_set_album_art
197                                         (didl_object,
198                                          g_value_get_string (value));
199                 break;
200         case PROP_DESCRIPTION:
201                 gupnp_didl_lite_object_set_description
202                                         (didl_object,
203                                          g_value_get_string (value));
204                 break;
205         case PROP_DATE:
206                 gupnp_didl_lite_object_set_date
207                                         (didl_object,
208                                          g_value_get_string (value));
209                 break;
210         case PROP_TRACK_NUMBER:
211                 gupnp_didl_lite_object_set_track_number
212                                         (didl_object,
213                                          g_value_get_int (value));
214                 break;
215         case PROP_DLNA_MANAGED:
216                 gupnp_didl_lite_object_set_dlna_managed
217                                         (didl_object,
218                                          g_value_get_flags (value));
219                 break;
220         case PROP_UPDATE_ID:
221                 gupnp_didl_lite_object_set_update_id
222                                         (didl_object,
223                                          g_value_get_uint (value));
224                 break;
225         default:
226                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
227                 break;
228         }
229 }
230
231 static void
232 gupnp_didl_lite_object_get_property (GObject    *object,
233                                      guint       property_id,
234                                      GValue     *value,
235                                      GParamSpec *pspec)
236 {
237         GUPnPDIDLLiteObject *didl_object;
238
239         didl_object = GUPNP_DIDL_LITE_OBJECT (object);
240
241         switch (property_id) {
242         case PROP_XML_NODE:
243                 g_value_set_pointer
244                         (value,
245                          gupnp_didl_lite_object_get_xml_node (didl_object));
246                 break;
247         case PROP_UPNP_NAMESPACE:
248                 g_value_set_pointer
249                         (value,
250                          gupnp_didl_lite_object_get_upnp_namespace
251                                 (didl_object));
252                 break;
253         case PROP_DC_NAMESPACE:
254                 g_value_set_pointer
255                         (value,
256                          gupnp_didl_lite_object_get_dc_namespace
257                                 (didl_object));
258                 break;
259         case PROP_DLNA_NAMESPACE:
260                 g_value_set_pointer
261                         (value,
262                          gupnp_didl_lite_object_get_dlna_namespace
263                                 (didl_object));
264                 break;
265         case PROP_PV_NAMESPACE:
266                 g_value_set_pointer
267                         (value,
268                          gupnp_didl_lite_object_get_pv_namespace
269                                 (didl_object));
270                 break;
271         case PROP_ID:
272                 g_value_set_string
273                         (value,
274                          gupnp_didl_lite_object_get_id (didl_object));
275                 break;
276         case PROP_PARENT_ID:
277                 g_value_set_string
278                         (value,
279                          gupnp_didl_lite_object_get_parent_id (didl_object));
280                 break;
281         case PROP_RESTRICTED:
282                 g_value_set_boolean
283                         (value,
284                          gupnp_didl_lite_object_get_restricted (didl_object));
285                 break;
286         case PROP_TITLE:
287                 g_value_set_string
288                         (value,
289                          gupnp_didl_lite_object_get_title (didl_object));
290                 break;
291         case PROP_UPNP_CLASS:
292                 g_value_set_string
293                         (value,
294                          gupnp_didl_lite_object_get_upnp_class (didl_object));
295                 break;
296         case PROP_CREATOR:
297                 g_value_set_string
298                         (value,
299                          gupnp_didl_lite_object_get_creator (didl_object));
300                 break;
301         case PROP_ARTIST:
302                 g_value_set_string
303                         (value,
304                          gupnp_didl_lite_object_get_artist (didl_object));
305                 break;
306         case PROP_AUTHOR:
307                 g_value_set_string
308                         (value,
309                          gupnp_didl_lite_object_get_author (didl_object));
310                 break;
311         case PROP_GENRE:
312                 g_value_set_string
313                         (value,
314                          gupnp_didl_lite_object_get_genre (didl_object));
315                 break;
316         case PROP_WRITE_STATUS:
317                 g_value_set_string
318                         (value,
319                          gupnp_didl_lite_object_get_write_status (didl_object));
320                 break;
321         case PROP_ALBUM:
322                 g_value_set_string
323                         (value,
324                          gupnp_didl_lite_object_get_album (didl_object));
325                 break;
326         case PROP_ALBUM_ART:
327                 g_value_set_string
328                         (value,
329                          gupnp_didl_lite_object_get_album_art (didl_object));
330                 break;
331         case PROP_DESCRIPTION:
332                 g_value_set_string
333                         (value,
334                          gupnp_didl_lite_object_get_description (didl_object));
335                 break;
336         case PROP_DATE:
337                 g_value_set_string
338                         (value,
339                          gupnp_didl_lite_object_get_date (didl_object));
340                 break;
341         case PROP_TRACK_NUMBER:
342                 g_value_set_int
343                         (value,
344                          gupnp_didl_lite_object_get_track_number (didl_object));
345                 break;
346         case PROP_DLNA_MANAGED:
347                 g_value_set_flags
348                         (value,
349                          gupnp_didl_lite_object_get_dlna_managed (didl_object));
350                 break;
351         case PROP_UPDATE_ID:
352                 g_value_set_uint
353                         (value,
354                          gupnp_didl_lite_object_get_update_id (didl_object));
355                 break;
356         default:
357                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
358                 break;
359         }
360 }
361
362 static void
363 gupnp_didl_lite_object_dispose (GObject *object)
364 {
365         GObjectClass               *object_class;
366         GUPnPDIDLLiteObjectPrivate *priv;
367
368         priv = GUPNP_DIDL_LITE_OBJECT (object)->priv;
369
370         if (priv->xml_doc) {
371                 g_object_unref (priv->xml_doc);
372                 priv->xml_doc = NULL;
373         }
374
375         object_class = G_OBJECT_CLASS (gupnp_didl_lite_object_parent_class);
376         object_class->dispose (object);
377 }
378
379 static void
380 gupnp_didl_lite_object_class_init (GUPnPDIDLLiteObjectClass *klass)
381 {
382         GObjectClass *object_class;
383
384         object_class = G_OBJECT_CLASS (klass);
385
386         object_class->set_property = gupnp_didl_lite_object_set_property;
387         object_class->get_property = gupnp_didl_lite_object_get_property;
388         object_class->dispose = gupnp_didl_lite_object_dispose;
389
390         g_type_class_add_private (klass, sizeof (GUPnPDIDLLiteObjectPrivate));
391
392         /**
393          * GUPnPDIDLLiteObject:xml-node:
394          *
395          * The pointer to object node in XML document.
396          **/
397         g_object_class_install_property
398                 (object_class,
399                  PROP_XML_NODE,
400                  g_param_spec_pointer ("xml-node",
401                                        "XMLNode",
402                                        "The pointer to object node in XML"
403                                        " document.",
404                                        G_PARAM_READWRITE |
405                                        G_PARAM_CONSTRUCT_ONLY |
406                                        G_PARAM_STATIC_NAME |
407                                        G_PARAM_STATIC_NICK |
408                                        G_PARAM_STATIC_BLURB));
409
410         /**
411          * GUPnPDIDLLiteObject:xml-doc:
412          *
413          * The reference to XML document containing this object.
414          *
415          * Internal property.
416          *
417          * Stability: Private
418          **/
419         g_object_class_install_property
420                 (object_class,
421                  PROP_XML_DOC,
422                  g_param_spec_object ("xml-doc",
423                                       "XMLDoc",
424                                       "The reference to XML document"
425                                       " containing this object.",
426                                       GUPNP_TYPE_XML_DOC,
427                                       G_PARAM_WRITABLE |
428                                       G_PARAM_CONSTRUCT_ONLY |
429                                       G_PARAM_STATIC_NAME |
430                                       G_PARAM_STATIC_NICK |
431                                       G_PARAM_STATIC_BLURB));
432
433         /**
434          * GUPnPDIDLLiteObject:upnp-namespace:
435          *
436          * Pointer to the UPnP namespace registered with the XML document
437          * containing this object.
438          *
439          **/
440         g_object_class_install_property
441                 (object_class,
442                  PROP_UPNP_NAMESPACE,
443                  g_param_spec_pointer ("upnp-namespace",
444                                        "XML namespace",
445                                        "Pointer to the UPnP XML namespace "
446                                        "registered with the XML document "
447                                        "containing this object.",
448                                        G_PARAM_READWRITE |
449                                        G_PARAM_CONSTRUCT_ONLY |
450                                        G_PARAM_STATIC_NAME |
451                                        G_PARAM_STATIC_NICK |
452                                        G_PARAM_STATIC_BLURB));
453
454         /**
455          * GUPnPDIDLLiteObject:dc-namespace:
456          *
457          * Pointer to the DublinCore namespace registered with the XML document
458          * containing this object.
459          *
460          **/
461         g_object_class_install_property
462                 (object_class,
463                  PROP_DC_NAMESPACE,
464                  g_param_spec_pointer ("dc-namespace",
465                                        "XML namespace",
466                                        "Pointer to the Dublin Core XML "
467                                        "namespace registered with the XML "
468                                        "document containing this object.",
469                                        G_PARAM_READWRITE |
470                                        G_PARAM_CONSTRUCT_ONLY |
471                                        G_PARAM_STATIC_NAME |
472                                        G_PARAM_STATIC_NICK |
473                                        G_PARAM_STATIC_BLURB));
474
475         /**
476          * GUPnPDIDLLiteObject:dlna-namespace:
477          *
478          * Pointer to the DLNA metadata namespace registered with the XML
479          * document containing this object.
480          *
481          **/
482         g_object_class_install_property
483                 (object_class,
484                  PROP_DLNA_NAMESPACE,
485                  g_param_spec_pointer ("dlna-namespace",
486                                        "XML namespace",
487                                        "Pointer to the DLNA metadata namespace "
488                                        "registered with the XML document "
489                                        "containing this object.",
490                                        G_PARAM_READWRITE |
491                                        G_PARAM_CONSTRUCT_ONLY |
492                                        G_PARAM_STATIC_NAME |
493                                        G_PARAM_STATIC_NICK |
494                                        G_PARAM_STATIC_BLURB));
495
496         /**
497          * GUPnPDIDLLiteObject:pv-namespace:
498          *
499          * Pointer to the PV metadata namespace registered with the XML
500          * document containing this object.
501          *
502          **/
503         g_object_class_install_property
504                 (object_class,
505                  PROP_PV_NAMESPACE,
506                  g_param_spec_pointer ("pv-namespace",
507                                        "XML namespace",
508                                        "Pointer to the PV metadata namespace "
509                                        "registered with the XML document "
510                                        "containing this object.",
511                                        G_PARAM_READWRITE |
512                                        G_PARAM_CONSTRUCT_ONLY |
513                                        G_PARAM_STATIC_STRINGS));
514
515         /**
516          * GUPnPDIDLLiteObject:id:
517          *
518          * The ID of this object.
519          **/
520         g_object_class_install_property
521                 (object_class,
522                  PROP_ID,
523                  g_param_spec_string ("id",
524                                       "ID",
525                                       "The ID of this object.",
526                                       NULL,
527                                       G_PARAM_READWRITE |
528                                       G_PARAM_STATIC_NAME |
529                                       G_PARAM_STATIC_NICK |
530                                       G_PARAM_STATIC_BLURB));
531
532         /**
533          * GUPnPDIDLLiteObject:parent-id:
534          *
535          * The ID of the parent container of this object.
536          **/
537         g_object_class_install_property
538                 (object_class,
539                  PROP_PARENT_ID,
540                  g_param_spec_string ("parent-id",
541                                       "ParentID",
542                                       "The ID of the parent container of"
543                                       " this object.",
544                                       NULL,
545                                       G_PARAM_READWRITE |
546                                       G_PARAM_STATIC_NAME |
547                                       G_PARAM_STATIC_NICK |
548                                       G_PARAM_STATIC_BLURB));
549
550         /**
551          * GUPnPDIDLLiteObject:restricted:
552          *
553          * Whether this object is restricted.
554          **/
555         g_object_class_install_property
556                 (object_class,
557                  PROP_RESTRICTED,
558                  g_param_spec_boolean ("restricted",
559                                        "Restricted",
560                                        "Whether this object is restricted.",
561                                        FALSE,
562                                        G_PARAM_READWRITE |
563                                        G_PARAM_STATIC_NAME |
564                                        G_PARAM_STATIC_NICK |
565                                        G_PARAM_STATIC_BLURB));
566
567         /**
568          * GUPnPDIDLLiteObject:title:
569          *
570          * The title of this object.
571          **/
572         g_object_class_install_property
573                 (object_class,
574                  PROP_TITLE,
575                  g_param_spec_string ("title",
576                                       "Title",
577                                       "The title of this object.",
578                                       NULL,
579                                       G_PARAM_READWRITE |
580                                       G_PARAM_STATIC_NAME |
581                                       G_PARAM_STATIC_NICK |
582                                       G_PARAM_STATIC_BLURB));
583
584         /**
585          * GUPnPDIDLLiteObject:upnp-class:
586          *
587          * The UPnP class of this object.
588          **/
589         g_object_class_install_property
590                 (object_class,
591                  PROP_UPNP_CLASS,
592                  g_param_spec_string ("upnp-class",
593                                       "UPnPClassName",
594                                       "The UPnP class of this object.",
595                                       NULL,
596                                       G_PARAM_READWRITE |
597                                       G_PARAM_STATIC_NAME |
598                                       G_PARAM_STATIC_NICK |
599                                       G_PARAM_STATIC_BLURB));
600
601         /**
602          * GUPnPDIDLLiteObject:creator:
603          *
604          * The creator of this object.
605          *
606          **/
607         g_object_class_install_property
608                 (object_class,
609                  PROP_CREATOR,
610                  g_param_spec_string ("creator",
611                                       "Creator",
612                                       "The creator of this object.",
613                                       NULL,
614                                       G_PARAM_READWRITE |
615                                       G_PARAM_STATIC_NAME |
616                                       G_PARAM_STATIC_NICK |
617                                       G_PARAM_STATIC_BLURB));
618
619         /**
620          * GUPnPDIDLLiteObject:artist:
621          *
622          * The artist of this object.
623          *
624          * Deprecated: 0.5.3: Use #gupnp_didl_lite_object_get_artists and
625          * #gupnp_didl_lite_object_add_artist instead since unlike this
626          * property, they are capable of dealing with multiple artist nodes.
627          **/
628         g_object_class_install_property
629                 (object_class,
630                  PROP_ARTIST,
631                  g_param_spec_string ("artist",
632                                       "Artist",
633                                       "The artist of this object.",
634                                       NULL,
635                                       G_PARAM_READWRITE |
636                                       G_PARAM_STATIC_NAME |
637                                       G_PARAM_STATIC_NICK |
638                                       G_PARAM_STATIC_BLURB));
639
640         /**
641          * GUPnPDIDLLiteObject:author:
642          *
643          * The author of this object.
644          *
645          * Deprecated: 0.5.3: Use #gupnp_didl_lite_object_get_authors and
646          * #gupnp_didl_lite_object_add_author instead since unlike this
647          * property, they are capable of dealing with multiple author nodes.
648          **/
649         g_object_class_install_property
650                 (object_class,
651                  PROP_AUTHOR,
652                  g_param_spec_string ("author",
653                                       "Author",
654                                       "The author of this object.",
655                                       NULL,
656                                       G_PARAM_READWRITE |
657                                       G_PARAM_STATIC_NAME |
658                                       G_PARAM_STATIC_NICK |
659                                       G_PARAM_STATIC_BLURB));
660
661         /**
662          * GUPnPDIDLLiteObject:genre:
663          *
664          * The genre of this object.
665          **/
666         g_object_class_install_property
667                 (object_class,
668                  PROP_GENRE,
669                  g_param_spec_string ("genre",
670                                       "Genre",
671                                       "The genre of this object.",
672                                       NULL,
673                                       G_PARAM_READWRITE |
674                                       G_PARAM_STATIC_NAME |
675                                       G_PARAM_STATIC_NICK |
676                                       G_PARAM_STATIC_BLURB));
677
678         /**
679          * GUPnPDIDLLiteObject:write-status:
680          *
681          * The write status of this object.
682          **/
683         g_object_class_install_property
684                 (object_class,
685                  PROP_WRITE_STATUS,
686                  g_param_spec_string ("write-status",
687                                       "WriteStatus",
688                                       "The write status of this object.",
689                                       NULL,
690                                       G_PARAM_READWRITE |
691                                       G_PARAM_STATIC_NAME |
692                                       G_PARAM_STATIC_NICK |
693                                       G_PARAM_STATIC_BLURB));
694
695         /**
696          * GUPnPDIDLLiteObject:album:
697          *
698          * The album of this object.
699          **/
700         g_object_class_install_property
701                 (object_class,
702                  PROP_ALBUM,
703                  g_param_spec_string ("album",
704                                       "Album",
705                                       "The album of this object.",
706                                       NULL,
707                                       G_PARAM_READWRITE |
708                                       G_PARAM_STATIC_NAME |
709                                       G_PARAM_STATIC_NICK |
710                                       G_PARAM_STATIC_BLURB));
711
712         /**
713          * GUPnPDIDLLiteObject:album-art:
714          *
715          * The URI to album art of this object.
716          **/
717         g_object_class_install_property
718                 (object_class,
719                  PROP_ALBUM_ART,
720                  g_param_spec_string ("album-art",
721                                       "AlbumArt",
722                                       "The URI to album art of this object.",
723                                       NULL,
724                                       G_PARAM_READWRITE |
725                                       G_PARAM_STATIC_NAME |
726                                       G_PARAM_STATIC_NICK |
727                                       G_PARAM_STATIC_BLURB));
728
729         /**
730          * GUPnPDIDLLiteObject:description:
731          *
732          * The description of this object.
733          **/
734         g_object_class_install_property
735                 (object_class,
736                  PROP_DESCRIPTION,
737                  g_param_spec_string ("description",
738                                       "Description",
739                                       "The description of this object.",
740                                       NULL,
741                                       G_PARAM_READWRITE |
742                                       G_PARAM_STATIC_NAME |
743                                       G_PARAM_STATIC_NICK |
744                                       G_PARAM_STATIC_BLURB));
745
746         /**
747          * GUPnPDIDLLiteObject:date:
748          *
749          * The date of this object.
750          **/
751         g_object_class_install_property
752                 (object_class,
753                  PROP_DATE,
754                  g_param_spec_string ("date",
755                                       "Date",
756                                       "The date of this object.",
757                                       NULL,
758                                       G_PARAM_READWRITE |
759                                       G_PARAM_STATIC_NAME |
760                                       G_PARAM_STATIC_NICK |
761                                       G_PARAM_STATIC_BLURB));
762
763         /**
764          * GUPnPDIDLLiteObject:track-number:
765          *
766          * The original track number of this object.
767          **/
768         g_object_class_install_property
769                 (object_class,
770                  PROP_TRACK_NUMBER,
771                  g_param_spec_int ("track-number",
772                                    "TrackNumber",
773                                    "The original track number of this  object.",
774                                    -1, G_MAXINT, -1,
775                                    G_PARAM_READWRITE |
776                                    G_PARAM_STATIC_NAME |
777                                    G_PARAM_STATIC_NICK |
778                                    G_PARAM_STATIC_BLURB));
779
780         /**
781          * GUPnPDIDLLiteObject:dlna-managed:
782          *
783          * The 'dlna:dlnaManaged' attribute.
784          **/
785         g_object_class_install_property
786                 (object_class,
787                  PROP_DLNA_MANAGED,
788                  g_param_spec_flags ("dlna-managed",
789                                      "DLNAManaged",
790                                      "The 'dlna:dlnaManaged' attribute",
791                                      GUPNP_TYPE_OCM_FLAGS,
792                                      GUPNP_OCM_FLAGS_NONE,
793                                      G_PARAM_READWRITE |
794                                      G_PARAM_STATIC_NAME |
795                                      G_PARAM_STATIC_NICK |
796                                      G_PARAM_STATIC_BLURB));
797
798         /**
799          * GUPnPDIDLLiteObject:update-id:
800          *
801          * Update ID of this object.
802          **/
803         g_object_class_install_property
804                                 (object_class,
805                                  PROP_UPDATE_ID,
806                                  g_param_spec_uint ("update-id",
807                                                     "UpdateID",
808                                                     "Update ID of this object.",
809                                                     0,
810                                                     G_MAXUINT,
811                                                     0,
812                                                     G_PARAM_READWRITE |
813                                                     G_PARAM_STATIC_NAME |
814                                                     G_PARAM_STATIC_NICK |
815                                                     G_PARAM_STATIC_BLURB));
816
817         if (didl_lite_xsd == NULL)
818                 didl_lite_xsd = fragment_util_get_didl_lite_xsd_data ();
819 }
820
821 static gboolean
822 is_resource_compatible (GUPnPDIDLLiteResource *resource,
823                         char                 **protocols)
824 {
825         gboolean ret = FALSE;
826         char **it;
827
828         for (it = protocols; *it != NULL && !ret; it++) {
829                 GUPnPProtocolInfo *info;
830                 GUPnPProtocolInfo *res_info;
831
832                 info = gupnp_protocol_info_new_from_string (*it, NULL);
833                 if (info == NULL)
834                         continue;
835
836                 res_info = gupnp_didl_lite_resource_get_protocol_info
837                                                         (resource);
838                 ret = gupnp_protocol_info_is_compatible (info, res_info);
839
840                 g_object_unref (info);
841         }
842
843         return ret;
844 }
845
846 static GList *
847 get_contributor_list_by_name (GUPnPDIDLLiteObject *object,
848                               const char          *name)
849 {
850         GList *contributors = NULL;
851         GList *ret = NULL;
852         GList *l;
853
854         contributors = gupnp_didl_lite_object_get_properties (object, name);
855
856         for (l = contributors; l; l = l->next) {
857                 GUPnPDIDLLiteContributor *contributor;
858                 xmlNode *contributor_node;
859
860                 contributor_node = (xmlNode *) l->data;
861                 if (!contributor_node->children)
862                         continue;
863
864                 contributor = gupnp_didl_lite_contributor_new_from_xml
865                                         (contributor_node,
866                                          object->priv->xml_doc);
867
868                 ret = g_list_append (ret, contributor);
869         }
870
871         g_list_free (contributors);
872
873         return ret;
874 }
875
876 static char *
877 get_contributors_xml_string_by_name (GUPnPDIDLLiteObject *object,
878                                      const char          *name)
879 {
880         GList     *contributors = NULL;
881         char      *ret = NULL;
882         GList     *l;
883         xmlBuffer *buffer;
884
885         contributors = gupnp_didl_lite_object_get_properties (object, name);
886         if (contributors == NULL)
887                 return NULL;
888
889         buffer = xmlBufferCreate ();
890
891         for (l = contributors; l; l = l->next) {
892                 xmlNode *node;
893
894                 node = (xmlNode *) l->data;
895                 if (!node->children)
896                         continue;
897
898                 xmlNodeDump (buffer,
899                              object->priv->xml_doc->doc,
900                              node,
901                              0,
902                              0);
903         }
904
905         ret = g_strndup ((char *) xmlBufferContent (buffer),
906                          xmlBufferLength (buffer));
907         xmlBufferFree (buffer);
908
909         g_list_free (contributors);
910
911         return ret;
912 }
913
914 static void
915 unset_contributors_by_name (GUPnPDIDLLiteObject *object, const char *name)
916 {
917         GList *contributors = NULL;
918         GList *l;
919
920         contributors = gupnp_didl_lite_object_get_properties (object, name);
921         if (contributors == NULL)
922                 return;
923
924         for (l = contributors; l; l = l->next) {
925                 xmlNode *node;
926
927                 node = (xmlNode *) l->data;
928                 if (!node->children)
929                         continue;
930
931                 xmlUnlinkNode (node);
932                 xmlFreeNode (node);
933         }
934
935         g_list_free (contributors);
936
937         return;
938 }
939
940 /**
941  * gupnp_didl_lite_object_new_from_xml:
942  * @xml_node: The pointer to 'res' node in XML document
943  * @xml_doc: The reference to XML document containing this object
944  * @upnp_ns: The pointer to 'upnp' namespace in XML document
945  * @dc_ns: The pointer to 'dc' namespace in XML document
946  * @dlna_ns: The pointer to 'dlna' namespace in XML document
947  * @pv_ns: The pointer to 'pv' namespace in XML document
948  *
949  * Creates a new #GUPnPDIDLLiteObject for the @xml_node.
950  *
951  * Return value: A new #GUPnPDIDLLiteObject object. Unref after usage.
952  **/
953 GUPnPDIDLLiteObject *
954 gupnp_didl_lite_object_new_from_xml (xmlNode     *xml_node,
955                                      GUPnPXMLDoc *xml_doc,
956                                      xmlNs       *upnp_ns,
957                                      xmlNs       *dc_ns,
958                                      xmlNs       *dlna_ns,
959                                      xmlNs       *pv_ns)
960 {
961         g_return_val_if_fail (xml_node != NULL, NULL);
962         g_return_val_if_fail (xml_node->name != NULL, NULL);
963         g_return_val_if_fail (upnp_ns != NULL, NULL);
964         g_return_val_if_fail (dc_ns != NULL, NULL);
965         g_return_val_if_fail (dlna_ns != NULL, NULL);
966
967         if (g_ascii_strcasecmp ((char *) xml_node->name, "container") == 0)
968                 return g_object_new (GUPNP_TYPE_DIDL_LITE_CONTAINER,
969                                      "xml-node", xml_node,
970                                      "xml-doc", xml_doc,
971                                      "upnp-namespace", upnp_ns,
972                                      "dc-namespace", dc_ns,
973                                      "dlna-namespace", dlna_ns,
974                                      "pv-namespace", pv_ns,
975                                      NULL);
976         else if (g_ascii_strcasecmp ((char *) xml_node->name, "item") == 0)
977                 return g_object_new (GUPNP_TYPE_DIDL_LITE_ITEM,
978                                      "xml-node", xml_node,
979                                      "xml-doc", xml_doc,
980                                      "upnp-namespace", upnp_ns,
981                                      "dc-namespace", dc_ns,
982                                      "dlna-namespace", dlna_ns,
983                                      "pv-namespace", pv_ns,
984                                      NULL);
985         else
986                 return NULL;
987 }
988
989 /**
990  * gupnp_didl_lite_object_get_gupnp_xml_doc:
991  * @object: The #GUPnPDIDLLiteObject
992  *
993  * Get the pointer to the XML document containing this object.
994  *
995  * Returns: (transfer none): The pointer to the XML document containing this
996  * object.
997  **/
998 GUPnPXMLDoc *
999 gupnp_didl_lite_object_get_gupnp_xml_doc (GUPnPDIDLLiteObject *object)
1000 {
1001         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1002
1003         return object->priv->xml_doc;
1004 }
1005
1006 /**
1007  * gupnp_didl_lite_object_get_xml_node:
1008  * @object: The #GUPnPDIDLLiteObject
1009  *
1010  * Get the pointer to object node in XML document.
1011  *
1012  * Returns: (transfer none): The pointer to object node in XML document.
1013  **/
1014 xmlNode *
1015 gupnp_didl_lite_object_get_xml_node (GUPnPDIDLLiteObject *object)
1016 {
1017         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1018
1019         return object->priv->xml_node;
1020 }
1021
1022 /**
1023  * gupnp_didl_lite_object_get_upnp_namespace:
1024  * @object: The #GUPnPDIDLLiteObject
1025  *
1026  * Get the pointer to the UPnP namespace registered with the XML document.
1027  *
1028  * Returns: (transfer none): The pointer to UPnP namespace in XML document.
1029  **/
1030 xmlNsPtr
1031 gupnp_didl_lite_object_get_upnp_namespace (GUPnPDIDLLiteObject *object)
1032 {
1033         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1034
1035         return object->priv->upnp_ns;
1036 }
1037
1038 /**
1039  * gupnp_didl_lite_object_get_dc_namespace:
1040  * @object: The #GUPnPDIDLLiteObject
1041  *
1042  * Get the pointer to the DublinCore namespace registered with the XML document
1043  * containing this object.
1044  *
1045  * Returns: (transfer none): The pointer to DublinCore namespace in XML document.
1046  **/
1047 xmlNsPtr
1048 gupnp_didl_lite_object_get_dc_namespace (GUPnPDIDLLiteObject *object)
1049 {
1050         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1051
1052         return object->priv->dc_ns;
1053 }
1054
1055 /**
1056  * gupnp_didl_lite_object_get_upnp_class:
1057  * @object: The #GUPnPDIDLLiteObject
1058  *
1059  * Get the UPnP class of the @object.
1060  *
1061  * Return value: The class of @object, or %NULL.
1062  **/
1063 const char *
1064 gupnp_didl_lite_object_get_upnp_class (GUPnPDIDLLiteObject *object)
1065 {
1066         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1067
1068         return xml_util_get_child_element_content (object->priv->xml_node,
1069                                                    "class");
1070 }
1071
1072 /**
1073  * gupnp_didl_lite_object_get_dlna_namespace:
1074  * @object: The #GUPnPDIDLLiteObject
1075  *
1076  * Get the pointer to the DLNA metadata namespace registered with the XML
1077  * document containing this object.
1078  *
1079  * Returns: (transfer none): The pointer to DLNA namespace in XML document.
1080  **/
1081 xmlNsPtr
1082 gupnp_didl_lite_object_get_dlna_namespace (GUPnPDIDLLiteObject *object)
1083 {
1084         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1085
1086         return object->priv->dlna_ns;
1087 }
1088
1089 /**
1090  * gupnp_didl_lite_object_get_pv_namespace:
1091  * @object: The #GUPnPDIDLLiteObject
1092  *
1093  * Get the pointer to the PV metadata namespace registered with the XML
1094  * document containing this object.
1095  *
1096  * Returns: (transfer none): The pointer to PV namespace in XML document.
1097  **/
1098 xmlNsPtr
1099 gupnp_didl_lite_object_get_pv_namespace (GUPnPDIDLLiteObject *object)
1100 {
1101         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1102
1103         return object->priv->pv_ns;
1104 }
1105
1106
1107 /**
1108  * gupnp_didl_lite_object_get_id:
1109  * @object: #GUPnPDIDLLiteObject
1110  *
1111  * Get the ID of the @object.
1112  *
1113  * Return value: The ID of the @object, or %NULL.
1114  **/
1115 const char *
1116 gupnp_didl_lite_object_get_id (GUPnPDIDLLiteObject *object)
1117 {
1118         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1119
1120         return xml_util_get_attribute_content (object->priv->xml_node, "id");
1121 }
1122
1123 /**
1124  * gupnp_didl_lite_object_get_parent_id:
1125  * @object: #GUPnPDIDLLiteObject
1126  *
1127  * Get the ID of the parent of the @object.
1128  *
1129  * Return value: The ID of parent of the @object, or %NULL.
1130  **/
1131 const char *
1132 gupnp_didl_lite_object_get_parent_id (GUPnPDIDLLiteObject *object)
1133 {
1134         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1135
1136         return xml_util_get_attribute_content (object->priv->xml_node,
1137                                                "parentID");
1138 }
1139
1140 /**
1141  * gupnp_didl_lite_object_get_properties:
1142  * @object: #GUPnPDIDLLiteObject
1143  * @name: name of the properties
1144  *
1145  * Use this function to retreive property nodes by name.
1146  *
1147  * Return value: (element-type xmlNode*) (transfer container): The list of
1148  * property nodes by the name @property_name belonging to @object, or %NULL.
1149  * #g_list_free the returned list after usage but do not modify the contents.
1150  **/
1151 GList *
1152 gupnp_didl_lite_object_get_properties (GUPnPDIDLLiteObject *object,
1153                                        const char          *name)
1154 {
1155         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1156         g_return_val_if_fail (name != NULL, NULL);
1157
1158         return xml_util_get_child_elements_by_name (object->priv->xml_node,
1159                                                     name);
1160 }
1161
1162 /**
1163  * gupnp_didl_lite_object_get_restricted:
1164  * @object: #GUPnPDIDLLiteObject
1165  *
1166  * Whether the @object is restricted or not.
1167  *
1168  * Return value: #TRUE if @object is restricted.
1169  **/
1170 gboolean
1171 gupnp_didl_lite_object_get_restricted (GUPnPDIDLLiteObject *object)
1172 {
1173         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), FALSE);
1174
1175         return xml_util_get_boolean_attribute (object->priv->xml_node,
1176                                                "restricted");
1177 }
1178
1179 /**
1180  * gupnp_didl_lite_object_get_title:
1181  * @object: #GUPnPDIDLLiteObject
1182  *
1183  * Get the title of the @object.
1184  *
1185  * Return value: The title of the @object, or %NULL.
1186  **/
1187 const char *
1188 gupnp_didl_lite_object_get_title (GUPnPDIDLLiteObject *object)
1189 {
1190         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1191
1192         return xml_util_get_child_element_content (object->priv->xml_node,
1193                                                    "title");
1194 }
1195
1196 /**
1197  * gupnp_didl_lite_object_get_creator:
1198  * @object: #GUPnPDIDLLiteObject
1199  *
1200  * Get the creator of the @object.
1201  *
1202  * Return value: The creator of the @object, or %NULL.
1203  **/
1204 const char *
1205 gupnp_didl_lite_object_get_creator (GUPnPDIDLLiteObject *object)
1206 {
1207         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1208
1209         return xml_util_get_child_element_content (object->priv->xml_node,
1210                                                    "creator");
1211 }
1212
1213 /**
1214  * gupnp_didl_lite_object_get_creators:
1215  * @object: #GUPnPDIDLLiteObject
1216  *
1217  * Get the creators of the @object.
1218  *
1219  * Returns: (element-type GUPnPDIDLLiteContributor*) (transfer full): The list
1220  * of creators belonging to @object, or %NULL.
1221  * #g_list_free the returned list after usage and unref each object in it.
1222  **/
1223 GList *
1224 gupnp_didl_lite_object_get_creators (GUPnPDIDLLiteObject *object)
1225 {
1226         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1227
1228         return get_contributor_list_by_name (object, "creator");
1229 }
1230
1231 /**
1232  * gupnp_didl_lite_object_get_artist:
1233  * @object: #GUPnPDIDLLiteObject
1234  *
1235  * Get the artist of the @object. If role is not %NULL, it is set to the role
1236  * of the artist if available.
1237  *
1238  * Return value: The artist of the @object, or %NULL.
1239  *
1240  * Deprecated: 0.5.3: Use #gupnp_didl_lite_object_get_artists instead.
1241  **/
1242 const char *
1243 gupnp_didl_lite_object_get_artist (GUPnPDIDLLiteObject *object)
1244 {
1245         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1246
1247         return xml_util_get_child_element_content (object->priv->xml_node,
1248                                                    "artist");
1249 }
1250
1251 /**
1252  * gupnp_didl_lite_object_get_artists:
1253  * @object: #GUPnPDIDLLiteObject
1254  *
1255  * Get the artists of the @object.
1256  *
1257  * Returns: (element-type GUPnPDIDLLiteContributor*) (transfer full): The list
1258  * of artists belonging to @object, or %NULL.
1259  * #g_list_free the returned list after usage and unref each object in it.
1260  **/
1261 GList *
1262 gupnp_didl_lite_object_get_artists (GUPnPDIDLLiteObject *object)
1263 {
1264         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1265
1266         return get_contributor_list_by_name (object, "artist");
1267 }
1268
1269 /**
1270  * gupnp_didl_lite_object_get_author:
1271  * @object: #GUPnPDIDLLiteObject
1272  *
1273  * Get the author of the @object.
1274  *
1275  * Return value: The author of the @object, or %NULL.
1276  *
1277  * Deprecated: 0.5.3: Use #gupnp_didl_lite_object_get_authors instead.
1278  **/
1279 const char *
1280 gupnp_didl_lite_object_get_author (GUPnPDIDLLiteObject *object)
1281 {
1282         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1283
1284         return xml_util_get_child_element_content (object->priv->xml_node,
1285                                                    "author");
1286 }
1287
1288 /**
1289  * gupnp_didl_lite_object_get_authors:
1290  * @object: #GUPnPDIDLLiteObject
1291  *
1292  * Get the authors of the @object.
1293  *
1294  * Returns: (element-type GUPnPDIDLLiteContributor*) (transfer full): The list
1295  * of authors belonging to @object, or %NULL.
1296  * #g_list_free the returned list after usage and unref each object in it.
1297  **/
1298 GList *
1299 gupnp_didl_lite_object_get_authors (GUPnPDIDLLiteObject *object)
1300 {
1301         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1302
1303         return get_contributor_list_by_name (object, "author");
1304 }
1305
1306 /**
1307  * gupnp_didl_lite_object_get_descriptors:
1308  * @object: #GUPnPDIDLLiteObject
1309  *
1310  * Get the descriptors of the @object.
1311  *
1312  * Returns: (element-type GUPnPDIDLLiteDescriptor*) (transfer full): The list of
1313  * descriptors belonging to @object, or %NULL.
1314  * #g_list_free the returned list after usage and unref each object in it.
1315  **/
1316 GList *
1317 gupnp_didl_lite_object_get_descriptors (GUPnPDIDLLiteObject *object)
1318 {
1319         GList *descriptors = NULL;
1320         GList *ret = NULL;
1321         GList *l;
1322
1323         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1324
1325         descriptors = gupnp_didl_lite_object_get_properties (object, "desc");
1326
1327         for (l = descriptors; l; l = l->next) {
1328                 GUPnPDIDLLiteDescriptor *descriptor;
1329                 xmlNode *descriptor_node;
1330
1331                 descriptor_node = (xmlNode *) l->data;
1332
1333                 descriptor = gupnp_didl_lite_descriptor_new_from_xml
1334                                         (descriptor_node,
1335                                          object->priv->xml_doc);
1336
1337                 ret = g_list_append (ret, descriptor);
1338         }
1339
1340         g_list_free (descriptors);
1341
1342         return ret;
1343 }
1344
1345 /**
1346  * gupnp_didl_lite_object_get_genre:
1347  * @object: #GUPnPDIDLLiteObject
1348  *
1349  * Get the genre of the @object.
1350  *
1351  * Return value: The genre of the @object, or %NULL.
1352  **/
1353 const char *
1354 gupnp_didl_lite_object_get_genre (GUPnPDIDLLiteObject *object)
1355 {
1356         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1357
1358         return xml_util_get_child_element_content (object->priv->xml_node,
1359                                                    "genre");
1360 }
1361
1362 /**
1363  * gupnp_didl_lite_object_get_write_status:
1364  * @object: #GUPnPDIDLLiteObject
1365  *
1366  * Get the write status of the @object.
1367  *
1368  * Return value: The write status of the @object, or %NULL.
1369  **/
1370 const char *
1371 gupnp_didl_lite_object_get_write_status (GUPnPDIDLLiteObject *object)
1372 {
1373         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1374
1375         return xml_util_get_child_element_content (object->priv->xml_node,
1376                                                    "writeStatus");
1377 }
1378
1379 /**
1380  * gupnp_didl_lite_object_get_album:
1381  * @object: #GUPnPDIDLLiteObject
1382  *
1383  * Get the album of the @object.
1384  *
1385  * Return value: The album of the @object, or %NULL.
1386  **/
1387 const char *
1388 gupnp_didl_lite_object_get_album (GUPnPDIDLLiteObject *object)
1389 {
1390         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1391
1392         return xml_util_get_child_element_content (object->priv->xml_node,
1393                                                    "album");
1394 }
1395
1396 /**
1397  * gupnp_didl_lite_object_get_album_art:
1398  * @object: #GUPnPDIDLLiteObject
1399  *
1400  * Get the URI to album art of the @object.
1401  *
1402  * Return value: The URI to album art of the @object, or %NULL.
1403  **/
1404 const char *
1405 gupnp_didl_lite_object_get_album_art (GUPnPDIDLLiteObject *object)
1406 {
1407         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1408
1409         return xml_util_get_child_element_content (object->priv->xml_node,
1410                                                    "albumArtURI");
1411 }
1412
1413 /**
1414  * gupnp_didl_lite_object_get_description:
1415  * @object: #GUPnPDIDLLiteObject
1416  *
1417  * Get the description of the @object.
1418  *
1419  * Return value: The description of the @object, or %NULL.
1420  **/
1421 const char *
1422 gupnp_didl_lite_object_get_description (GUPnPDIDLLiteObject *object)
1423 {
1424         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1425
1426         return xml_util_get_child_element_content (object->priv->xml_node,
1427                                                    "description");
1428 }
1429
1430 /**
1431  * gupnp_didl_lite_object_get_date:
1432  * @object: #GUPnPDIDLLiteObject
1433  *
1434  * Get the date of the @object.
1435  *
1436  * Return value: The date of the @object, or %NULL.
1437  **/
1438 const char *
1439 gupnp_didl_lite_object_get_date (GUPnPDIDLLiteObject *object)
1440 {
1441         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1442
1443         return xml_util_get_child_element_content (object->priv->xml_node,
1444                                                    "date");
1445 }
1446
1447 /**
1448  * gupnp_didl_lite_object_get_track_number:
1449  * @object: #GUPnPDIDLLiteObject
1450  *
1451  * Get the original track number of the @object.
1452  *
1453  * Return value: The original track number of the @object, or -1.
1454  **/
1455 int
1456 gupnp_didl_lite_object_get_track_number (GUPnPDIDLLiteObject *object)
1457 {
1458         const char *str;
1459
1460         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), -1);
1461
1462         str = xml_util_get_child_element_content (object->priv->xml_node,
1463                                                   "originalTrackNumber");
1464         if (str == NULL)
1465                 return -1;
1466
1467         return atoi (str);
1468 }
1469
1470 /**
1471  * gupnp_didl_lite_object_get_dlna_managed:
1472  * @object: #GUPnPDIDLLiteObject
1473  *
1474  * Get the 'dlna:dlnaManaged' attribute of the @object.
1475  *
1476  * Return value: The 'dlna:dlnaManaged' attribute of the @object.
1477  **/
1478 GUPnPOCMFlags
1479 gupnp_didl_lite_object_get_dlna_managed (GUPnPDIDLLiteObject *object)
1480 {
1481         const char *str;
1482         GUPnPOCMFlags dlna_managed;
1483
1484         g_return_val_if_fail (object != NULL, GUPNP_OCM_FLAGS_NONE);
1485         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object),
1486                               GUPNP_OCM_FLAGS_NONE);
1487
1488         str = xml_util_get_attribute_content (object->priv->xml_node,
1489                                               "dlnaManaged");
1490         if (str == NULL)
1491                 return GUPNP_OCM_FLAGS_NONE;
1492
1493         sscanf (str, "%08x", &dlna_managed);
1494
1495         return dlna_managed;
1496 }
1497
1498 /**
1499  * gupnp_didl_lite_object_get_update_id:
1500  * @object: #GUPnPDIDLLiteObject
1501  *
1502  * Get the update ID of the @object.
1503  *
1504  * Return value: The update ID of the @object.
1505  **/
1506 guint
1507 gupnp_didl_lite_object_get_update_id (GUPnPDIDLLiteObject *object)
1508 {
1509         g_return_val_if_fail (object != NULL, 0);
1510         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), 0);
1511
1512         return xml_util_get_uint_child_element (object->priv->xml_node,
1513                                                 "objectUpdateID",
1514                                                 0);
1515 }
1516
1517 /**
1518  * gupnp_didl_lite_object_update_id_is_set:
1519  * @object: #GUPnPDIDLLiteObject
1520  *
1521  * Get whether the update ID of the @object is set.
1522  *
1523  * Return value: %TRUE if update ID is set, otherwise %FALSE
1524  **/
1525 gboolean
1526 gupnp_didl_lite_object_update_id_is_set (GUPnPDIDLLiteObject *object)
1527 {
1528         const char *content;
1529
1530         g_return_val_if_fail (object != NULL, FALSE);
1531         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), FALSE);
1532
1533         content = xml_util_get_child_element_content (object->priv->xml_node,
1534                                                       "objectUpdateID");
1535         return content != NULL;
1536 }
1537
1538 /**
1539  * gupnp_didl_lite_object_get_resources:
1540  * @object: #GUPnPDIDLLiteObject
1541  *
1542  * Use this function to retreive resources from the @object.
1543  *
1544  * Return value: (element-type GUPnPDIDLLiteResource*) (transfer full): The list
1545  *               of resources belonging to  @object, or %NULL. #g_list_free the
1546  *               returned list after usage and unref each resource in it.
1547  **/
1548 GList *
1549 gupnp_didl_lite_object_get_resources (GUPnPDIDLLiteObject *object)
1550 {
1551         GList *resources = NULL;
1552         GList *res = NULL;
1553         GList *ret = NULL;
1554
1555         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1556
1557         resources = gupnp_didl_lite_object_get_properties (object, "res");
1558
1559         for (res = resources; res; res = res->next) {
1560                 GUPnPDIDLLiteResource *resource;
1561                 xmlNode *res_node;
1562
1563                 res_node = (xmlNode *) res->data;
1564
1565                 /* Create a resource struct out of DIDLLite XML */
1566                 resource = gupnp_didl_lite_resource_new_from_xml
1567                                         (res_node,
1568                                          object->priv->xml_doc,
1569                                          object->priv->dlna_ns,
1570                                          object->priv->pv_ns);
1571
1572                 ret = g_list_append (ret, resource);
1573         }
1574
1575         g_list_free (resources);
1576
1577         return ret;
1578 }
1579
1580 /**
1581  * gupnp_didl_lite_object_get_compat_resource:
1582  * @object: #GUPnPDIDLLiteObject
1583  * @sink_protocol_info: The SinkProtocolInfo string from MediaRenderer
1584  * @lenient: Enable lenient mode
1585  *
1586  * Use this function to get a resource from the @object that is compatible with
1587  * any of the protocols specified in the @sink_protocol_info. The value of
1588  * @sink_protocol_info will typically be acquired from 'Sink' argument of
1589  * 'GetProtocolInfo' action or 'SinkProtocolInfo' state-variable of a
1590  * ConnectionManager service.
1591  *
1592  * If @lenient is #TRUE, the first resource in the list is returned instead of
1593  * %NULL if none of resources and protocols are found to be compatible.
1594  *
1595  * Returns: (transfer full): The resource belonging to @object that is comaptible with
1596  * any of the protocols specified in @sink_protocol_info, or %NULL. Unref after
1597  * usage.
1598  **/
1599 GUPnPDIDLLiteResource *
1600 gupnp_didl_lite_object_get_compat_resource
1601                                 (GUPnPDIDLLiteObject *object,
1602                                  const char          *sink_protocol_info,
1603                                  gboolean             lenient)
1604 {
1605         GUPnPDIDLLiteResource *resource = NULL;
1606         GList  *resources = NULL;
1607         GList  *compat_resources = NULL;
1608         GList  *res;
1609         char **protocols = NULL;
1610
1611         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1612         g_return_val_if_fail (sink_protocol_info != NULL, NULL);
1613
1614         resources = gupnp_didl_lite_object_get_resources (object);
1615         if (resources == NULL)
1616                 return NULL;
1617
1618         protocols = g_strsplit (sink_protocol_info, ",", -1);
1619         for (res = resources;
1620              res != NULL;
1621              res = res->next) {
1622                 resource = (GUPnPDIDLLiteResource *) res->data;
1623
1624                 if (is_resource_compatible (resource, protocols))
1625                         compat_resources = g_list_append (compat_resources,
1626                                                           resource);
1627         }
1628         g_strfreev (protocols);
1629         protocols = NULL;
1630
1631         resource = NULL;
1632
1633         if (compat_resources != NULL) {
1634                 /* Try to find non-transcoded resource */
1635                 res = g_list_find_custom (compat_resources,
1636                                           NULL,
1637                                           (GCompareFunc)
1638                                           is_non_transcoded_resource);
1639
1640                 if (res != NULL)
1641                         resource = (GUPnPDIDLLiteResource *) res->data;
1642                 else
1643                         /* Just use the first compatible resource */
1644                         resource = (GUPnPDIDLLiteResource *)
1645                                    compat_resources->data;
1646
1647         } else if (lenient)
1648                 /* Just use the first resource */
1649                 resource = (GUPnPDIDLLiteResource *) resources->data;
1650
1651         /* Unref all resources except for the one we just took */
1652         for (res = resources; res; res = res->next)
1653                 if (res->data != resource)
1654                         g_object_unref (res->data);
1655         g_list_free (resources);
1656         g_list_free (compat_resources);
1657
1658         return resource;
1659 }
1660
1661 /**
1662  * gupnp_didl_lite_object_set_upnp_class:
1663  * @object: The #GUPnPDIDLLiteObject
1664  * @upnp_class: The UPnP class as string.
1665  *
1666  * Set the UPnP class of the @object to @upnp_class.
1667  **/
1668 void
1669 gupnp_didl_lite_object_set_upnp_class (GUPnPDIDLLiteObject *object,
1670                                        const char          *upnp_class)
1671 {
1672         g_return_if_fail (object != NULL);
1673         g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
1674
1675         xml_util_set_child (object->priv->xml_node,
1676                             object->priv->upnp_ns,
1677                             object->priv->xml_doc->doc,
1678                             "class",
1679                             upnp_class);
1680
1681         g_object_notify (G_OBJECT (object), "upnp-class");
1682 }
1683
1684 /**
1685  * gupnp_didl_lite_object_set_id:
1686  * @object: #GUPnPDIDLLiteObject
1687  * @id: The ID
1688  *
1689  * Set the ID of the @object to @id.
1690  **/
1691 void
1692 gupnp_didl_lite_object_set_id (GUPnPDIDLLiteObject *object,
1693                                const char          *id)
1694 {
1695         g_return_if_fail (object != NULL);
1696         g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
1697
1698         xmlSetProp (object->priv->xml_node,
1699                     (unsigned char *) "id",
1700                     (unsigned char *) id);
1701
1702         g_object_notify (G_OBJECT (object), "id");
1703 }
1704
1705 /**
1706  * gupnp_didl_lite_object_set_parent_id:
1707  * @object: #GUPnPDIDLLiteObject
1708  * @parent_id: The parent ID
1709  *
1710  * Set the ID of the parent of the @object to @parent_id.
1711  **/
1712 void
1713 gupnp_didl_lite_object_set_parent_id (GUPnPDIDLLiteObject *object,
1714                                       const char          *parent_id)
1715 {
1716         g_return_if_fail (object != NULL);
1717         g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
1718
1719         xmlSetProp (object->priv->xml_node,
1720                     (unsigned char *) "parentID",
1721                     (unsigned char *) parent_id);
1722
1723         g_object_notify (G_OBJECT (object), "parent-id");
1724 }
1725
1726 /**
1727  * gupnp_didl_lite_object_set_restricted:
1728  * @object: #GUPnPDIDLLiteObject
1729  * @restricted: The restricted status
1730  *
1731  * Set the restricted status of @object to @restricted.
1732  **/
1733 void
1734 gupnp_didl_lite_object_set_restricted (GUPnPDIDLLiteObject *object,
1735                                        gboolean             restricted)
1736 {
1737         const char *str;
1738
1739         g_return_if_fail (object != NULL);
1740         g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
1741
1742         if (restricted)
1743                 str = "1";
1744         else
1745                 str = "0";
1746         xmlSetProp (object->priv->xml_node,
1747                     (unsigned char *) "restricted",
1748                     (unsigned char *) str);
1749
1750         g_object_notify (G_OBJECT (object), "restricted");
1751 }
1752
1753 /**
1754  * gupnp_didl_lite_object_set_title:
1755  * @object: #GUPnPDIDLLiteObject
1756  * @title: The title
1757  *
1758  * Set the title of the @object to @title.
1759  **/
1760 void
1761 gupnp_didl_lite_object_set_title (GUPnPDIDLLiteObject *object,
1762                                   const char          *title)
1763 {
1764         g_return_if_fail (object != NULL);
1765         g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
1766
1767         xml_util_set_child (object->priv->xml_node,
1768                             object->priv->dc_ns,
1769                             object->priv->xml_doc->doc,
1770                             "title",
1771                             title);
1772
1773         g_object_notify (G_OBJECT (object), "title");
1774 }
1775
1776 /**
1777  * gupnp_didl_lite_object_set_creator:
1778  * @object: #GUPnPDIDLLiteObject
1779  * @creator: The creator
1780  *
1781  * Set the creator of the @object to @creator.
1782  **/
1783 void
1784 gupnp_didl_lite_object_set_creator (GUPnPDIDLLiteObject *object,
1785                                     const char          *creator)
1786 {
1787         g_return_if_fail (object != NULL);
1788         g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
1789
1790         xml_util_set_child (object->priv->xml_node,
1791                             object->priv->dc_ns,
1792                             object->priv->xml_doc->doc,
1793                             "creator",
1794                             creator);
1795
1796         g_object_notify (G_OBJECT (object), "creator");
1797 }
1798
1799 /**
1800  * gupnp_didl_lite_object_add_creator:
1801  * @object: The #GUPnPDIDLLiteObject
1802  *
1803  * Add a new creator node to the @object and return the associated
1804  * #GUPnPDIDLLiteContributor object.
1805  *
1806  * Returns: (transfer full): A new #GUPnPDIDLLiteContributor object. Unref after usage.
1807  **/
1808 GUPnPDIDLLiteContributor *
1809 gupnp_didl_lite_object_add_creator (GUPnPDIDLLiteObject *object)
1810 {
1811         xmlNode *res_node;
1812
1813         g_return_val_if_fail (object != NULL, NULL);
1814         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1815
1816         res_node = xmlNewChild (object->priv->xml_node,
1817                                 object->priv->dc_ns,
1818                                 (unsigned char *) "creator",
1819                                 NULL);
1820
1821         return gupnp_didl_lite_contributor_new_from_xml (res_node,
1822                                                          object->priv->xml_doc);
1823 }
1824
1825
1826 /**
1827  * gupnp_didl_lite_object_set_artist:
1828  * @object: The #GUPnPDIDLLiteObject
1829  * @artist: The Artist
1830  *
1831  * Set the Artist of the @object to @artist.
1832  *
1833  * Deprecated: 0.5.3: Use #gupnp_didl_lite_object_add_artist instead.
1834  **/
1835 void
1836 gupnp_didl_lite_object_set_artist (GUPnPDIDLLiteObject *object,
1837                                    const char          *artist)
1838 {
1839         g_return_if_fail (object != NULL);
1840         g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
1841
1842         xml_util_set_child (object->priv->xml_node,
1843                             object->priv->upnp_ns,
1844                             object->priv->xml_doc->doc,
1845                             "artist",
1846                             artist);
1847
1848         g_object_notify (G_OBJECT (object), "artist");
1849 }
1850
1851 /**
1852  * gupnp_didl_lite_object_add_artist:
1853  * @object: The #GUPnPDIDLLiteObject
1854  *
1855  * Add a new Artist node to the @object and return the associated
1856  * #GUPnPDIDLLiteContributor object.
1857  *
1858  * Returns: (transfer full): A new #GUPnPDIDLLiteContributor object. Unref after usage.
1859  **/
1860 GUPnPDIDLLiteContributor *
1861 gupnp_didl_lite_object_add_artist (GUPnPDIDLLiteObject *object)
1862 {
1863         xmlNode *res_node;
1864
1865         g_return_val_if_fail (object != NULL, NULL);
1866         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1867
1868         res_node = xmlNewChild (object->priv->xml_node,
1869                                 object->priv->upnp_ns,
1870                                 (unsigned char *) "artist",
1871                                 NULL);
1872
1873         return gupnp_didl_lite_contributor_new_from_xml (res_node,
1874                                                          object->priv->xml_doc);
1875 }
1876
1877 /**
1878  * gupnp_didl_lite_object_set_author:
1879  * @object: The #GUPnPDIDLLiteObject
1880  * @author: The Author
1881  *
1882  * Set the Author of the @object to @author.
1883  *
1884  * Deprecated: 0.5.3: Use #gupnp_didl_lite_object_add_author instead.
1885  **/
1886 void
1887 gupnp_didl_lite_object_set_author (GUPnPDIDLLiteObject *object,
1888                                    const char          *author)
1889 {
1890         g_return_if_fail (object != NULL);
1891         g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
1892
1893         xml_util_set_child (object->priv->xml_node,
1894                             object->priv->upnp_ns,
1895                             object->priv->xml_doc->doc,
1896                             "author",
1897                             author);
1898
1899         g_object_notify (G_OBJECT (object), "author");
1900 }
1901
1902 /**
1903  * gupnp_didl_lite_object_add_author:
1904  * @object: The #GUPnPDIDLLiteObject
1905  *
1906  * Add a new author node to the @object and return the associated
1907  * #GUPnPDIDLLiteContributor object.
1908  *
1909  * Returns: (transfer full): A new #GUPnPDIDLLiteContributor object. Unref after usage.
1910  **/
1911 GUPnPDIDLLiteContributor *
1912 gupnp_didl_lite_object_add_author (GUPnPDIDLLiteObject *object)
1913 {
1914         xmlNode *res_node;
1915
1916         g_return_val_if_fail (object != NULL, NULL);
1917         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
1918
1919         res_node = xmlNewChild (object->priv->xml_node,
1920                                 object->priv->upnp_ns,
1921                                 (unsigned char *) "author",
1922                                 NULL);
1923
1924         return gupnp_didl_lite_contributor_new_from_xml (res_node,
1925                                                          object->priv->xml_doc);
1926 }
1927
1928 /**
1929  * gupnp_didl_lite_object_set_genre:
1930  * @object: The #GUPnPDIDLLiteObject
1931  * @genre: The Genre
1932  *
1933  * Set the genre of the @object to @genre.
1934  **/
1935 void
1936 gupnp_didl_lite_object_set_genre (GUPnPDIDLLiteObject *object,
1937                                   const char          *genre)
1938 {
1939         g_return_if_fail (object != NULL);
1940         g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
1941
1942         xml_util_set_child (object->priv->xml_node,
1943                             object->priv->upnp_ns,
1944                             object->priv->xml_doc->doc,
1945                             "genre",
1946                             genre);
1947
1948         g_object_notify (G_OBJECT (object), "genre");
1949 }
1950
1951 /**
1952  * gupnp_didl_lite_object_set_write_status:
1953  * @object: #GUPnPDIDLLiteObject
1954  * @write_status: The write status string
1955  *
1956  * Set the write status of the @object to @write_status.
1957  **/
1958 void
1959 gupnp_didl_lite_object_set_write_status (GUPnPDIDLLiteObject *object,
1960                                          const char          *write_status)
1961 {
1962         g_return_if_fail (object != NULL);
1963         g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
1964
1965         xml_util_set_child (object->priv->xml_node,
1966                             object->priv->dc_ns,
1967                             object->priv->xml_doc->doc,
1968                             "writeStatus",
1969                             write_status);
1970
1971         g_object_notify (G_OBJECT (object), "write-status");
1972 }
1973
1974 /**
1975  * gupnp_didl_lite_object_set_album:
1976  * @object: #GUPnPDIDLLiteObject
1977  * @album: The album string
1978  *
1979  * Set the album of the @object to @album.
1980  **/
1981 void
1982 gupnp_didl_lite_object_set_album (GUPnPDIDLLiteObject *object,
1983                                   const char          *album)
1984 {
1985         g_return_if_fail (object != NULL);
1986         g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
1987
1988         xml_util_set_child (object->priv->xml_node,
1989                             object->priv->upnp_ns,
1990                             object->priv->xml_doc->doc,
1991                             "album",
1992                             album);
1993
1994         g_object_notify (G_OBJECT (object), "album");
1995 }
1996
1997 /**
1998  * gupnp_didl_lite_object_set_album_art:
1999  * @object: #GUPnPDIDLLiteObject
2000  * @album_art: The URI of album art
2001  *
2002  * Set the URI to album art of the @object to @album_art.
2003  **/
2004 void
2005 gupnp_didl_lite_object_set_album_art (GUPnPDIDLLiteObject *object,
2006                                       const char          *album_art)
2007 {
2008         xmlNode *node;
2009
2010         g_return_if_fail (object != NULL);
2011         g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
2012
2013         node = xml_util_set_child (object->priv->xml_node,
2014                                    object->priv->upnp_ns,
2015                                    object->priv->xml_doc->doc,
2016                                    "albumArtURI",
2017                                    album_art);
2018         xmlSetNsProp (node,
2019                       object->priv->dlna_ns,
2020                       (const unsigned char *) "profileID",
2021                       (const unsigned char *) "JPEG_TN");
2022
2023         g_object_notify (G_OBJECT (object), "album-art");
2024 }
2025
2026 /**
2027  * gupnp_didl_lite_object_set_description:
2028  * @object: #GUPnPDIDLLiteObject
2029  * @description: The description string
2030  *
2031  * Set the description of the @object to @description.
2032  **/
2033 void
2034 gupnp_didl_lite_object_set_description (GUPnPDIDLLiteObject *object,
2035                                         const char          *description)
2036 {
2037         g_return_if_fail (object != NULL);
2038         g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
2039
2040         xml_util_set_child (object->priv->xml_node,
2041                             object->priv->dc_ns,
2042                             object->priv->xml_doc->doc,
2043                             "description",
2044                             description);
2045
2046         g_object_notify (G_OBJECT (object), "description");
2047 }
2048
2049 /**
2050  * gupnp_didl_lite_object_set_date:
2051  * @object: #GUPnPDIDLLiteObject
2052  * @date: The date string
2053  *
2054  * Set the date of the @object to @date.
2055  **/
2056 void
2057 gupnp_didl_lite_object_set_date (GUPnPDIDLLiteObject *object,
2058                                  const char          *date)
2059 {
2060         g_return_if_fail (object != NULL);
2061         g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
2062
2063         xml_util_set_child (object->priv->xml_node,
2064                             object->priv->dc_ns,
2065                             object->priv->xml_doc->doc,
2066                             "date",
2067                             date);
2068
2069         g_object_notify (G_OBJECT (object), "date");
2070 }
2071
2072 /**
2073  * gupnp_didl_lite_object_set_track_number:
2074  * @object: #GUPnPDIDLLiteObject
2075  * @track_number: The original track number
2076  *
2077  * Set the original track number of the @object to @track_number.
2078  **/
2079 void
2080 gupnp_didl_lite_object_set_track_number (GUPnPDIDLLiteObject *object,
2081                                          int                  track_number)
2082 {
2083         char *str;
2084
2085         g_return_if_fail (object != NULL);
2086         g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
2087
2088         str = g_strdup_printf ("%d", track_number);
2089         xml_util_set_child (object->priv->xml_node,
2090                             object->priv->upnp_ns,
2091                             object->priv->xml_doc->doc,
2092                             "originalTrackNumber",
2093                             str);
2094         g_free (str);
2095
2096         g_object_notify (G_OBJECT (object), "track-number");
2097 }
2098
2099 /**
2100  * gupnp_didl_lite_object_set_dlna_managed:
2101  * @object: #GUPnPDIDLLiteObject
2102  * @dlna_managed: The #GUPnPOCMFlags.
2103  *
2104  * Set the 'dlna:dlnaManaged' attribute of the @object to @dlna_managed.
2105  **/
2106 void
2107 gupnp_didl_lite_object_set_dlna_managed (GUPnPDIDLLiteObject *object,
2108                                          GUPnPOCMFlags        dlna_managed)
2109 {
2110         char *str;
2111
2112         g_return_if_fail (object != NULL);
2113         g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
2114
2115         str = g_strdup_printf ("%08x", dlna_managed);
2116         xmlSetNsProp (object->priv->xml_node,
2117                       object->priv->dlna_ns,
2118                       (const unsigned char *) "dlnaManaged",
2119                       (const unsigned char *) str);
2120         g_free (str);
2121
2122         g_object_notify (G_OBJECT (object), "dlna-managed");
2123 }
2124
2125 /**
2126  * gupnp_didl_lite_object_set_update_id:
2127  * @object: #GUPnPDIDLLiteObject
2128  * @update_id: Update ID
2129  *
2130  * Set the update ID of the @object.
2131  **/
2132 void
2133 gupnp_didl_lite_object_set_update_id (GUPnPDIDLLiteObject *object,
2134                                       guint                update_id)
2135 {
2136         char *str;
2137
2138         g_return_if_fail (object != NULL);
2139         g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
2140
2141         str = g_strdup_printf ("%u", update_id);
2142         xml_util_set_child (object->priv->xml_node,
2143                             object->priv->upnp_ns,
2144                             object->priv->xml_doc->doc,
2145                             "objectUpdateID",
2146                             str);
2147         g_free (str);
2148
2149         g_object_notify (G_OBJECT (object), "update-id");
2150 }
2151
2152 /**
2153  * gupnp_didl_lite_object_unset_update_id:
2154  * @object: #GUPnPDIDLLiteObject
2155  *
2156  * Unset the update ID property of the @object.
2157  **/
2158 void
2159 gupnp_didl_lite_object_unset_update_id (GUPnPDIDLLiteObject *object)
2160 {
2161         g_return_if_fail (object != NULL);
2162         g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
2163
2164         xml_util_unset_child (object->priv->xml_node,
2165                               "objectUpdateID");
2166
2167         g_object_notify (G_OBJECT (object), "update-id");
2168 }
2169
2170 /**
2171  * gupnp_didl_lite_object_add_resource:
2172  * @object: A #GUPnPDIDLLiteObject
2173  *
2174  * Creates a new resource, attaches it to @object and returns it.
2175  *
2176  * Returns: (transfer full): A new #GUPnPDIDLLiteResource object. Unref after usage.
2177  **/
2178 GUPnPDIDLLiteResource *
2179 gupnp_didl_lite_object_add_resource (GUPnPDIDLLiteObject *object)
2180 {
2181         xmlNode *res_node;
2182
2183         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
2184
2185         res_node = xmlNewChild (object->priv->xml_node,
2186                                 NULL,
2187                                 (unsigned char *) "res",
2188                                 NULL);
2189
2190         return gupnp_didl_lite_resource_new_from_xml (res_node,
2191                                                       object->priv->xml_doc,
2192                                                       object->priv->dlna_ns,
2193                                                       object->priv->pv_ns);
2194 }
2195
2196 /**
2197  * gupnp_didl_lite_object_add_descriptor:
2198  * @object: A #GUPnPDIDLLiteObject
2199  *
2200  * Creates a new descriptor, attaches it to @object and returns it.
2201  *
2202  * Returns: (transfer full): A new #GUPnPDIDLLiteDescriptor object. Unref after usage.
2203  **/
2204 GUPnPDIDLLiteDescriptor *
2205 gupnp_didl_lite_object_add_descriptor (GUPnPDIDLLiteObject *object)
2206 {
2207         xmlNode *desc_node;
2208
2209         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
2210
2211         desc_node = xmlNewChild (object->priv->xml_node,
2212                                 NULL,
2213                                 (unsigned char *) "desc",
2214                                 NULL);
2215
2216         return gupnp_didl_lite_descriptor_new_from_xml (desc_node,
2217                                                         object->priv->xml_doc);
2218 }
2219
2220 /**
2221  * gupnp_didl_lite_object_get_title_xml_string:
2222  * @object: A #GUPnPDIDLLiteObject
2223  *
2224  * Creates a string representation of the DIDL-Lite XML fragment related to the
2225  * object title.
2226  *
2227  * Return value: A DIDL-Lite XML fragment string, or %NULL. #g_free after usage.
2228  **/
2229 char *
2230 gupnp_didl_lite_object_get_title_xml_string (GUPnPDIDLLiteObject *object)
2231 {
2232         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
2233
2234         return xml_util_get_child_string (object->priv->xml_node,
2235                                           object->priv->xml_doc->doc,
2236                                           "title");
2237 }
2238
2239 /**
2240  * gupnp_didl_lite_object_get_date_xml_string:
2241  * @object: A #GUPnPDIDLLiteObject
2242  *
2243  * Creates a string representation of the DIDL-Lite XML fragment related to the
2244  * object date.
2245  *
2246  * Return value: A DIDL-Lite XML fragment string, or %NULL. #g_free after usage.
2247  **/
2248 char *
2249 gupnp_didl_lite_object_get_date_xml_string (GUPnPDIDLLiteObject *object)
2250 {
2251         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
2252
2253         return xml_util_get_child_string (object->priv->xml_node,
2254                                           object->priv->xml_doc->doc,
2255                                           "date");
2256 }
2257
2258 /**
2259  * gupnp_didl_lite_object_get_upnp_class_xml_string:
2260  * @object: A #GUPnPDIDLLiteObject
2261  *
2262  * Creates a string representation of the DIDL-Lite XML fragment related to the
2263  * object UPnP class.
2264  *
2265  * Return value: A DIDL-Lite XML fragment string, or %NULL. #g_free after usage.
2266  **/
2267 char *
2268 gupnp_didl_lite_object_get_upnp_class_xml_string (GUPnPDIDLLiteObject *object)
2269 {
2270         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
2271
2272         return xml_util_get_child_string (object->priv->xml_node,
2273                                           object->priv->xml_doc->doc,
2274                                           "class");
2275 }
2276
2277 /**
2278  * gupnp_didl_lite_object_get_album_xml_string:
2279  * @object: A #GUPnPDIDLLiteObject
2280  *
2281  * Creates a string representation of the DIDL-Lite XML fragment related to the
2282  * object album.
2283  *
2284  * Return value: A DIDL-Lite XML fragment string, or %NULL. #g_free after usage.
2285  **/
2286 char *
2287 gupnp_didl_lite_object_get_album_xml_string (GUPnPDIDLLiteObject *object)
2288 {
2289         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
2290
2291         return xml_util_get_child_string (object->priv->xml_node,
2292                                           object->priv->xml_doc->doc,
2293                                           "album");
2294 }
2295
2296 /**
2297  * gupnp_didl_lite_object_get_track_number_xml_string:
2298  * @object: A #GUPnPDIDLLiteObject
2299  *
2300  * Creates a string representation of the DIDL-Lite XML fragment related to the
2301  * object track number.
2302  *
2303  * Return value: A DIDL-Lite XML fragment string, or %NULL. #g_free after usage.
2304  **/
2305 char *
2306 gupnp_didl_lite_object_get_track_number_xml_string (GUPnPDIDLLiteObject *object)
2307 {
2308         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
2309
2310         return xml_util_get_child_string (object->priv->xml_node,
2311                                           object->priv->xml_doc->doc,
2312                                           "originalTrackNumber");
2313 }
2314
2315 /**
2316  * gupnp_didl_lite_object_get_artists_xml_string:
2317  * @object: A #GUPnPDIDLLiteObject
2318  *
2319  * Creates a string representation of the DIDL-Lite XML fragments related to the
2320  * object artists.
2321  *
2322  * Return value: A DIDL-Lite XML fragment string, or %NULL. #g_free after usage.
2323  **/
2324 char *
2325 gupnp_didl_lite_object_get_artists_xml_string (GUPnPDIDLLiteObject *object)
2326 {
2327         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL);
2328
2329         return get_contributors_xml_string_by_name (object, "artist");
2330 }
2331
2332 /**
2333  * gupnp_didl_lite_object_unset_artists:
2334  * @object: #GUPnPDIDLLiteObject
2335  *
2336  * Unset the artists properties of the @object.
2337  **/
2338 void
2339 gupnp_didl_lite_object_unset_artists (GUPnPDIDLLiteObject *object)
2340 {
2341         g_return_if_fail (object != NULL);
2342         g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object));
2343
2344         unset_contributors_by_name (object, "artist");
2345
2346         g_object_notify (G_OBJECT (object), "artist");
2347 }
2348
2349 /* GENERAL DOCS ABOUT FRAGMENT APPLYING.
2350  *
2351  * The function applying fragments takes two arrays of fragments. One
2352  * array contains current fragments and another one contains new
2353  * fragments. Both arrays have to be of equal length and have more
2354  * then zero elements. Each of fragments in both arrays make a pair
2355  * (i.e. first/second/third/... fragment in current array and
2356  * first/second/third/... fragment in new array form a pair). Each
2357  * fragment can have zero, one or more XML elements.
2358  *
2359  * For each fragment pair first we check if current fragment is indeed
2360  * a part of this object's document. If it is then we check validity
2361  * of new fragment for applying. If it is then we replace the current
2362  * fragment with new fragment in object's document copy and validate
2363  * the modified document against didl-lite schema. After all fragment
2364  * pairs are processed we replace a part describing this object in
2365  * original document with respective one in modified document.
2366  *
2367  * Checking if current fragment is a part of object's document is in
2368  * essence checking for deep equality of document's node and this
2369  * fragment (i.e. element name and properties have to be equal, same
2370  * for children).
2371  *
2372  * Checking if new fragment is valid for applying is about checking
2373  * whether element in new fragment is either a context (i.e. both
2374  * current element and new element are deep equal) or element
2375  * modification (i.e. changes attributes but element name is still the
2376  * same). There may be a case when there are more elements in current
2377  * fragment than in new fragment then those excessive elements are
2378  * checked whether they can be really removed. The other case is when
2379  * there are more elements in new fragments than in current fragment -
2380  * in such situation we check if additions are valid.
2381  *
2382  * By checking validity of modification, removals or additions we mean
2383  * that no read-only properties are changed. Additionaly, for
2384  * removals, we check if required properties are not removed.
2385  *
2386  * This approach may fail in some more twisted cases.
2387  */
2388
2389 /**
2390  * gupnp_didl_lite_object_apply_fragments:
2391  * @object: The #GUPnPDIDLLiteObject
2392  * @current_fragments: (array length=current_size) (transfer none): XML
2393  * fragments of @object.
2394  * @current_size: Size of @current_fragments or -1.
2395  * @new_fragments: (array length=new_size) (transfer none): Substitutes
2396  * for @current_fragments.
2397  * @new_size: Size of @new_fragments or -1.
2398  *
2399  * Updates object by applying @new_fragments in places of
2400  * @current_fragments. For @current_size and @new_size -1 can be
2401  * passed when respectively @current_fragments and @new_fragments are
2402  * NULL terminated.
2403  *
2404  * Returns: Result of operation.
2405  */
2406 GUPnPDIDLLiteFragmentResult
2407 gupnp_didl_lite_object_apply_fragments (GUPnPDIDLLiteObject  *object,
2408                                         gchar               **current_fragments,
2409                                         gint                  current_size,
2410                                         gchar               **new_fragments,
2411                                         gint                  new_size)
2412 {
2413         DocNode modified;
2414         DocNode original;
2415         GUPnPDIDLLiteFragmentResult result;
2416         gint iter;
2417
2418         g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object),
2419                               GUPNP_DIDL_LITE_FRAGMENT_RESULT_UNKNOWN_ERROR);
2420         g_return_val_if_fail (current_fragments != NULL,
2421                               GUPNP_DIDL_LITE_FRAGMENT_RESULT_CURRENT_INVALID);
2422         g_return_val_if_fail (new_fragments != NULL,
2423                               GUPNP_DIDL_LITE_FRAGMENT_RESULT_NEW_INVALID);
2424
2425         result = GUPNP_DIDL_LITE_FRAGMENT_RESULT_OK;
2426         modified.doc = NULL;
2427
2428         if (current_size < 0)
2429                 current_size = g_strv_length (current_fragments);
2430         if (new_size < 0)
2431                 new_size = g_strv_length (new_fragments);
2432
2433         if (current_size != new_size) {
2434                 result = GUPNP_DIDL_LITE_FRAGMENT_RESULT_MISMATCH;
2435
2436                 goto out;
2437         }
2438
2439         if (!current_size) {
2440                 result = GUPNP_DIDL_LITE_FRAGMENT_RESULT_CURRENT_INVALID;
2441
2442                 goto out;
2443         }
2444
2445         original.doc = object->priv->xml_doc->doc;
2446         original.node = object->priv->xml_node;
2447         modified.doc = xmlCopyDoc (original.doc, 1);
2448
2449         if (modified.doc == NULL) {
2450                 result = GUPNP_DIDL_LITE_FRAGMENT_RESULT_UNKNOWN_ERROR;
2451
2452                 goto out;
2453         }
2454
2455         modified.node = xml_util_find_node (modified.doc->children,
2456                                             original.node);
2457
2458         if (modified.node == NULL) {
2459                 result = GUPNP_DIDL_LITE_FRAGMENT_RESULT_UNKNOWN_ERROR;
2460
2461                 goto out;
2462         }
2463
2464         for (iter = 0; iter < new_size; ++iter) {
2465                 const gchar *current_fragment = current_fragments[iter];
2466                 const gchar *new_fragment = new_fragments[iter];
2467
2468                 result = fragment_util_check_fragments (&original,
2469                                                         &modified,
2470                                                         current_fragment,
2471                                                         new_fragment,
2472                                                         didl_lite_xsd);
2473
2474                 if (result != GUPNP_DIDL_LITE_FRAGMENT_RESULT_OK)
2475                         goto out;
2476         }
2477
2478         if (!fragment_util_apply_modification (&object->priv->xml_node,
2479                                                &modified))
2480                 result = GUPNP_DIDL_LITE_FRAGMENT_RESULT_UNKNOWN_ERROR;
2481  out:
2482         if (modified.doc != NULL)
2483                 xmlFreeDoc (modified.doc);
2484         return result;
2485 }
2486
2487 /**
2488  * gupnp_didl_lite_object_get_xml_string:
2489  * @object: #GUPnPDIDLLiteObject
2490  *
2491  * Get the representation of this object as an XML string.
2492  * Returns: (transfer full): XML representation of this object as string.
2493  **/
2494 char *
2495 gupnp_didl_lite_object_get_xml_string (GUPnPDIDLLiteObject *object)
2496 {
2497         xmlBuffer *buffer = NULL;
2498         char *ret = NULL;
2499
2500         buffer = xmlBufferCreate ();
2501         xmlNodeDump (buffer,
2502                      object->priv->xml_doc->doc,
2503                      object->priv->xml_node,
2504                      0,
2505                      0);
2506
2507         ret = g_strndup ((char *) xmlBufferContent (buffer),
2508                          xmlBufferLength (buffer));
2509         xmlBufferFree (buffer);
2510
2511         return ret;
2512 }