Revert previous commit, was incorrect
[amarok.git] / src / xspfplaylist.cpp
blob9899b19978013e3c741babbcf4798ebeb198ed93
1 /***************************************************************************
2 * copyright : (C) 2006 Mattias Fliesberg <mattias.fliesberg@gmail.com> *
3 * (C) 2007 Ian Monroe <ian@monroe.nu> *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License or (at your option) version 3 or any later version
9 * accepted by the membership of KDE e.V. (or its successor approved
10 * by the membership of KDE e.V.), which shall act as a proxy
11 * defined in Section 14 of version 3 of the license.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 **************************************************************************/
24 #include "xspfplaylist.h"
26 #include "atomicstring.h"
27 #include "debug.h"
28 #include "Meta.h"
30 #include <QDateTime>
32 XSPFPlaylist::XSPFPlaylist( )
34 QDomElement root = createElement( "playlist" );
36 root.setAttribute( "version", 1 );
37 root.setAttribute( "xmlns", "http://xspf.org/ns/1/" );
39 root.appendChild( createElement( "trackList" ) );
41 appendChild( root );
44 XSPFPlaylist::XSPFPlaylist( QTextStream &stream )
46 loadXSPF( stream );
49 bool
50 XSPFPlaylist::loadXSPF( QTextStream &stream )
52 QString errorMsg;
53 int errorLine, errorColumn;
54 stream.setCodec( "UTF8" );
55 if (!setContent(stream.readAll(), &errorMsg, &errorLine, &errorColumn))
57 debug() << "[XSPFPlaylist]: Error loading xml file: " "(" << errorMsg << ")"
58 << " at line " << errorLine << ", column " << errorColumn;
59 return false;
62 return true;
65 QString
66 XSPFPlaylist::title()
68 return documentElement().namedItem( "title" ).firstChild().nodeValue();
71 QString
72 XSPFPlaylist::creator()
74 return documentElement().namedItem( "creator" ).firstChild().nodeValue();
77 QString
78 XSPFPlaylist::annotation()
80 return documentElement().namedItem( "annotation" ).firstChild().nodeValue();
83 KUrl
84 XSPFPlaylist::info()
86 return KUrl( documentElement().namedItem( "info" ).firstChild().nodeValue() );
89 KUrl
90 XSPFPlaylist::location()
92 return KUrl( documentElement().namedItem( "location" ).firstChild().nodeValue() );
95 QString
96 XSPFPlaylist::identifier()
98 return documentElement().namedItem( "identifier" ).firstChild().nodeValue();
101 KUrl
102 XSPFPlaylist::image()
104 return KUrl( documentElement().namedItem( "image" ).firstChild().nodeValue() );
107 QDateTime
108 XSPFPlaylist::date()
110 return QDateTime::fromString( documentElement().namedItem( "date" ).firstChild().nodeValue(), Qt::ISODate );
113 KUrl
114 XSPFPlaylist::license()
116 return KUrl( documentElement().namedItem( "license" ).firstChild().nodeValue() );
119 KUrl::List
120 XSPFPlaylist::attribution()
122 QDomNode node = documentElement().namedItem( "attribution" );
123 KUrl::List list;
125 while ( !node.isNull() )
127 if ( !node.namedItem( "location" ).firstChild().nodeValue().isNull() )
128 list.append( node.namedItem( "location" ).firstChild().nodeValue() );
129 else if ( !node.namedItem( "identifier" ).firstChild().nodeValue().isNull() )
130 list.append( node.namedItem( "identifier" ).firstChild().nodeValue() );
132 node = node.nextSibling();
135 return list;
138 KUrl
139 XSPFPlaylist::link()
141 return KUrl( documentElement().namedItem( "link" ).firstChild().nodeValue() );
144 void
145 XSPFPlaylist::setTitle( QString title )
147 if ( documentElement().namedItem( "title" ).isNull() )
149 QDomNode node = createElement( "title" );
150 QDomNode subNode = createTextNode( title );
151 node.appendChild( subNode );
152 documentElement().insertBefore( node, documentElement().namedItem( "trackList" ) );
154 else
155 documentElement().namedItem( "title" ).replaceChild( createTextNode( title ), documentElement().namedItem( "title" ).firstChild() );
158 void
159 XSPFPlaylist::setCreator( QString creator )
161 if ( documentElement().namedItem( "creator" ).isNull() )
163 QDomNode node = createElement( "creator" );
164 QDomNode subNode = createTextNode( creator );
165 node.appendChild( subNode );
166 documentElement().insertBefore( node, documentElement().namedItem( "trackList" ) );
168 else
169 documentElement().namedItem( "creator" ).replaceChild( createTextNode( creator ), documentElement().namedItem( "creator" ).firstChild() );
172 void
173 XSPFPlaylist::setAnnotation( QString annotation )
175 if ( documentElement().namedItem( "annotation" ).isNull() )
177 QDomNode node = createElement( "annotation" );
178 QDomNode subNode = createTextNode( annotation );
179 node.appendChild( subNode );
180 documentElement().insertBefore( node, documentElement().namedItem( "trackList" ) );
182 else
183 documentElement().namedItem( "annotation" ).replaceChild( createTextNode( annotation ), documentElement().namedItem( "annotation" ).firstChild() );
186 void
187 XSPFPlaylist::setInfo( KUrl info )
189 if ( documentElement().namedItem( "info" ).isNull() )
191 QDomNode node = createElement( "info" );
192 QDomNode subNode = createTextNode( info.url() );
193 node.appendChild( subNode );
194 documentElement().insertBefore( node, documentElement().namedItem( "trackList" ) );
196 else
197 documentElement().namedItem( "info" ).replaceChild( createTextNode( info.url() ), documentElement().namedItem( "info" ).firstChild() );
200 void
201 XSPFPlaylist::setLocation( KUrl location )
203 if ( documentElement().namedItem( "location" ).isNull() )
205 QDomNode node = createElement( "location" );
206 QDomNode subNode = createTextNode( location.url() );
207 node.appendChild( subNode );
208 documentElement().insertBefore( node, documentElement().namedItem( "trackList" ) );
210 else
211 documentElement().namedItem( "location" ).replaceChild( createTextNode( location.url() ), documentElement().namedItem( "location" ).firstChild() );
214 void
215 XSPFPlaylist::setIdentifier( QString identifier )
217 if ( documentElement().namedItem( "identifier" ).isNull() )
219 QDomNode node = createElement( "identifier" );
220 QDomNode subNode = createTextNode( identifier );
221 node.appendChild( subNode );
222 documentElement().insertBefore( node, documentElement().namedItem( "trackList" ) );
224 else
225 documentElement().namedItem( "identifier" ).replaceChild( createTextNode( identifier ), documentElement().namedItem( "identifier" ).firstChild() );
228 void
229 XSPFPlaylist::setImage( KUrl image )
231 if ( documentElement().namedItem( "image" ).isNull() )
233 QDomNode node = createElement( "image" );
234 QDomNode subNode = createTextNode( image.url() );
235 node.appendChild( subNode );
236 documentElement().insertBefore( node, documentElement().namedItem( "trackList" ) );
238 else
239 documentElement().namedItem( "image" ).replaceChild( createTextNode( image.url() ), documentElement().namedItem( "image" ).firstChild() );
242 void
243 XSPFPlaylist::setDate( QDateTime date )
245 /* date needs timezone info to be compliant with the standard
246 (ex. 2005-01-08T17:10:47-05:00 ) */
248 if ( documentElement().namedItem( "date" ).isNull() )
250 QDomNode node = createElement( "date" );
251 QDomNode subNode = createTextNode( date.toString( "yyyy-MM-ddThh:mm:ss" ) );
252 node.appendChild( subNode );
253 documentElement().insertBefore( node, documentElement().namedItem( "trackList" ) );
255 else
256 documentElement().namedItem( "date" ).replaceChild( createTextNode( date.toString( "yyyy-MM-ddThh:mm:ss" ) ), documentElement().namedItem( "date" ).firstChild() );
259 void
260 XSPFPlaylist::setLicense( KUrl license )
262 if ( documentElement().namedItem( "license" ).isNull() )
264 QDomNode node = createElement( "license" );
265 QDomNode subNode = createTextNode( license.url() );
266 node.appendChild( subNode );
267 documentElement().insertBefore( node, documentElement().namedItem( "trackList" ) );
269 else
270 documentElement().namedItem( "license" ).replaceChild( createTextNode( license.url() ), documentElement().namedItem( "license" ).firstChild() );
273 void
274 XSPFPlaylist::setAttribution( KUrl attribution, bool append )
276 if ( documentElement().namedItem( "attribution" ).isNull() )
277 documentElement().insertBefore( createElement( "attribution" ), documentElement().namedItem( "trackList" ) );
279 if ( append )
281 QDomNode subNode = createElement( "location" );
282 QDomNode subSubNode = createTextNode( attribution.url() );
283 subNode.appendChild( subSubNode );
284 documentElement().namedItem( "attribution" ).insertBefore( subNode, documentElement().namedItem( "attribution" ).firstChild() );
286 else
288 QDomNode node = createElement( "attribution" );
289 QDomNode subNode = createElement( "location" );
290 QDomNode subSubNode = createTextNode( attribution.url() );
291 subNode.appendChild( subSubNode );
292 node.appendChild( subNode );
293 documentElement().replaceChild( node, documentElement().namedItem( "attribution" ) );
297 void
298 XSPFPlaylist::setLink( KUrl link )
300 if ( documentElement().namedItem( "link" ).isNull() )
302 QDomNode node = createElement( "link" );
303 QDomNode subNode = createTextNode( link.url() );
304 node.appendChild( subNode );
305 documentElement().insertBefore( node, documentElement().namedItem( "trackList" ) );
307 else
308 documentElement().namedItem( "link" ).replaceChild( createTextNode( link.url() ), documentElement().namedItem( "link" ).firstChild() );
310 XSPFtrackList
311 XSPFPlaylist::trackList()
313 XSPFtrackList list;
315 QDomNode trackList = documentElement().namedItem( "trackList" );
316 QDomNode subNode = trackList.firstChild();
317 QDomNode subSubNode;
319 while ( !subNode.isNull() )
321 XSPFtrack track;
322 subSubNode = subNode.firstChild();
323 if ( subNode.nodeName() == "track" )
325 while ( !subSubNode.isNull() )
327 if ( subSubNode.nodeName() == "location" )
328 track.location = subSubNode.firstChild().nodeValue();
329 else if ( subSubNode.nodeName() == "title" )
330 track.title = subSubNode.firstChild().nodeValue();
331 else if ( subSubNode.nodeName() == "creator" )
332 track.creator = subSubNode.firstChild().nodeValue();
333 else if ( subSubNode.nodeName() == "duration" )
334 track.duration = subSubNode.firstChild().nodeValue().toInt();
335 else if ( subSubNode.nodeName() == "annotation" )
336 track.annotation = subSubNode.firstChild().nodeValue();
337 else if ( subSubNode.nodeName() == "album" )
338 track.album = subSubNode.firstChild().nodeValue();
339 else if ( subSubNode.nodeName() == "trackNum" )
340 track.trackNum = (uint)subSubNode.firstChild().nodeValue().toInt();
341 else if ( subSubNode.nodeName() == "identifier" )
342 track.identifier = subSubNode.firstChild().nodeValue();
343 else if ( subSubNode.nodeName() == "info" )
344 track.info = subSubNode.firstChild().nodeValue();
345 else if ( subSubNode.nodeName() == "image" )
346 track.image = subSubNode.firstChild().nodeValue();
347 else if ( subSubNode.nodeName() == "link" )
348 track.link = subSubNode.firstChild().nodeValue();
350 subSubNode = subSubNode.nextSibling();
353 list.append( track );
354 subNode = subNode.nextSibling();
357 return list;
361 //documentation of attributes from http://www.xspf.org/xspf-v1.html
362 void
363 XSPFPlaylist::setTrackList( Meta::TrackList trackList, bool append )
365 if ( documentElement().namedItem( "trackList" ).isNull() )
366 documentElement().appendChild( createElement( "trackList" ) );
368 QDomNode node = createElement( "trackList" );
370 XSPFtrackList::iterator it;
372 Meta::TrackPtr track;
373 foreach( track, trackList )
375 QDomNode subNode = createElement( "track" );
377 //URI of resource to be rendered.
378 QDomNode location = createElement( "location" );
379 //Human-readable name of the track that authored the resource
380 QDomNode title = createElement( "title" );
381 //Human-readable name of the entity that authored the resource.
382 QDomNode creator = createElement( "creator" );
383 //A human-readable comment on the track.
384 QDomNode annotation = createElement( "annotation" );
385 //Human-readable name of the collection from which the resource comes
386 QDomNode album = createElement( "album" );
387 //Integer > 0 giving the ordinal position of the media in the album.
388 QDomNode trackNum = createElement( "trackNum" );
389 //The time to render a resource, in milliseconds. It MUST be a nonNegativeInteger.
390 QDomNode duration = createElement( "duration" );
392 //identifier - Canonical ID for this resource. Likely to be a hash or other
393 // location-independent name, such as a MusicBrainz identifier. MUST be a legal URI.
394 // QDomNode identifier = createElement( "identifier" );
395 //info - URI of a place where this resource can be bought or more info can be found.
396 // QDomNode info = createElement( "info" );
397 //image - URI of an image to display for the duration of the track.
398 // QDomNode image = createElement( "image" );
399 // link - element allows XSPF to be extended without the use of XML namespaces.
400 // QDomNode link = createElement( "link" );
401 // QDomNode meta
402 // QDomNode extension
404 #define APPENDNODE( X, Y ) \
406 X.appendChild( createTextNode( Y ) ); \
407 subNode.appendChild( X ); \
410 if ( !track->playableUrl().isEmpty() )
411 APPENDNODE(location, track->playableUrl().url() )
412 if ( !track->name().isEmpty() )
413 APPENDNODE(title, track->name() )
414 if ( track->artist() && !track->artist()->name().isEmpty() )
415 APPENDNODE(creator, track->artist()->name() );
416 if ( !track->comment().isEmpty() )
417 APPENDNODE(annotation, track->comment() );
418 if ( track->album() && !track->album()->name().isEmpty() )
419 APPENDNODE( album, track->album()->name() );
420 if ( track->trackNumber() > 0 )
421 APPENDNODE( trackNum, QString::number( track->trackNumber() ) );
422 if ( track->length() > 0 )
423 APPENDNODE( duration, QString::number( track->length() * 1000 ) );
424 #undef APPENDNODE
425 node.appendChild( subNode );
428 if ( append )
430 while ( !node.isNull() )
432 documentElement().namedItem( "trackList" ).appendChild( node.firstChild() );
433 node = node.nextSibling();
436 else
437 documentElement().replaceChild( node, documentElement().namedItem( "trackList" ) );