1 /***************************************************************************
2 * copyright : (C) 2006 Mattias Fliesberg *
3 * (C) 2007 Ian Monroe <ian@monroe.nu> *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License version 2 *
7 * as published by the Free Software Foundation. *
8 ***************************************************************************/
10 #include "xspfplaylist.h"
12 #include "atomicstring.h"
18 XSPFPlaylist::XSPFPlaylist( )
20 QDomElement root
= createElement( "playlist" );
22 root
.setAttribute( "version", 1 );
23 root
.setAttribute( "xmlns", "http://xspf.org/ns/1/" );
25 root
.appendChild( createElement( "trackList" ) );
30 XSPFPlaylist::XSPFPlaylist( QTextStream
&stream
)
36 XSPFPlaylist::loadXSPF( QTextStream
&stream
)
39 int errorLine
, errorColumn
;
40 stream
.setCodec( "UTF8" );
41 if (!setContent(stream
.readAll(), &errorMsg
, &errorLine
, &errorColumn
))
43 debug() << "[XSPFPlaylist]: Error loading xml file: " "(" << errorMsg
<< ")"
44 << " at line " << errorLine
<< ", column " << errorColumn
;
54 return documentElement().namedItem( "title" ).firstChild().nodeValue();
58 XSPFPlaylist::creator()
60 return documentElement().namedItem( "creator" ).firstChild().nodeValue();
64 XSPFPlaylist::annotation()
66 return documentElement().namedItem( "annotation" ).firstChild().nodeValue();
72 return KUrl( documentElement().namedItem( "info" ).firstChild().nodeValue() );
76 XSPFPlaylist::location()
78 return KUrl( documentElement().namedItem( "location" ).firstChild().nodeValue() );
82 XSPFPlaylist::identifier()
84 return documentElement().namedItem( "identifier" ).firstChild().nodeValue();
90 return KUrl( documentElement().namedItem( "image" ).firstChild().nodeValue() );
96 return QDateTime::fromString( documentElement().namedItem( "date" ).firstChild().nodeValue(), Qt::ISODate
);
100 XSPFPlaylist::license()
102 return KUrl( documentElement().namedItem( "license" ).firstChild().nodeValue() );
106 XSPFPlaylist::attribution()
108 QDomNode node
= documentElement().namedItem( "attribution" );
111 while ( !node
.isNull() )
113 if ( !node
.namedItem( "location" ).firstChild().nodeValue().isNull() )
114 list
.append( node
.namedItem( "location" ).firstChild().nodeValue() );
115 else if ( !node
.namedItem( "identifier" ).firstChild().nodeValue().isNull() )
116 list
.append( node
.namedItem( "identifier" ).firstChild().nodeValue() );
118 node
= node
.nextSibling();
127 return KUrl( documentElement().namedItem( "link" ).firstChild().nodeValue() );
131 XSPFPlaylist::setTitle( QString title
)
133 if ( documentElement().namedItem( "title" ).isNull() )
135 QDomNode node
= createElement( "title" );
136 QDomNode subNode
= createTextNode( title
);
137 node
.appendChild( subNode
);
138 documentElement().insertBefore( node
, documentElement().namedItem( "trackList" ) );
141 documentElement().namedItem( "title" ).replaceChild( createTextNode( title
), documentElement().namedItem( "title" ).firstChild() );
145 XSPFPlaylist::setCreator( QString creator
)
147 if ( documentElement().namedItem( "creator" ).isNull() )
149 QDomNode node
= createElement( "creator" );
150 QDomNode subNode
= createTextNode( creator
);
151 node
.appendChild( subNode
);
152 documentElement().insertBefore( node
, documentElement().namedItem( "trackList" ) );
155 documentElement().namedItem( "creator" ).replaceChild( createTextNode( creator
), documentElement().namedItem( "creator" ).firstChild() );
159 XSPFPlaylist::setAnnotation( QString annotation
)
161 if ( documentElement().namedItem( "annotation" ).isNull() )
163 QDomNode node
= createElement( "annotation" );
164 QDomNode subNode
= createTextNode( annotation
);
165 node
.appendChild( subNode
);
166 documentElement().insertBefore( node
, documentElement().namedItem( "trackList" ) );
169 documentElement().namedItem( "annotation" ).replaceChild( createTextNode( annotation
), documentElement().namedItem( "annotation" ).firstChild() );
173 XSPFPlaylist::setInfo( KUrl info
)
175 if ( documentElement().namedItem( "info" ).isNull() )
177 QDomNode node
= createElement( "info" );
178 QDomNode subNode
= createTextNode( info
.url() );
179 node
.appendChild( subNode
);
180 documentElement().insertBefore( node
, documentElement().namedItem( "trackList" ) );
183 documentElement().namedItem( "info" ).replaceChild( createTextNode( info
.url() ), documentElement().namedItem( "info" ).firstChild() );
187 XSPFPlaylist::setLocation( KUrl location
)
189 if ( documentElement().namedItem( "location" ).isNull() )
191 QDomNode node
= createElement( "location" );
192 QDomNode subNode
= createTextNode( location
.url() );
193 node
.appendChild( subNode
);
194 documentElement().insertBefore( node
, documentElement().namedItem( "trackList" ) );
197 documentElement().namedItem( "location" ).replaceChild( createTextNode( location
.url() ), documentElement().namedItem( "location" ).firstChild() );
201 XSPFPlaylist::setIdentifier( QString identifier
)
203 if ( documentElement().namedItem( "identifier" ).isNull() )
205 QDomNode node
= createElement( "identifier" );
206 QDomNode subNode
= createTextNode( identifier
);
207 node
.appendChild( subNode
);
208 documentElement().insertBefore( node
, documentElement().namedItem( "trackList" ) );
211 documentElement().namedItem( "identifier" ).replaceChild( createTextNode( identifier
), documentElement().namedItem( "identifier" ).firstChild() );
215 XSPFPlaylist::setImage( KUrl image
)
217 if ( documentElement().namedItem( "image" ).isNull() )
219 QDomNode node
= createElement( "image" );
220 QDomNode subNode
= createTextNode( image
.url() );
221 node
.appendChild( subNode
);
222 documentElement().insertBefore( node
, documentElement().namedItem( "trackList" ) );
225 documentElement().namedItem( "image" ).replaceChild( createTextNode( image
.url() ), documentElement().namedItem( "image" ).firstChild() );
229 XSPFPlaylist::setDate( QDateTime date
)
231 /* date needs timezone info to be compliant with the standard
232 (ex. 2005-01-08T17:10:47-05:00 ) */
234 if ( documentElement().namedItem( "date" ).isNull() )
236 QDomNode node
= createElement( "date" );
237 QDomNode subNode
= createTextNode( date
.toString( "yyyy-MM-ddThh:mm:ss" ) );
238 node
.appendChild( subNode
);
239 documentElement().insertBefore( node
, documentElement().namedItem( "trackList" ) );
242 documentElement().namedItem( "date" ).replaceChild( createTextNode( date
.toString( "yyyy-MM-ddThh:mm:ss" ) ), documentElement().namedItem( "date" ).firstChild() );
246 XSPFPlaylist::setLicense( KUrl license
)
248 if ( documentElement().namedItem( "license" ).isNull() )
250 QDomNode node
= createElement( "license" );
251 QDomNode subNode
= createTextNode( license
.url() );
252 node
.appendChild( subNode
);
253 documentElement().insertBefore( node
, documentElement().namedItem( "trackList" ) );
256 documentElement().namedItem( "license" ).replaceChild( createTextNode( license
.url() ), documentElement().namedItem( "license" ).firstChild() );
260 XSPFPlaylist::setAttribution( KUrl attribution
, bool append
)
262 if ( documentElement().namedItem( "attribution" ).isNull() )
263 documentElement().insertBefore( createElement( "attribution" ), documentElement().namedItem( "trackList" ) );
267 QDomNode subNode
= createElement( "location" );
268 QDomNode subSubNode
= createTextNode( attribution
.url() );
269 subNode
.appendChild( subSubNode
);
270 documentElement().namedItem( "attribution" ).insertBefore( subNode
, documentElement().namedItem( "attribution" ).firstChild() );
274 QDomNode node
= createElement( "attribution" );
275 QDomNode subNode
= createElement( "location" );
276 QDomNode subSubNode
= createTextNode( attribution
.url() );
277 subNode
.appendChild( subSubNode
);
278 node
.appendChild( subNode
);
279 documentElement().replaceChild( node
, documentElement().namedItem( "attribution" ) );
284 XSPFPlaylist::setLink( KUrl link
)
286 if ( documentElement().namedItem( "link" ).isNull() )
288 QDomNode node
= createElement( "link" );
289 QDomNode subNode
= createTextNode( link
.url() );
290 node
.appendChild( subNode
);
291 documentElement().insertBefore( node
, documentElement().namedItem( "trackList" ) );
294 documentElement().namedItem( "link" ).replaceChild( createTextNode( link
.url() ), documentElement().namedItem( "link" ).firstChild() );
297 XSPFPlaylist::trackList()
301 QDomNode trackList
= documentElement().namedItem( "trackList" );
302 QDomNode subNode
= trackList
.firstChild();
305 while ( !subNode
.isNull() )
308 subSubNode
= subNode
.firstChild();
309 if ( subNode
.nodeName() == "track" )
311 while ( !subSubNode
.isNull() )
313 if ( subSubNode
.nodeName() == "location" )
314 track
.location
= subSubNode
.firstChild().nodeValue();
315 else if ( subSubNode
.nodeName() == "title" )
316 track
.title
= subSubNode
.firstChild().nodeValue();
317 else if ( subSubNode
.nodeName() == "creator" )
318 track
.creator
= subSubNode
.firstChild().nodeValue();
319 else if ( subSubNode
.nodeName() == "duration" )
320 track
.duration
= subSubNode
.firstChild().nodeValue().toInt();
321 else if ( subSubNode
.nodeName() == "annotation" )
322 track
.annotation
= subSubNode
.firstChild().nodeValue();
323 else if ( subSubNode
.nodeName() == "album" )
324 track
.album
= subSubNode
.firstChild().nodeValue();
325 else if ( subSubNode
.nodeName() == "trackNum" )
326 track
.trackNum
= (uint
)subSubNode
.firstChild().nodeValue().toInt();
327 else if ( subSubNode
.nodeName() == "identifier" )
328 track
.identifier
= subSubNode
.firstChild().nodeValue();
329 else if ( subSubNode
.nodeName() == "info" )
330 track
.info
= subSubNode
.firstChild().nodeValue();
331 else if ( subSubNode
.nodeName() == "image" )
332 track
.image
= subSubNode
.firstChild().nodeValue();
333 else if ( subSubNode
.nodeName() == "link" )
334 track
.link
= subSubNode
.firstChild().nodeValue();
336 subSubNode
= subSubNode
.nextSibling();
339 list
.append( track
);
340 subNode
= subNode
.nextSibling();
347 //documentation of attributes from http://www.xspf.org/xspf-v1.html
349 XSPFPlaylist::setTrackList( Meta::TrackList trackList
, bool append
)
351 if ( documentElement().namedItem( "trackList" ).isNull() )
352 documentElement().appendChild( createElement( "trackList" ) );
354 QDomNode node
= createElement( "trackList" );
356 XSPFtrackList::iterator it
;
358 Meta::TrackPtr track
;
359 foreach( track
, trackList
)
361 QDomNode subNode
= createElement( "track" );
363 //URI of resource to be rendered.
364 QDomNode location
= createElement( "location" );
365 //Human-readable name of the track that authored the resource
366 QDomNode title
= createElement( "title" );
367 //Human-readable name of the entity that authored the resource.
368 QDomNode creator
= createElement( "creator" );
369 //A human-readable comment on the track.
370 QDomNode annotation
= createElement( "annotation" );
371 //Human-readable name of the collection from which the resource comes
372 QDomNode album
= createElement( "album" );
373 //Integer > 0 giving the ordinal position of the media in the album.
374 QDomNode trackNum
= createElement( "trackNum" );
375 //The time to render a resource, in milliseconds. It MUST be a nonNegativeInteger.
376 QDomNode duration
= createElement( "duration" );
378 //identifier - Canonical ID for this resource. Likely to be a hash or other
379 // location-independent name, such as a MusicBrainz identifier. MUST be a legal URI.
380 // QDomNode identifier = createElement( "identifier" );
381 //info - URI of a place where this resource can be bought or more info can be found.
382 // QDomNode info = createElement( "info" );
383 //image - URI of an image to display for the duration of the track.
384 // QDomNode image = createElement( "image" );
385 // link - element allows XSPF to be extended without the use of XML namespaces.
386 // QDomNode link = createElement( "link" );
388 // QDomNode extension
390 #define APPENDNODE( X, Y ) \
392 X.appendChild( createTextNode( Y ) ); \
393 subNode.appendChild( X ); \
396 if ( !track
->playableUrl().isEmpty() )
397 APPENDNODE(location
, track
->playableUrl().url() )
398 if ( !track
->name().isEmpty() )
399 APPENDNODE(title
, track
->name() )
400 if ( track
->artist() && track
->artist()->name().isEmpty() )
401 APPENDNODE(creator
, track
->artist()->name() );
402 if ( !track
->comment().isEmpty() )
403 APPENDNODE(annotation
, track
->comment() );
404 if ( track
->album() && !track
->album()->name().isEmpty() )
405 APPENDNODE( album
, track
->album()->name() );
406 if ( track
->trackNumber() > 0 )
407 APPENDNODE( trackNum
, QString::number( track
->trackNumber() ) );
408 if ( track
->length() > 0 )
409 APPENDNODE( duration
, QString::number( track
->length() * 1000 ) );
411 node
.appendChild( subNode
);
416 while ( !node
.isNull() )
418 documentElement().namedItem( "trackList" ).appendChild( node
.firstChild() );
419 node
= node
.nextSibling();
423 documentElement().replaceChild( node
, documentElement().namedItem( "trackList" ) );