/*************************************************************************** * Copyright (C) 2004 by Michael Schulze * * mike.s@genion.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #ifndef TRACKCONTAINER_H #define TRACKCONTAINER_H #include #include #include #include #include "itunesdb/ItunesDBListener.h" #include "itunesdb/itunesdbdatasource.h" #include "itunesdb/playlist.h" #include "itunesdb/playlistitem.h" #include "trackmetadata.h" #include "tracklist.h" #include "artist.h" #define LISTITEM_DELETED PLAYLISTITEM_INVALID /** @author Michael Schulze */ class ITunesDB : public itunesdb::ItunesDBListener, itunesdb::ItunesDBDataSource { typedef Q3Dict ArtistMap; typedef Q3DictIterator ArtistMapIterator; typedef QMap TrackMap; public: QString error; ITunesDB(bool resolve_slashes= false); virtual ~ITunesDB(); /** * Opens the itunesdb file at the given ipod mountpoint * @return true if the itunesdb does exist and could be opened. For parse errors check the error member afterwards */ bool open(const QString& ipod_base); /** * Returns true if open() has already been successfully called. * @return true if open has already been successfully called, false otherwise */ bool isOpen(); bool writeDatabase(const QString& filename = QString()); /** * Returns true if the itunesdb file has been changed thus needs to be reloaded or does not exist anymore */ bool dbFileChanged(); QString getFilename() { return itunesdbfile.fileName(); } // ItunesDBDataSource Methods - for documentation see itunesdb/itunesdbdatasource.h void writeInit(); void writeFinished(); Q_UINT32 getNumPlaylists(); Q_UINT32 getNumTracks(); itunesdb::Playlist * getMainplaylist(); itunesdb::Playlist * firstPlaylist(); itunesdb::Playlist * nextPlaylist(); itunesdb::Track * firstTrack(); itunesdb::Track * nextTrack(); // ItunesDBListener Methods - for documentation see itunesdb/itunesdblistener.h void handleDataSet( Q_UINT32 type ); void handlePlaylist(const itunesdb::Playlist& playlist); void handleOTGPlaylist(const itunesdb::Playlist& playlist); void handlePlaycount( Q_UINT32 idx, Q_UINT32 lastplayed, Q_UINT32 stars, Q_UINT32 count, Q_UINT32 bookmark); void handleTrack(const itunesdb::Track& track); void handleError(const QString &message); void setNumPlaylists(Q_UINT32); void setNumTracks(Q_UINT32); void parseStarted(); void parseFinished(); // additional methods used by the IOslave /** * adds a new Track to the database after itunesDBlistener is done (finished) */ void addTrack(TrackMetadata& track); /** * returns the Track corresponding to the given ID * @param id ID of the track * @return the Track corresponding to the given ID */ TrackMetadata * getTrackByID(const Q_UINT32 id) const; /** * returns the Track found by the given information or NULL if no such Track could be found * @param artistname the name of the artist * @param albumname the name of the album * @param title the title of the track */ TrackMetadata * findTrack(const QString& artistname, const QString& albumname, const QString& title) const; /** * Returns fills the given QStringList with the names of all artists in the database * @return a pointer to the StringList */ QStringList * getArtists(QStringList &buffer) const; /** * Returns an Artist by the given name * @param artistname the artists name * @return an Artist by the given name or NULL if the artist could not be found by the given name */ Artist * getArtistByName(const QString& artistname) const; /** * Returns an Artist by the given name * @param artistname the artists name * @param create if true this function will create a new Artist for the given name of no such artist exists yet * @return an Artist by the given name or NULL if the artist could not be found by the given name and create is false */ Artist * getArtistByName(const QString &artistname, bool create); /** * Returns an album (list of trackIDs) by the given Artist/Album * @param artistname name of the artist of the album in question * @param albumname name of the album * @return a pointer to the album or NULL if no album could by found */ TrackList * getAlbum(const QString &artistname, const QString &albumname) const; /** * Returns a playlist by the given playlist title. * @param playlisttitle title of the playlist in question * @return a pointer to the playlist found or NULL if no such playlist exists */ TrackList * getPlaylistByTitle(const QString& playlisttitle) const; /** * removes an empty artist from the database */ bool removeArtist(const QString& artistname); /** * Renames an album with the given title and artist to newtitle, newartist */ TrackList * renameAlbum(TrackList& album, const QString& newartistname, const QString& newtitle); /** * Removes the playlist with the given title * @param title the title of the playlist to be removed * @param delete_instance if set to true the element gets deleted during removal * @return true if successful, otherwise false */ bool removePlaylist( const QString& title, bool delete_instance); /** * Removes the Track with the given trackid from the database. * This also removes all playlist references to this track * @param trackid ID of the track to be deleted * @param delete_instance if set to true (default) the Track gets deleted during removal * @return the trackid of the Track or 0 if no such Track exists */ Q_UINT32 removeTrack(Q_UINT32 trackid, bool delete_instance = true); /** * Sets a new artist/playlist for the given Trackid * @return true if successful, false if the track couldn't be found */ bool moveTrack(TrackMetadata& track, const QString& newartist, const QString& newalbum); /** * Wipes all data from the container. */ void clear(); /** * returns true if something in the container's control has been changed. * a change to a Playlist or a Track for example will not set the change flag yet. */ bool isChanged(); /** * Returns the max track ID found */ Q_UINT32 getMaxTrackID() { return maxtrackid; } Q_UINT64 getMaxTrackDBID() { return maxTrackDBID; } /** * Lock control functions to prevent concurrent access to the Database from different slaves */ void lock(bool write_lock); void unlock(); /** * Create a unique playlist title from a given prefix * e.g. On The Go -> On The Go-12 */ QString createPlaylistTitle( const QString &title ); uint lastModified() { return timestamp.toTime_t(); } QString getMainListTitle() const { return mainlist.getTitle(); } bool hasPodcasts() const { return hasPodcastsFlag; } protected: TrackMap trackmap; ArtistMap artistmap; TrackList mainlist; class PlaylistContainer; PlaylistContainer * playlists; bool resolveslashes; // replace '/' in Strings with %2F ? TODO doesn't belong here anymore bool changed; Q_UINT32 maxtrackid; Q_UINT64 maxTrackDBID; void insertTrackToDataBase(TrackMetadata& track); private: void convertOffsetsToIDs(itunesdb::Playlist& playlist); void removeFromAllPlaylists( Q_UINT32 trackid ); // helper class to sort playcounts by last played date class PlaycountSorter; PlaycountSorter * m_recentlyPlayed; TrackMap::iterator trackiterator; QFile itunesdbfile; QFile itunessdfile; QDateTime timestamp; uint currentDataSet; // refelcts the current dataset while parsing the itunesdb bool hasPodcastsFlag; }; #endif