File indexing completed on 2025-01-19 04:24:32

0001 /****************************************************************************************
0002  * Copyright (c) 2006 Andy Kelk <andy@mopoke.co.uk>                                     *
0003  * Copyright (c) 2008 Alejandro Wainzinger <aikawarazuni@gmail.com>                     *
0004  * Copyright (c) 2009 Mark Kretschmann <kretschmann@kde.org>                            *
0005  *                                                                                      *
0006  * This program is free software; you can redistribute it and/or modify it under        *
0007  * the terms of the GNU General Public License as published by the Free Software        *
0008  * Foundation; either version 2 of the License, or (at your option) version 3 or        *
0009  * any later version accepted by the membership of KDE e.V. (or its successor approved  *
0010  * by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of  *
0011  * version 3 of the license.                                                            *
0012  *                                                                                      *
0013  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0014  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0015  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0016  *                                                                                      *
0017  * You should have received a copy of the GNU General Public License along with         *
0018  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0019  ****************************************************************************************/
0020 
0021 #ifndef MTPHANDLER_H
0022 #define MTPHANDLER_H
0023 
0024 #include <libmtp.h>
0025 
0026 #include "MtpPlaylistCapability.h"
0027 #include "MtpReadCapability.h"
0028 #include "MtpWriteCapability.h"
0029 
0030 #include "MediaDeviceMeta.h"
0031 #include "MediaDeviceHandler.h"
0032 
0033 #include <KIO/Job>
0034 #include <ThreadWeaver/Job>
0035 #include <ThreadWeaver/Queue>
0036 
0037 #include <QObject>
0038 #include <QMap>
0039 #include <QMultiMap>
0040 #include <QMutex>
0041 #include <QSet>
0042 #include <QTemporaryDir>
0043 #include <QTemporaryFile>
0044 
0045 
0046 class QString;
0047 class QMutex;
0048 class QStringList;
0049 
0050 namespace Collections {
0051     class MtpCollection;
0052 }
0053 
0054 namespace Meta
0055 {
0056 typedef QMultiMap<QString, Meta::TrackPtr> TitleMap;
0057 class WorkerThread;
0058 
0059 /* The libmtp backend for all Mtp calls */
0060 class MtpHandler : public MediaDeviceHandler
0061 {
0062         Q_OBJECT
0063 
0064     public:
0065         explicit MtpHandler( Collections::MtpCollection *mc );
0066         ~MtpHandler() override;
0067 
0068         friend class WorkerThread;
0069 
0070         void init() override; // collection
0071         bool isWritable() const override;
0072 
0073         void getCopyableUrls( const Meta::TrackList &tracks ) override;
0074 
0075         QString prettyName() const override;
0076 
0077         void prepareToPlay( Meta::MediaDeviceTrackPtr &track ) override;
0078 
0079         /// Capability-related methods
0080 
0081         bool hasCapabilityInterface( Handler::Capability::Type type ) const override;
0082         Handler::Capability* createCapabilityInterface( Handler::Capability::Type type ) override;
0083 
0084         friend class Handler::MtpPlaylistCapability;
0085         friend class Handler::MtpReadCapability;
0086         friend class Handler::MtpWriteCapability;
0087 
0088     protected:
0089         /* Parsing of Tracks on Device */
0090         virtual void prepareToParseTracks();
0091         virtual bool isEndOfParseTracksList();
0092         virtual void prepareToParseNextTrack();
0093         virtual void nextTrackToParse();
0094 
0095         virtual void setAssociateTrack( const Meta::MediaDeviceTrackPtr track );
0096 
0097         virtual void prepareToParsePlaylists();
0098         virtual bool isEndOfParsePlaylistsList();
0099         virtual void prepareToParseNextPlaylist();
0100         virtual void nextPlaylistToParse();
0101 
0102         virtual bool shouldNotParseNextPlaylist();
0103 
0104         virtual void prepareToParsePlaylistTracks();
0105         virtual bool isEndOfParsePlaylist();
0106         virtual void prepareToParseNextPlaylistTrack();
0107         virtual void nextPlaylistTrackToParse();
0108 
0109         virtual QStringList supportedFormats();
0110 
0111         virtual void findPathToCopy( const Meta::TrackPtr &srcTrack, const Meta::MediaDeviceTrackPtr &destTrack );
0112         virtual bool libCopyTrack( const Meta::TrackPtr &srcTrack, Meta::MediaDeviceTrackPtr &destTrack );
0113         virtual bool libDeleteTrackFile( const Meta::MediaDeviceTrackPtr &track );
0114         virtual void libCreateTrack( const Meta::MediaDeviceTrackPtr &track );
0115         virtual void libDeleteTrack( const Meta::MediaDeviceTrackPtr &track );
0116 
0117         virtual Meta::MediaDeviceTrackPtr libGetTrackPtrForTrackStruct();
0118 
0119         virtual QString libGetPlaylistName();
0120         virtual void setAssociatePlaylist( const Playlists::MediaDevicePlaylistPtr &playlist );
0121         virtual void libSavePlaylist( const Playlists::MediaDevicePlaylistPtr &playlist, const QString& name );
0122         virtual void deletePlaylist( const Playlists::MediaDevicePlaylistPtr &playlist );
0123         virtual void renamePlaylist( const Playlists::MediaDevicePlaylistPtr &playlist );
0124 
0125         virtual void addTrackInDB( const Meta::MediaDeviceTrackPtr &track ) { Q_UNUSED( track ) }
0126         virtual void removeTrackFromDB( const Meta::MediaDeviceTrackPtr &track ) { Q_UNUSED( track ) }
0127         virtual void setDatabaseChanged();
0128 
0129         virtual QString libGetTitle( const Meta::MediaDeviceTrackPtr &track );
0130         virtual QString libGetAlbum( const Meta::MediaDeviceTrackPtr &track );
0131         virtual QString libGetArtist( const Meta::MediaDeviceTrackPtr &track );
0132         virtual QString libGetAlbumArtist( const Meta::MediaDeviceTrackPtr &track );
0133         virtual QString libGetComposer( const Meta::MediaDeviceTrackPtr &track );
0134         virtual QString libGetGenre( const Meta::MediaDeviceTrackPtr &track );
0135         virtual int     libGetYear( const Meta::MediaDeviceTrackPtr &track );
0136         virtual qint64  libGetLength( const Meta::MediaDeviceTrackPtr &track );
0137         virtual int     libGetTrackNumber( const Meta::MediaDeviceTrackPtr &track );
0138         virtual QString libGetComment( const Meta::MediaDeviceTrackPtr &track );
0139         virtual int     libGetDiscNumber( const Meta::MediaDeviceTrackPtr &track );
0140         virtual int     libGetBitrate( const Meta::MediaDeviceTrackPtr &track );
0141         virtual int     libGetSamplerate( const Meta::MediaDeviceTrackPtr &track );
0142         virtual qreal   libGetBpm( const Meta::MediaDeviceTrackPtr &track );
0143         virtual int     libGetFileSize( const Meta::MediaDeviceTrackPtr &track );
0144         virtual int     libGetPlayCount( const Meta::MediaDeviceTrackPtr &track );
0145         virtual QDateTime libGetLastPlayed( const Meta::MediaDeviceTrackPtr &track );
0146         virtual int     libGetRating( const Meta::MediaDeviceTrackPtr &track ) ;
0147         virtual QString libGetType( const Meta::MediaDeviceTrackPtr &track );
0148         virtual QUrl    libGetPlayableUrl( const Meta::MediaDeviceTrackPtr &track );
0149 
0150         virtual float usedCapacity() const;
0151         virtual float totalCapacity() const;
0152 
0153         virtual void libSetTitle( Meta::MediaDeviceTrackPtr &track, const QString& title );
0154         virtual void libSetAlbum( Meta::MediaDeviceTrackPtr &track, const QString& album );
0155         virtual void libSetArtist( Meta::MediaDeviceTrackPtr &track, const QString& artist );
0156         virtual void libSetAlbumArtist( Meta::MediaDeviceTrackPtr &track, const QString& albumArtist );
0157         virtual void libSetComposer( Meta::MediaDeviceTrackPtr &track, const QString& composer );
0158         virtual void libSetGenre( Meta::MediaDeviceTrackPtr &track, const QString& genre );
0159         virtual void libSetYear( Meta::MediaDeviceTrackPtr &track, const QString& year );
0160         virtual void libSetLength( Meta::MediaDeviceTrackPtr &track, int length );
0161         virtual void libSetTrackNumber( Meta::MediaDeviceTrackPtr &track, int tracknum );
0162         virtual void libSetComment( Meta::MediaDeviceTrackPtr &track, const QString& comment );
0163         virtual void libSetDiscNumber( Meta::MediaDeviceTrackPtr &track, int discnum );
0164         virtual void libSetBitrate( Meta::MediaDeviceTrackPtr &track, int bitrate );
0165         virtual void libSetSamplerate( Meta::MediaDeviceTrackPtr &track, int samplerate );
0166         virtual void libSetBpm( Meta::MediaDeviceTrackPtr &track, qreal bpm );
0167         virtual void libSetFileSize( Meta::MediaDeviceTrackPtr &track, int filesize );
0168         virtual void libSetPlayCount( Meta::MediaDeviceTrackPtr &track, int playcount );
0169         virtual void libSetLastPlayed( Meta::MediaDeviceTrackPtr &track, const QDateTime &lastplayed );
0170         virtual void libSetRating( Meta::MediaDeviceTrackPtr &track, int rating ) ;
0171         virtual void libSetType( Meta::MediaDeviceTrackPtr &track, const QString& type );
0172         virtual void libSetPlayableUrl( Meta::MediaDeviceTrackPtr &destTrack, const Meta::TrackPtr &srcTrack );
0173 
0174         virtual void prepareToCopy() {}
0175         virtual void prepareToDelete() {}
0176 
0177         /// libmtp-specific
0178     private Q_SLOTS:
0179         void slotDeviceMatchSucceeded( ThreadWeaver::JobPointer job );
0180         void slotDeviceMatchFailed( ThreadWeaver::JobPointer job );
0181 
0182     private:
0183         bool iterateRawDevices( int numrawdevices, LIBMTP_raw_device_t* rawdevices );
0184         void getDeviceInfo();
0185 
0186         void terminate();
0187 
0188         int getTrackToFile( const uint32_t id, const QString & filename );
0189 
0190         // Some internal stuff that must be public due to libmtp being in C
0191         static int progressCallback( uint64_t const sent, uint64_t const total, void const * const data );
0192 
0193         // file-copying related functions
0194         uint32_t checkFolderStructure( const Meta::TrackPtr track, bool create );
0195         uint32_t getDefaultParentId( void );
0196         uint32_t folderNameToID( char *name, LIBMTP_folder_t *folderlist );
0197         uint32_t subfolderNameToID( const char *name, LIBMTP_folder_t *folderlist, uint32_t parent_id );
0198         uint32_t createFolder( const char *name, uint32_t parent_id );
0199         void updateFolders( void );
0200 
0201         QString setTempFile( Meta::MediaDeviceTrackPtr &track, const QString &format );
0202 
0203         virtual void updateTrack( Meta::MediaDeviceTrackPtr &track );
0204 
0205         // mtp database
0206         LIBMTP_mtpdevice_t      *m_device;
0207 
0208         float                    m_capacity;
0209 
0210         QMap<int, QString>       mtpFileTypes;
0211 
0212         uint32_t                m_default_parent_folder;
0213         LIBMTP_folder_t        *m_folders;
0214         QString                 m_folderStructure;
0215         QString                 m_format;
0216         QString                 m_name;
0217         QStringList             m_supportedFiles;
0218 
0219         QMutex                  m_critical_mutex;
0220 
0221         // KIO-related Vars (to be moved elsewhere eventually)
0222         bool m_isCanceled;
0223         bool m_wait;
0224         bool m_dbChanged;
0225 
0226         LIBMTP_track_t* m_currentTrackList;
0227         LIBMTP_track_t* m_currentTrack;
0228         LIBMTP_playlist_t* m_currentPlaylistList;
0229         LIBMTP_playlist_t* m_currentPlaylist;
0230 
0231         QHash<Playlists::MediaDevicePlaylistPtr, LIBMTP_playlist_t*> m_mtpPlaylisthash;
0232 
0233         uint32_t m_trackcounter;
0234 
0235         // Hash that associates an LIBMTP_track_t* to every Track*
0236 
0237         QHash<Meta::MediaDeviceTrackPtr, LIBMTP_track_t*> m_mtpTrackHash;
0238 
0239         // Keeps track of which tracks have been copied/cached for playing
0240 
0241         QHash<Meta::MediaDeviceTrackPtr, QTemporaryFile*> m_cachedTracks;
0242 
0243         // Maps id's to tracks
0244 
0245         QHash<uint32_t, LIBMTP_track_t*> m_idTrackHash;
0246 
0247         // parentid calculated for new track copied to device
0248 
0249         uint32_t m_copyParentId;
0250 
0251         // Used as temporary location for copying files from mtp
0252 
0253         QTemporaryDir *m_tempDir;
0254 };
0255 
0256 class WorkerThread : public QObject, public ThreadWeaver::Job
0257 {
0258         Q_OBJECT
0259 
0260     public:
0261         WorkerThread( int numrawdevices, LIBMTP_raw_device_t* rawdevices, MtpHandler* handler );
0262         ~WorkerThread() override;
0263 
0264         bool success() const override;
0265 
0266     protected:
0267         void run(ThreadWeaver::JobPointer self = QSharedPointer<ThreadWeaver::Job>(), ThreadWeaver::Thread *thread = nullptr) override;
0268         void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override;
0269         void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override;
0270 
0271     Q_SIGNALS:
0272         /** This signal is emitted when this job is being processed by a thread. */
0273         void started(ThreadWeaver::JobPointer);
0274         /** This signal is emitted when the job has been finished (no matter if it succeeded or not). */
0275         void done(ThreadWeaver::JobPointer);
0276         /** This job has failed.
0277          * This signal is emitted when success() returns false after the job is executed. */
0278         void failed(ThreadWeaver::JobPointer);
0279 
0280     private:
0281         bool m_success;
0282         int m_numrawdevices;
0283         LIBMTP_raw_device_t* m_rawdevices;
0284         MtpHandler *m_handler;
0285 };
0286 
0287 }
0288 #endif