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

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 IPODCOLLECTION_H
0018 #define IPODCOLLECTION_H
0019 
0020 #include "ui_IpodConfiguration.h"
0021 #include "core/collections/Collection.h"
0022 #include "core/meta/Observer.h"
0023 
0024 #include <QMutex>
0025 #include <QSharedPointer>
0026 #include <QTimer>
0027 
0028 namespace Collections { class MemoryCollection; }
0029 namespace IpodMeta { class Track; }
0030 class IphoneMountPoint;
0031 class IpodParseTracksJob;
0032 class IpodWriteDatabaseJob;
0033 class IpodPlaylistProvider;
0034 class QDir;
0035 class QTemporaryFile;
0036 struct _Itdb_iTunesDB;
0037 typedef _Itdb_iTunesDB Itdb_iTunesDB;
0038 
0039 namespace Playlists
0040 {
0041 class UserPlaylistProvider;
0042 }
0043 
0044 class IpodCollection : public Collections::Collection, public Meta::Observer
0045 {
0046     Q_OBJECT
0047 
0048     public:
0049         /**
0050          * Creates an iPod collection on top of already-mounted filesystem.
0051          *
0052          * @param mountPoint actual iPod mount point to use, must be already mounted and
0053          * accessible. When eject is requested, solid StorageAccess with this mount point
0054          * is searched for to perform unmounting.
0055          * @param uuid filesystem volume UUID or another unique identifier for this iPod
0056          */
0057         explicit IpodCollection( const QDir &mountPoint, const QString &uuid );
0058 
0059         /**
0060          * Creates an iPod collection on top of not-mounted iPhone/iPad by accessing it
0061          * using libimobiledevice by its 40-digit device UUID. UUID may be empty which
0062          * means "any connected iPhone/iPad".
0063          */
0064         explicit IpodCollection( const QString &uuid );
0065 
0066         virtual ~IpodCollection();
0067 
0068         // TrackProvider methods:
0069         bool possiblyContainsTrack( const QUrl &url ) const override;
0070         Meta::TrackPtr trackForUrl( const QUrl &url ) override;
0071 
0072         // CollectionBase methods:
0073         bool hasCapabilityInterface( Capabilities::Capability::Type type ) const override;
0074         Capabilities::Capability* createCapabilityInterface( Capabilities::Capability::Type type ) override;
0075 
0076         // Collection methods:
0077         Collections::QueryMaker *queryMaker() override;
0078 
0079         QString uidUrlProtocol() const override;
0080         QString collectionId() const override;
0081         QString prettyName() const override;
0082         QIcon icon() const override;
0083 
0084         bool hasCapacity() const override;
0085         float usedCapacity() const override;
0086         float totalCapacity() const override;
0087 
0088         Collections::CollectionLocation *location() override;
0089         bool isWritable() const override;
0090         bool isOrganizable() const override;
0091 
0092         // Observer methods:
0093         void metadataChanged( const Meta::TrackPtr &track ) override;
0094         // so that the compiler doesn't complain about hidden virtual functions:
0095         using Meta::Observer::metadataChanged;
0096 
0097         // IpodCollection methods:
0098         /**
0099          * In-fact second phase of the constructor. Called by CollectionFactory right after
0100          * constructor. Should return true if the collection initialised itself successfully
0101          * and should be shown to the user; return value of false means it should be
0102          * destroyed and forgotten by the factory.
0103          */
0104         bool init();
0105 
0106         /**
0107          * Get local mount point. Can return QString() in case no reasonable mountpoint
0108          * is available
0109          */
0110         QString mountPoint();
0111 
0112         /**
0113          * Return number of bytes that should be kept free in iPod for database operations.
0114          * CollectionLocation should try hard not to occupy this safety margin.
0115          */
0116         float capacityMargin() const;
0117 
0118         /**
0119          * Return a list of file formats (compatible with Meta::Track::type()) current iPod
0120          * is able to play.
0121          */
0122         QStringList supportedFormats() const;
0123 
0124         /**
0125          * Return pointer to playlist provider associated with this iPod. May be null in
0126          * special cases (iPod not yet initialised etc.)
0127          */
0128         Playlists::UserPlaylistProvider *playlistProvider() const;
0129 
0130         Meta::TrackPtr trackForUidUrl( const QString &uidUrl );
0131 
0132     Q_SIGNALS:
0133         /**
0134          * Start a count-down that emits updated() signal after it expires.
0135          * Resets the timer to original timeout if already running. This is to ensure
0136          * that we Q_EMIT update() max. once per \<timeout\> for batch updates.
0137          *
0138          * Timers can only be started from "their" thread so use signals & slots for that.
0139          */
0140         void startUpdateTimer();
0141 
0142         /**
0143          * Start a count-down that initiates iTunes database writing after it expires.
0144          * Resets the timer to original timeout if already running. This is to ensure
0145          * that we don't write the database all the time for batch updates.
0146          *
0147          * Timers can only be started from "their" thread so use signals & slots for that.
0148          */
0149         void startWriteDatabaseTimer();
0150 
0151     public Q_SLOTS:
0152         /**
0153          * Destroy the collection, try to write back iTunes database (if dirty)
0154          */
0155         void slotDestroy();
0156 
0157         /**
0158          * Destroy the collection, write back iTunes db (if dirty) and try to eject the
0159          * iPod from system
0160          */
0161         void slotEject();
0162 
0163         /**
0164          * Shows the configuration dialog in a non-modal window. If m_itdb is null, shows
0165          * some info and a button to try to initialize iPod.
0166          */
0167         void slotShowConfigureDialog();
0168 
0169         /**
0170          * Shows the configuration dialog in a non-modal window. If m_itdb is null, shows
0171          * some info and a button to try to initialize iPod.
0172          */
0173         void slotShowConfigureDialogWithError( const QString &errorMessage );
0174 
0175     private Q_SLOTS:
0176         /**
0177          * Update m_lastUpdated timestamp and Q_EMIT updated()
0178          */
0179         void collectionUpdated();
0180 
0181         /**
0182          * Tries to initialize iPod, read the database, add tracks. (Re)shows the
0183          * configuration dialog with info about initialization.
0184          */
0185         void slotInitialize();
0186 
0187         /**
0188          * Sets iPod name to the name in configure dialog.
0189          */
0190         void slotApplyConfiguration();
0191 
0192         /**
0193          * Starts a timer that ensures we Q_EMIT updated() signal sometime in future.
0194          */
0195         void slotStartUpdateTimer();
0196 
0197         /**
0198          * Starts a timer that initiates iTunes database writing after 30 seconds.
0199          */
0200         void slotStartWriteDatabaseTimer();
0201 
0202         /**
0203          * Enqueues a job in a thread that writes iTunes database back to iPod. Should
0204          * only be called from m_writeDatabaseTimer's timeout() signal. (with exception
0205          * when IpodCollection is about to destroy itself)
0206          */
0207         void slotInitiateDatabaseWrite();
0208 
0209         /**
0210          * Tries to unmount underlying solid device. You must try to write database before
0211          * calling this. Emits remove() before returning.
0212          */
0213         void slotPerformTeardownAndRemove();
0214 
0215         /**
0216          * Do sanity checks and Q_EMIT remove() so that this collection is destroyed by
0217          * CollectionManager. No other method is allowed to Q_EMIT remove()!
0218          */
0219         void slotRemove();
0220 
0221     private:
0222         friend class IpodCopyTracksJob;
0223         friend class IpodDeleteTracksJob;
0224         friend class IpodParseTracksJob;
0225         friend class IpodWriteDatabaseJob;
0226         friend class IpodPlaylistProvider;
0227 
0228         static const QString s_uidUrlProtocol;
0229         static const QStringList s_audioFileTypes;
0230         static const QStringList s_videoFileTypes;
0231         static const QStringList s_audioVideoFileTypes;
0232 
0233         // method for IpodParseTracksJob and IpodCopyTracksJob:
0234         /**
0235          * Add an iPod track to the collection.
0236          *
0237          * This method adds it to the collection, master playlist (if not already there)
0238          * etc. The file must be already physically copied to iPod. (Re)Sets track's
0239          * collection to this collection. Takes ownership of the track (passes it to
0240          * AmarokSharedPointer)
0241          *
0242          * This method is thread-safe.
0243          *
0244          * @return pointer to newly added track if successful, null pointer otherwise
0245          */
0246         Meta::TrackPtr addTrack( IpodMeta::Track *track );
0247 
0248         // method for IpodDeleteTracksJob:
0249         /**
0250          * Removes a track from iPod collection. Does not delete the file physically,
0251          * caller must do it after calling this method.
0252          *
0253          * @param track a track from associated MemoryCollection to delete. Accepts also
0254          * underlying IpodMeta::Track, this is treated as if MemoryMeta::Track track
0255          * proxy it was passed.
0256          *
0257          * This method is thread-safe.
0258          */
0259         void removeTrack( const Meta::TrackPtr &track );
0260 
0261         // method for IpodWriteDatabaseJob and destructor:
0262         /**
0263          * Calls itdb_write() directly. Logs a message about success/failure in Amarok
0264          * interface.
0265          */
0266         bool writeDatabase();
0267 
0268         QDialog *m_configureDialog;
0269         Ui::IpodConfiguration m_configureDialogUi;
0270         QSharedPointer<Collections::MemoryCollection> m_mc;
0271         /**
0272          * pointer to libgpod iTunes database. If null, this collection is invalid
0273          * (not yet initialised). Can only be changed with m_itdbMutex hold.
0274          */
0275         Itdb_iTunesDB *m_itdb;
0276         QMutex m_itdbMutex;
0277         QTimer m_updateTimer;
0278         qint64 m_lastUpdated; /* msecs since epoch */
0279         QTimer m_writeDatabaseTimer;
0280         QTemporaryFile *m_preventUnmountTempFile;
0281         QString m_mountPoint;
0282         QString m_uuid;
0283         IphoneMountPoint *m_iphoneAutoMountpoint;
0284         QString m_prettyName;
0285         IpodPlaylistProvider *m_playlistProvider;
0286         QAction *m_configureAction;
0287         QAction *m_ejectAction;
0288         QAction *m_consolidateAction;
0289         QPointer<IpodParseTracksJob> m_parseTracksJob;
0290         QPointer<IpodWriteDatabaseJob> m_writeDatabaseJob;
0291 };
0292 
0293 #endif // IPODCOLLECTION_H