add mp3 and ogg torrent url info to JamendoAlbum
[amarok.git] / src / xspfplaylist.cpp
blob42061c69fa64a507a4940d94aa7abe452ca14d0b
1 /***************************************************************************
2 * copyright : (C) 2006 Mattias Fliesberg *
3 * (C) 2007 Ian Monroe <ian@monroe.nu> *
4 * *
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"
13 #include "debug.h"
14 #include "meta.h"
16 #include <QDateTime>
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" ) );
27 appendChild( root );
30 XSPFPlaylist::XSPFPlaylist( QTextStream &stream )
32 loadXSPF( stream );
35 bool
36 XSPFPlaylist::loadXSPF( QTextStream &stream )
38 QString errorMsg;
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;
45 return false;
48 return true;
51 QString
52 XSPFPlaylist::title()
54 return documentElement().namedItem( "title" ).firstChild().nodeValue();
57 QString
58 XSPFPlaylist::creator()
60 return documentElement().namedItem( "creator" ).firstChild().nodeValue();
63 QString
64 XSPFPlaylist::annotation()
66 return documentElement().namedItem( "annotation" ).firstChild().nodeValue();
69 KUrl
70 XSPFPlaylist::info()
72 return KUrl( documentElement().namedItem( "info" ).firstChild().nodeValue() );
75 KUrl
76 XSPFPlaylist::location()
78 return KUrl( documentElement().namedItem( "location" ).firstChild().nodeValue() );
81 QString
82 XSPFPlaylist::identifier()
84 return documentElement().namedItem( "identifier" ).firstChild().nodeValue();
87 KUrl
88 XSPFPlaylist::image()
90 return KUrl( documentElement().namedItem( "image" ).firstChild().nodeValue() );
93 QDateTime
94 XSPFPlaylist::date()
96 return QDateTime::fromString( documentElement().namedItem( "date" ).firstChild().nodeValue(), Qt::ISODate );
99 KUrl
100 XSPFPlaylist::license()
102 return KUrl( documentElement().namedItem( "license" ).firstChild().nodeValue() );
105 KUrl::List
106 XSPFPlaylist::attribution()
108 QDomNode node = documentElement().namedItem( "attribution" );
109 KUrl::List list;
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();
121 return list;
124 KUrl
125 XSPFPlaylist::link()
127 return KUrl( documentElement().namedItem( "link" ).firstChild().nodeValue() );
130 void
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" ) );
140 else
141 documentElement().namedItem( "title" ).replaceChild( createTextNode( title ), documentElement().namedItem( "title" ).firstChild() );
144 void
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" ) );
154 else
155 documentElement().namedItem( "creator" ).replaceChild( createTextNode( creator ), documentElement().namedItem( "creator" ).firstChild() );
158 void
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" ) );
168 else
169 documentElement().namedItem( "annotation" ).replaceChild( createTextNode( annotation ), documentElement().namedItem( "annotation" ).firstChild() );
172 void
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" ) );
182 else
183 documentElement().namedItem( "info" ).replaceChild( createTextNode( info.url() ), documentElement().namedItem( "info" ).firstChild() );
186 void
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" ) );
196 else
197 documentElement().namedItem( "location" ).replaceChild( createTextNode( location.url() ), documentElement().namedItem( "location" ).firstChild() );
200 void
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" ) );
210 else
211 documentElement().namedItem( "identifier" ).replaceChild( createTextNode( identifier ), documentElement().namedItem( "identifier" ).firstChild() );
214 void
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" ) );
224 else
225 documentElement().namedItem( "image" ).replaceChild( createTextNode( image.url() ), documentElement().namedItem( "image" ).firstChild() );
228 void
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" ) );
241 else
242 documentElement().namedItem( "date" ).replaceChild( createTextNode( date.toString( "yyyy-MM-ddThh:mm:ss" ) ), documentElement().namedItem( "date" ).firstChild() );
245 void
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" ) );
255 else
256 documentElement().namedItem( "license" ).replaceChild( createTextNode( license.url() ), documentElement().namedItem( "license" ).firstChild() );
259 void
260 XSPFPlaylist::setAttribution( KUrl attribution, bool append )
262 if ( documentElement().namedItem( "attribution" ).isNull() )
263 documentElement().insertBefore( createElement( "attribution" ), documentElement().namedItem( "trackList" ) );
265 if ( append )
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() );
272 else
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" ) );
283 void
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" ) );
293 else
294 documentElement().namedItem( "link" ).replaceChild( createTextNode( link.url() ), documentElement().namedItem( "link" ).firstChild() );
296 XSPFtrackList
297 XSPFPlaylist::trackList()
299 XSPFtrackList list;
301 QDomNode trackList = documentElement().namedItem( "trackList" );
302 QDomNode subNode = trackList.firstChild();
303 QDomNode subSubNode;
305 while ( !subNode.isNull() )
307 XSPFtrack track;
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();
343 return list;
347 //documentation of attributes from http://www.xspf.org/xspf-v1.html
348 void
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" );
387 // QDomNode meta
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 ) );
410 #undef APPENDNODE
411 node.appendChild( subNode );
414 if ( append )
416 while ( !node.isNull() )
418 documentElement().namedItem( "trackList" ).appendChild( node.firstChild() );
419 node = node.nextSibling();
422 else
423 documentElement().replaceChild( node, documentElement().namedItem( "trackList" ) );