00001 /*************************************************************************** 00002 * Copyright (C) 2006 by Michael Schulze * 00003 * mike.s@genion.de * 00004 * * 00005 * This program is free software; you can redistribute it and/or modify * 00006 * it under the terms of the GNU General Public License as published by * 00007 * the Free Software Foundation; either version 2 of the License, or * 00008 * (at your option) any later version. * 00009 * * 00010 * This program is distributed in the hope that it will be useful, * 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00013 * GNU General Public License for more details. * 00014 * * 00015 * You should have received a copy of the GNU General Public License * 00016 * along with this program; if not, write to the * 00017 * Free Software Foundation, Inc., * 00018 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 00019 ***************************************************************************/ 00020 00021 00022 #include <stdio.h> 00023 #include <qfile.h> 00024 #include <qstringlist.h> 00025 00026 #include <qobject.h> 00027 00028 #include "listtests.h" 00029 00030 #include "ipod.h" 00031 00032 00033 00034 #define RECENTLYPLAYEDTITLE "KPOD:Recently Played" 00035 #define RECENTLYSKIPPEDTITLE "KPOD:Recently Skipped" 00036 #define RECENTLYADDEDTITLE "KPOD:Recently added" 00037 #define FAVORITES "KPOD:Most Played" 00038 #define NEVERPLAYEDBEFORETITLE "KPOD:Never Played Before" 00039 #define HIGHESTRATEDLIST "KPOD:Highest Rated" 00040 00041 using namespace itunesdb; 00042 00043 /** 00044 * Creates a smart playlist with a rule for the matching the songs played in 00045 * the last 2 weeks and a limit for the 30 last played songs. 00046 */ 00047 void ListTests::createRecentlyPlayedList( ITunesDB& itunesdb ) { 00048 printf( "creating new smart playlist: %s\n", RECENTLYPLAYEDTITLE ); 00049 00050 // create a new playlist 00051 ITunesDBPlaylist * recentlyPlayed = itunesdb.createNewPlaylist( RECENTLYPLAYEDTITLE ); 00052 00053 recentlyPlayed->setSortOrder( Playlist::SORTORDER_TIME_PLAYED ); 00054 00055 // make it a smart playlist and get the ruleset 00056 SmartPlaylistRuleSet& ruleSet = recentlyPlayed->enableSmartPlaylist(); 00057 00058 // add the rule "last played in the last 2 weeks" 00059 ruleSet.addInTheLastRule( FIELD_LASTPLAYED, false, -2, IN_THE_LAST_WEEKS ); 00060 00061 // limit to the first 30 songs, sorted by last played date 00062 ruleSet.setLimits( LIMIT_SORT_LASTPLAYED, LIMIT_TYPE_SONGS, 30 ); 00063 00064 // match ANY rule (doesn't really matter since we only have one rule) 00065 ruleSet.setMatchAnyFlag( true ); 00066 00067 // enable live update (updates the playlist on the go) 00068 ruleSet.setLiveUpdateFlag( true ); 00069 00070 // finally add the playlist to the database 00071 if ( !itunesdb.addPlaylist( recentlyPlayed ) ) { 00072 delete recentlyPlayed; 00073 } 00074 } 00075 00076 /** 00077 * Creates a smart playlist with a rule for the matching the songs played in 00078 * the last 2 weeks and a limit for the 30 last played songs. 00079 */ 00080 void ListTests::createRecentlySkippedList( ITunesDB& itunesdb ) { 00081 printf( "creating new smart playlist: %s\n", RECENTLYSKIPPEDTITLE ); 00082 00083 // create a new playlist 00084 ITunesDBPlaylist * recentlySkipped = itunesdb.createNewPlaylist( RECENTLYSKIPPEDTITLE ); 00085 00086 recentlySkipped->setSortOrder( Playlist::SORTORDER_TIME_PLAYED ); 00087 00088 // make it a smart playlist and get the ruleset 00089 SmartPlaylistRuleSet& ruleSet = recentlySkipped->enableSmartPlaylist(); 00090 00091 // add the rule "last played in the last 2 weeks" 00092 ruleSet.addInTheLastRule( FIELD_LAST_SKIPPED, false, -2, IN_THE_LAST_WEEKS ); 00093 00094 // limit to the first 30 songs, sorted by last played date 00095 ruleSet.setLimits( LIMIT_SORT_LASTPLAYED, LIMIT_TYPE_SONGS, 30 ); 00096 00097 // match ANY rule (doesn't really matter since we only have one rule) 00098 ruleSet.setMatchAnyFlag( true ); 00099 00100 // enable live update (updates the playlist on the go) 00101 ruleSet.setLiveUpdateFlag( true ); 00102 00103 // finally add the playlist to the database 00104 if ( !itunesdb.addPlaylist( recentlySkipped ) ) { 00105 delete recentlySkipped; 00106 } 00107 } 00108 00109 00110 /** 00111 * Creates a smart playlist for the 25 most often played tracks 00112 */ 00113 void ListTests::createTop25List( ITunesDB& itunesdb ) { 00114 printf( "creating new smart playlist: %s\n", FAVORITES ); 00115 00116 // create a new playlist 00117 ITunesDBPlaylist * favorites = itunesdb.createNewPlaylist( FAVORITES ); 00118 00119 // sort by playcount 00120 favorites->setSortOrder( ITunesDBPlaylist::SORTORDER_PLAYCOUNT ); 00121 00122 // make it a smart playlist and get the ruleset 00123 SmartPlaylistRuleSet& ruleSet = favorites->enableSmartPlaylist(); 00124 00125 // only tracks that were played at least once 00126 ruleSet.addUIntRule( itunesdb::FIELD_PLAYCOUNT, itunesdb::ACTION_GREATER_THAN, 0, 0 ); 00127 00128 // limit to the 25 most played songs 00129 ruleSet.setLimits( LIMIT_SORT_PLAYCOUNT, LIMIT_TYPE_SONGS, 25 ); 00130 00131 // enable live update (updates the playlist on the go) 00132 ruleSet.setLiveUpdateFlag( true ); 00133 00134 // finally add the playlist to the database 00135 if ( !itunesdb.addPlaylist( favorites ) ) { 00136 delete favorites; 00137 } 00138 00139 } 00140 00141 00142 void ListTests::createNeverPlayedBeforeList( ITunesDB& itunesdb ) { 00143 printf( "creating new smart playlist: %s\n", NEVERPLAYEDBEFORETITLE ); 00144 00145 // create a new playlist 00146 ITunesDBPlaylist * neverplayed = itunesdb.createNewPlaylist( NEVERPLAYEDBEFORETITLE ); 00147 00148 neverplayed->setSortOrder( itunesdb::Playlist::SORTORDER_TIME_ADDED ); 00149 00150 SmartPlaylistRuleSet& ruleSet = neverplayed->enableSmartPlaylist(); 00151 ruleSet.setMatchAnyFlag( false ); 00152 ruleSet.addUIntRule( FIELD_LASTPLAYED, ACTION_IS_UINT, 0, 0 ); 00153 ruleSet.addUIntRule( FIELD_LAST_SKIPPED, ACTION_IS_UINT, 0, 0 ); 00154 ruleSet.setLimits( LIMIT_SORT_RECENTLYADDED, LIMIT_TYPE_SONGS, 50, true ); 00155 ruleSet.setLiveUpdateFlag( true ); 00156 00157 if ( !itunesdb.addPlaylist( neverplayed ) ) { 00158 delete neverplayed; 00159 } 00160 } 00161 00162 00163 void ListTests::createHighestRated( ITunesDB& itunesdb ) { 00164 printf( "creating new smart playlist: %s\n", HIGHESTRATEDLIST ); 00165 00166 // create a new playlist 00167 ITunesDBPlaylist * highestrated = itunesdb.createNewPlaylist( HIGHESTRATEDLIST ); 00168 00169 highestrated->setSortOrder( itunesdb::Playlist::SORTORDER_RANDOM ); 00170 00171 SmartPlaylistRuleSet& ruleSet = highestrated->enableSmartPlaylist(); 00172 ruleSet.setMatchAnyFlag( false ); 00173 ruleSet.addUIntRule( itunesdb::FIELD_RATING, ACTION_IS_UINT, 100, 100 ); 00174 ruleSet.setLiveUpdateFlag( true ); 00175 00176 if ( !itunesdb.addPlaylist( highestrated ) ) { 00177 delete highestrated; 00178 } 00179 } 00180 00181 00182 /** 00183 * Creates a playlist with the tracks added in the last 2 weeks 00184 */ 00185 void ListTests::createNewestAdditionsList( ITunesDB& itunesdb ) { 00186 printf( "creating new smart playlist: %s\n", RECENTLYADDEDTITLE ); 00187 00188 // create a new playlist 00189 ITunesDBPlaylist * recentlyAdded = itunesdb.createNewPlaylist( RECENTLYADDEDTITLE ); 00190 00191 // sort the playlist by artist 00192 recentlyAdded->setSortOrder( itunesdb::Playlist::SORTORDER_ARTIST ); 00193 00194 // make it smart and get a reference to the still empty ruleset 00195 SmartPlaylistRuleSet& ruleSet = recentlyAdded->enableSmartPlaylist(); 00196 00197 // add a rule matching all the tracks added in the last 2 weeks 00198 ruleSet.addInTheLastRule( FIELD_DATEADDED, false, -2, IN_THE_LAST_WEEKS ); 00199 00200 // enable live update 00201 ruleSet.setLiveUpdateFlag( true ); 00202 00203 // add the playlist to the database 00204 if ( !itunesdb.addPlaylist( recentlyAdded ) ) { 00205 delete recentlyAdded; 00206 } 00207 00208 } 00209 00210 00211 /** 00212 * Prints the contents of a playlist in the desired order to stdout. 00213 */ 00214 void ListTests::printSortedBy( ITunesDBPlaylist& playlist, Playlist::Sortorder order ) { 00215 // save the old sort order 00216 Playlist::Sortorder origOrder = playlist.getSortOrder(); 00217 // set the desired order 00218 playlist.setSortOrder( order ); 00219 00220 // iterate over the playlist 00221 Playlist::Iterator trackIter = playlist.getElements(); 00222 while( trackIter.hasNext() ) { 00223 Track * track = playlist.getTrack( *trackIter.next() ); 00224 00225 if ( track ) { 00226 fprintf( stdout, "\t%s\t\t%d,%d\t\t%s\t\t%s\n", 00227 track->getArtist().ascii(), track->getPlayCount(), track->getSkipCount(), track->getAlbum().ascii(), track->getTitle().ascii() ); 00228 } else { 00229 // this only happens if the database is inconsistent 00230 // this will be fixed when saving back the database 00231 fprintf( stdout, "\ttrack not found\n" ); 00232 } 00233 } 00234 00235 // restore the original sort order 00236 playlist.setSortOrder( origOrder ); 00237 } 00238 00239 00240 /** 00241 * This rather inefficient but informative example prints out all the tracks grouped by 00242 * artist and album, giving lots of examples on how to query the database for various information 00243 * 00244 * A more efficient way to do this would be to create a sorted TrackPtrList and iterate over it 00245 * printing Artist and Album every time it changes 00246 */ 00247 void ListTests::printTracksByArtist( const ITunesDB& itunesdb ) { 00248 // get a list of all artist names 00249 QStringList artistlist; 00250 if( !itunesdb.getArtists( artistlist ) ) { 00251 printf("NO ARTISTS!!!!"); 00252 } 00253 00254 // iterate over the artist names 00255 for( QStringList::iterator artistiterator = artistlist.begin(); artistiterator!= artistlist.end(); ++artistiterator ) { 00256 // print out the artist 00257 printf("%s\n", (*artistiterator).ascii()); 00258 00259 00260 // get a list of albums by the artist 00261 QStringList albums; 00262 if( ! itunesdb.getAlbumsByArtist( *artistiterator, albums ) ) { 00263 // doesn't happen 00264 printf("ARTIST NOT FOUND!!!"); 00265 } else { 00266 QStringList::iterator albumiterator = albums.begin(); 00267 for( ; albumiterator != albums.end(); ++albumiterator) { 00268 00269 // get the tracks in the album 00270 TrackPtrList album; 00271 // get the album by artistname, albumname 00272 itunesdb.getAlbum( *artistiterator, *albumiterator, album ); 00273 // sort by default sort order (track number) 00274 album.sort(); 00275 00276 // print out the albumname, number of tracks and if a track 00277 // of the album was played recently 00278 printf("\t%s (%d)%s\n", (*albumiterator).ascii(), album.count(), album.hasRecentlyPlayedTracks() ? " played recently" : ""); 00279 00280 // iterate over the tracks 00281 TrackPtrList::Iterator trackiterator = album.iterator(); 00282 while ( trackiterator.hasNext() ) { 00283 itunesdb::Track * track = trackiterator.next(); 00284 00285 QDateTime added; 00286 added.setTime_t( track->getDateAdded(), Qt::UTC ); 00287 00288 QDateTime played; 00289 played.setTime_t( track->getLastPlayed(), Qt::UTC ); 00290 00291 // print out number and title, last played date and 00292 // the date the track was added to the database 00293 printf("\t\t%d - %s - played %s, added %s\n", 00294 track->getTrackNumber(), track->getTitle().ascii(), 00295 played.toString().ascii(), added.toString().ascii() ); 00296 } 00297 } 00298 printf("\tall Tracks ...\n"); 00299 00300 00301 /****************************************************************** 00302 * 00303 * list all the tracks by the given artist, regardless of the album 00304 * 00305 *****************************************************************/ 00306 00307 // list all the tracks by the artist 00308 TrackPtrList artisttracks; 00309 // get all the tracks by the given artistname 00310 itunesdb.getTracksByArtist( *artistiterator, artisttracks ); 00311 00312 // sort the tracks by album 00313 artisttracks.setComparator( TrackComparators::BY_ALBUM ); 00314 artisttracks.sort(); 00315 00316 TrackPtrList::Iterator trackiterator = artisttracks.iterator(); 00317 while ( trackiterator.hasNext() ) { 00318 itunesdb::Track * track = trackiterator.next(); 00319 printf("\t\t%s - %d - %s\n", track->getAlbum().ascii(), track->getTrackNumber(), track->getTitle().ascii()); 00320 } 00321 } 00322 } 00323 } 00324 00325 /** 00326 * Print out all the playlists. 00327 */ 00328 void ListTests::printPlaylists( const ITunesDB& itunesdb ) { 00329 00330 // get all the playlist titles 00331 QStringList playlistTitles; 00332 itunesdb.getPlaylistTitles( playlistTitles ); 00333 00334 fprintf( stdout, "PLAYLISTS\n" ); 00335 00336 // iterate over all the playlists 00337 for ( unsigned int i = 0; i < playlistTitles.count(); ++i ) { 00338 ITunesDBPlaylist * playlist = itunesdb.getPlaylistByTitle( playlistTitles[ i ] ); 00339 00340 if ( playlist ) { // would be weird if not, but who knows 00341 if ( playlist->isSmartPlaylist() ) { 00342 // print out the ruleset 00343 fprintf( stdout, "%s\n", playlist->getSmartPlaylistRules()->toString().ascii() ); 00344 00345 // forced update of the playlists entries 00346 playlist->updateSmartPlaylist( true ); 00347 } 00348 00349 fprintf( stdout, "%s (%d) - original order\n", playlist->getTitle().ascii(), playlist->getNumTracks() ); 00350 printSortedBy( *playlist, playlist->getSortOrder() ); 00351 00352 fprintf( stdout, "%s - ordered by title\n", playlist->getTitle().ascii() ); 00353 printSortedBy( *playlist, Playlist::SORTORDER_TITLE ); 00354 00355 fprintf( stdout, "%s - ordered by artist\n", playlist->getTitle().ascii() ); 00356 printSortedBy( *playlist, Playlist::SORTORDER_ARTIST ); 00357 00358 fprintf( stdout, "%s - randomly\n", playlist->getTitle().ascii() ); 00359 printSortedBy( *playlist, Playlist::SORTORDER_RANDOM ); 00360 00361 fprintf( stdout, "%s - ordered by time played\n", playlist->getTitle().ascii() ); 00362 printSortedBy( *playlist, Playlist::SORTORDER_PLAYCOUNT ); 00363 } 00364 } 00365 00366 printf( "number of playlists: %u\n", itunesdb.getNumPlaylists() ); 00367 } 00368 00369 00370 int ListTests::run( QStringList& ) { 00371 IPod * ipod = findFirstIPod(); 00372 if ( !ipod ) { 00373 return -1; 00374 } 00375 00376 // get the iTunesDB instance 00377 ITunesDB& itunesdb = ipod->getITunesDB(); 00378 00379 // print out all the tracks 00380 printTracksByArtist( itunesdb ); 00381 00382 // test smart playlist stuff 00383 00384 ITunesDBPlaylist * spl = itunesdb.getPlaylistByTitle( RECENTLYPLAYEDTITLE ); 00385 if ( spl == NULL ) { 00386 createRecentlyPlayedList( itunesdb ); 00387 } 00388 00389 spl = itunesdb.getPlaylistByTitle( FAVORITES ); 00390 if ( spl == NULL ) { 00391 createTop25List( itunesdb ); 00392 } 00393 00394 spl = itunesdb.getPlaylistByTitle( NEVERPLAYEDBEFORETITLE ); 00395 if ( spl == NULL ) { 00396 createNeverPlayedBeforeList( itunesdb ); 00397 } 00398 00399 spl = itunesdb.getPlaylistByTitle( RECENTLYADDEDTITLE ); 00400 if ( spl == NULL ) { 00401 createNewestAdditionsList( itunesdb ); 00402 } 00403 00404 spl = itunesdb.getPlaylistByTitle( RECENTLYSKIPPEDTITLE ); 00405 if ( spl == NULL ) { 00406 createRecentlySkippedList( itunesdb ); 00407 } 00408 00409 spl = itunesdb.getPlaylistByTitle( HIGHESTRATEDLIST ); 00410 if ( spl == NULL ) { 00411 createHighestRated( itunesdb ); 00412 } 00413 00414 printPlaylists( itunesdb ); 00415 00416 printf( "%s is %s\n", ipod->getName().ascii(), ipod->isDirty() ? "dirty" : "clean" ); 00417 00418 // try to write 00419 #ifdef WIN32 00420 if ( !ipod->getITunesDB().writeDatabase( "iTunesDB" ) ) { 00421 printf( "writing database failed\n" ); 00422 } else { 00423 printf( "database successfully written\n" ); 00424 } 00425 #else 00426 ipod->getITunesDB().writeDatabase( "/tmp/iTunesDB" ); 00427 #endif 00428 printf("closing ipod instance\n"); 00429 ipod->close(); 00430 delete ipod; 00431 00432 return 0; 00433 } 00434 00435 QString ListTests::getName() { 00436 return "list"; 00437 } 00438 00439