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