File indexing completed on 2025-01-05 04:26:01

0001 /****************************************************************************************
0002  * Copyright (c) 2012 Matěj Laitl <matej@laitl.cz                                       *
0003  *                                                                                      *
0004  * This program is free software; you can redistribute it and/or modify it under        *
0005  * the terms of the GNU General Public License as published by the Free Software        *
0006  * Foundation; either version 2 of the License, or (at your option) any later           *
0007  * version.                                                                             *
0008  *                                                                                      *
0009  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0010  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0011  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0012  *                                                                                      *
0013  * You should have received a copy of the GNU General Public License along with         *
0014  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0015  ****************************************************************************************/
0016 
0017 #ifndef IPODMETA_H
0018 #define IPODMETA_H
0019 
0020 #include "MetaValues.h"
0021 #include "core/meta/Meta.h"
0022 #include "core/meta/Statistics.h"
0023 #include "core/meta/TrackEditor.h"
0024 
0025 #include <QPointer>
0026 #include <QReadWriteLock>
0027 
0028 #include <glib.h>
0029 
0030 struct _Itdb_Track;
0031 typedef _Itdb_Track Itdb_Track;
0032 class IpodCollection;
0033 
0034 namespace IpodMeta
0035 {
0036     /**
0037      * An iPod track. album, artist, composer etc. are invisible to outside world, they are
0038      * proxied in the MemoMeta track. All methods in this class are thread-safe with a few
0039      * exceptions that are noted in relevant method docstrings.
0040      */
0041     class Track : public Meta::Track, public Meta::Statistics, public Meta::TrackEditor
0042     {
0043         public:
0044             /**
0045              * Constructs an iPod track from an existing libgpod track structure. Caller
0046              * must guarantee that these are already added to the collection's itdb database.
0047              */
0048             explicit Track( Itdb_Track *ipodTrack );
0049 
0050             /**
0051              * Constructs an iPod track out of an existing track by copying its meta-data
0052              */
0053             explicit Track( const Meta::TrackPtr &origTrack );
0054 
0055             virtual ~Track();
0056 
0057             // Meta::Base methods:
0058             QString name() const override;
0059 
0060             // Meta::Track methods:
0061             QUrl playableUrl() const override;
0062             QString prettyUrl() const override;
0063             QString uidUrl() const override;
0064             QString notPlayableReason() const override;
0065 
0066             Meta::AlbumPtr album() const override;
0067             Meta::ArtistPtr artist() const override;
0068             Meta::ComposerPtr composer() const override;
0069             Meta::GenrePtr genre() const override;
0070             Meta::YearPtr year() const override;
0071 
0072             qreal bpm() const override;
0073             QString comment() const override;
0074 
0075             qint64 length() const override;
0076             int filesize() const override;
0077             int sampleRate() const override;
0078             int bitrate() const override;
0079 
0080             QDateTime createDate() const override;
0081             QDateTime modifyDate() const override;
0082 
0083             int trackNumber() const override;
0084             int discNumber() const override;
0085 
0086             qreal replayGain( Meta::ReplayGainTag mode ) const override;
0087             QString type() const override;
0088 
0089             bool inCollection() const override;
0090             Collections::Collection* collection() const override;
0091 
0092             Meta::TrackEditorPtr editor() override;
0093             Meta::StatisticsPtr statistics() override;
0094 
0095             // Meta::TrackEditor methods:
0096             void setAlbum( const QString &newAlbum ) override;
0097             void setAlbumArtist( const QString &newAlbumArtist ) override;
0098             void setArtist( const QString &newArtist ) override;
0099             void setComposer( const QString &newComposer ) override;
0100             void setGenre( const QString &newGenre ) override;
0101             void setYear( int newYear ) override;
0102             void setTitle( const QString &newTitle ) override;
0103             void setComment( const QString &newComment ) override;
0104             void setTrackNumber( int newTrackNumber ) override;
0105             void setDiscNumber( int newDiscNumber ) override;
0106             void setBpm( const qreal newBpm ) override;
0107 
0108             // Meta::Statistics methods:
0109             int rating() const override;
0110             void setRating( int newRating ) override;
0111 
0112             QDateTime lastPlayed() const override;
0113             void setLastPlayed( const QDateTime &time ) override;
0114 
0115             QDateTime firstPlayed() const override;
0116             void setFirstPlayed( const QDateTime &time ) override;
0117 
0118             int playCount() const override;
0119             int recentPlayCount() const override;
0120             void setPlayCount( const int playcount ) override;
0121 
0122             // Combined Meta::TrackEditor, Meta::Statistics methods:
0123             void beginUpdate() override;
0124             void endUpdate() override;
0125 
0126             // IpodMeta::Track methods:
0127             /**
0128              * Return a pointer to IpodMeta::Track given pointer to underlying libgpod
0129              * track. Does not attempt to create the track, so it may return null ptr if
0130              * there is no IpodMeta::Track associated with given libgpod track.
0131              */
0132             static Meta::TrackPtr fromIpodTrack( const Itdb_Track *ipodTrack );
0133 
0134             /**
0135              * Return a pointer to underlying libgpod track. You aren't allowed to cache
0136              * the pointer - IpodMeta::Track owns it. Guaranteed to be non-null and
0137              * constant throughout the lifetime of IpodMeta::Track.
0138              */
0139             Itdb_Track *itdbTrack() const;
0140 
0141             /**
0142              * CollectionLocation must call this method when it finishes copying the
0143              * track file onto iPod, before adding this track to IpodCollection.
0144              * Sets ipod_path, filetype_marker, transferred and size m_track fields.
0145              *
0146              * @param mountPoint a path where iPod is mounted, e.g. /media/MyiPod in local
0147              * encoding (use QFile::encodeName())
0148              * @param filePath full absolute path to copied file, must be in form
0149              * <@p mountPoint>/iPod_Control/Music/... - it is recommended to use
0150              * itdb_cp_get_dest_filename() to construct the filename
0151              *
0152              * @return true if the track was "accepted", false if not in which case you
0153              * shouldn't add it to collection.
0154              */
0155             bool finalizeCopying( const gchar *mountPoint, const gchar *filePath );
0156 
0157             /**
0158              * Set collection this track belongs to. If collection is not null, (re)set
0159              * the mount point stored in track. (affects playableUrl())
0160              */
0161             void setCollection( QPointer<IpodCollection> collection );
0162 
0163             // Methods for copy constructor:
0164             void setIsCompilation( bool newIsCompilation );
0165             void setImage( const QImage &newImage );
0166             void setLength( qint64 newLength );
0167             void setSampleRate( int newSampleRate );
0168             void setBitrate( int newBitrate );
0169             void setCreateDate( const QDateTime &newDate );
0170             void setModifyDate( const QDateTime &newDate );
0171             void setReplayGain( Meta::ReplayGainTag mode, qreal newReplayGain );
0172             void setType( const QString &newType );
0173 
0174         private:
0175             bool isEditable() const;
0176 
0177             /**
0178              * Must be called at end of every set*() method, with m_trackLock locked for
0179              * writing. Takes care of writing back the fields and notifying observers.
0180              */
0181             void commitIfInNonBatchUpdate( qint64 field, const QVariant &value );
0182             void commitIfInNonBatchUpdate();
0183 
0184             friend class Album; // so that is can access m_track and friends
0185 
0186             /**
0187              * Meta::Track is memory-managed using KSharedPointer to QSharedData, but
0188              * IpodCollection's memory management is out of our control, therefore the
0189              * weak pointer.
0190              */
0191             QPointer<IpodCollection> m_coll;
0192 
0193             /**
0194              * While mount point is accessible through m_track->itdb-> ..., we want to
0195              * remember our location even when we are removed from collection
0196              */
0197             QString m_mountPoint;
0198 
0199             /**
0200              * Associated libgpod track structure that holds all the data, we own this
0201              * pointer
0202              */
0203             Itdb_Track *const m_track; // yes, the address is constant, not the track
0204 
0205             /**
0206              * You must hold this lock when acessing m_track data. Beware that
0207              * m_track->itdb may change even with this lock hold - IpodCollection is the
0208              * owner of this field
0209              */
0210             mutable QReadWriteLock m_trackLock;
0211 
0212             /**
0213              * We need the temporary image file to exist for the lifetime of Track because
0214              * calling itdb_track_set_thumbnails() only saves the filename - the file is
0215              * read only when needed. If this path is non-empty, it means that the file
0216              * should be deleted in destructor.
0217              */
0218             QString m_tempImageFilePath;
0219 
0220             /**
0221              * Set of field types (identified by constants from MetaValues.h) changed by
0222              * TrackEditor or set{Rating,Score,...} not yet committed to database and
0223              * underlying file
0224              */
0225             Meta::FieldHash m_changedFields;
0226 
0227             /**
0228              * Number of current batch operations started by @see beginUpdate() and not
0229              * yet ended by @see endUpdate(). Must only be accessed with m_trackLock held.
0230              */
0231             int m_batch;
0232 
0233             static const quint64 m_gpodTrackUserTypeAmarokTrackPtr = Q_UINT64_C(0x416d61726f6b5472); /* AmarokTr */
0234     };
0235 
0236     /**
0237      * Dummy Artist that just stores its name; not visible from outside - iPod tracks are
0238      * proxied by MemoryMeta that creates its own Artist entities.
0239      */
0240     class Artist : public Meta::Artist
0241     {
0242         public:
0243             explicit Artist( const QString &name ) : m_name( name ) {}
0244             virtual ~Artist() {}
0245 
0246             QString name() const override { return m_name; }
0247             Meta::TrackList tracks() override { return Meta::TrackList(); }
0248 
0249         private:
0250             QString m_name;
0251     };
0252 
0253     /**
0254      * For performance reasons, Album stores just pointer to the tracks and reads all its
0255      * fields on-demand.
0256      */
0257     class Album : public Meta::Album
0258     {
0259         public:
0260             explicit Album( Track *track );
0261 
0262             QString name() const override;
0263             // dummy, iPod tracks are supposed to be proxied by MemoryMeta which handles this
0264             Meta::TrackList tracks() override { return Meta::TrackList(); }
0265 
0266             bool isCompilation() const override;
0267             bool canUpdateCompilation() const override;
0268             void setCompilation( bool isCompilation ) override;
0269 
0270             bool hasAlbumArtist() const override;
0271             Meta::ArtistPtr albumArtist() const override;
0272 
0273             bool hasImage( int size = 0 ) const override;
0274             QImage image( int size = 0 ) const override;
0275             bool canUpdateImage() const override;
0276             void setImage( const QImage &image ) override;
0277             void removeImage() override;
0278 
0279         private:
0280             AmarokSharedPointer<Track> m_track;
0281     };
0282 
0283     /**
0284      * Dummy Composer that just stores its name; not visible from outside - iPod tracks are
0285      * proxied by MemoryMeta that creates its own Composer entities.
0286      */
0287     class Composer : public Meta::Composer
0288     {
0289         public:
0290             explicit Composer( const QString &name ) : m_name( name ) {}
0291             virtual ~Composer() {}
0292 
0293             QString name() const override { return m_name; }
0294             Meta::TrackList tracks() override { return Meta::TrackList(); }
0295 
0296         private:
0297             QString m_name;
0298     };
0299 
0300     /**
0301      * Dummy Genre that just stores its name; not visible from outside - iPod tracks are
0302      * proxied by MemoryMeta that creates its own Genre entities.
0303      */
0304     class Genre : public Meta::Genre
0305     {
0306         public:
0307             explicit Genre( const QString &name ) : m_name( name ) {}
0308             virtual ~Genre() {}
0309 
0310             QString name() const override { return m_name; }
0311             Meta::TrackList tracks() override { return Meta::TrackList(); }
0312 
0313         private:
0314             QString m_name;
0315     };
0316 
0317     /**
0318      * Dummy Year that just stores its name; not visible from outside - iPod tracks are
0319      * proxied by MemoryMeta that creates its own Year entities.
0320      */
0321     class Year : public Meta::Year
0322     {
0323         public:
0324             explicit Year( const QString &name ) : m_name( name ) {}
0325             virtual ~Year() {}
0326 
0327             QString name() const override { return m_name; }
0328             Meta::TrackList tracks() override { return Meta::TrackList(); }
0329 
0330         private:
0331             QString m_name;
0332     };
0333 
0334 } // namespace IpodMeta
0335 
0336 #endif // IPODMETA_H