1
/******************************************************************************
2
 * Copyright (C) 2004 Christian Muehlhaeuser <chris@chris.de>                 *
3
 *           (C) 2005 Martin Aumueller <aumuell@reserv.at>                    *
4
 *           (C) 2005 Seb Ruiz <ruiz@kde.org>                                 *
5
 *           (C) 2006 T.R.Shashwath <trshash84@gmail.com>                     *
6
 *           (c) 2007 Jeff Mitchell <kde-dev@emailgoeshere.com>               *
7
 *                                                                            *
8
 * This program is free software; you can redistribute it and/or              *
9
 * modify it under the terms of the GNU General Public License as             *
10
 * published by the Free Software Foundation; either version 2 of             *
11
 * the License, or (at your option) any later version.                        *
12
 *                                                                            *
13
 * This program is distributed in the hope that it will be useful,            *
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
16
 * GNU General Public License for more details.                               *
17
 *                                                                            *
18
 * You should have received a copy of the GNU General Public License          *
19
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.      *
20
 ******************************************************************************/
21
22
#ifndef AMAROK_MEDIADEVICE_H
23
#define AMAROK_MEDIADEVICE_H
24
25
#include "amarok_export.h"
26
#include "Amarok.h"
27
#include "mediabrowser.h"
28
#include "Meta.h"
29
30
#include <QObject>
31
32
#include <kio/global.h>      //filesize_t
33
#include <KUrl>            //stack allocated
34
35
class MediaDevice;
36
class MediaItem;
37
class TransferDialog;
38
class MediaView;
39
class AmarokShellProcess;
40
41
/* at least the pure virtual functions have to be implemented by a media device,
42
   all items are stored in a hierarchy of MediaItems,
43
   when items are manipulated the MediaItems have to be updated accordingly */
44
45
class AMAROK_EXPORT MediaDevice : public QObject, public Amarok::Plugin
46
{
47
    Q_OBJECT
48
    friend class DeviceConfigureDialog;
49
    friend class MediaBrowser;
50
    friend class MediaDeviceConfig;
51
    friend class MediaView;
52
    friend class MediaQueue;
53
    friend class TransferDialog;
54
55
    public:
56
        enum Flags
57
        {
58
            None = 0,
59
            OnlyPlayed = 1,
60
            DeleteTrack = 2,
61
            Recursing = 4
62
        };
63
64
        MediaDevice();
65
        virtual void init( MediaBrowser* parent );
66
        virtual ~MediaDevice();
67
68
        MediaView *view();
69
70
        /**
71
         * @return a KAction that will be plugged into the media device browser toolbar
72
         */
73
        virtual KAction *customAction() { return 0; }
74
75
        virtual void rmbPressed( Q3ListViewItem *item, const QPoint &point, int ) { (void)item; (void) point; }
76
77
        /**
78
         * @return list of filetypes playable on this device
79
         *  (empty list is interpreted as all types are good)
80
         */
81
        virtual QStringList supportedFiletypes() { return QStringList(); }
82
83
        /**
84
         * @param track describes track that should be checked
85
         * @return true if the device is capable of playing the track referred to by track
86
         */
87
        virtual bool isPlayable( const Meta::TrackPtr track );
88
89
        /**
90
         * @param track describes track that should be checked
91
         * @return true if the track is in the preferred (first in list) format of the device
92
         */
93
        virtual bool isPreferredFormat( const Meta::TrackPtr track );
94
95
        /**
96
         * @return true if the device is connected
97
         */
98
        virtual bool       isConnected() = 0;
99
100
        /**
101
         * Adds particular tracks to a playlist
102
         * @param playlist parent playlist for tracks to be added to
103
         * @param after insert following this item
104
         * @param items tracks to add to playlist
105
         */
106
        virtual void       addToPlaylist(MediaItem *playlist, MediaItem *after, QList<MediaItem*> items) { Q_UNUSED(playlist); Q_UNUSED(after); Q_UNUSED(items); }
107
108
        /**
109
         * Create a new playlist
110
         * @param name playlist title
111
         * @param parent parent MediaItem of the new playlist
112
         * @param items tracks to add to the new playlist
113
         * @return the newly created playlist
114
         */
115
        virtual MediaItem *newPlaylist(const QString &name, MediaItem *parent, QList<MediaItem*> items) { Q_UNUSED(name); Q_UNUSED(parent); Q_UNUSED(items); return 0; }
116
117
        /**
118
         * Move items to a directory
119
         * @param directory new parent of dropped items
120
         * @param items tracks to add to the directory
121
         */
122
        virtual void      addToDirectory( MediaItem *directory, QList<MediaItem*> items ) { Q_UNUSED(directory); Q_UNUSED(items); }
123
124
        /**
125
         * Create a new directory
126
         * @param name directory title
127
         * @param parent parent MediaItem of the new directory
128
         * @param items tracks to add to the new directory
129
         * @return the newly created directory
130
         */
131
        virtual MediaItem *newDirectory( const QString &name, MediaItem *parent ) { Q_UNUSED(name); Q_UNUSED(parent); return 0; }
132
133
        /**
134
         * Notify device of changed tags
135
         * @param item item to be updated
136
         * @param changed meta containing new tags
137
         * @return the changed MediaItem
138
         */
139
        virtual MediaItem *tagsChanged( MediaItem *item, const Meta::TrackPtr changed ) { Q_UNUSED(item); Q_UNUSED(changed); return 0; }
140
141
        /**
142
         * Indicate whether the device has a custom transfer dialog
143
         * @return whether there is a custom dialog
144
         */
145
        virtual bool hasTransferDialog() { return false; }
146
147
        /**
148
         * Run the transfer dialog to be used when Transfer is clicked
149
         */
150
        virtual void runTransferDialog() {}
151
152
        /**
153
         * Get the transfer dialog, if any
154
         * @return the transfer dialog, if any, else NULL;
155
         */
156
        virtual TransferDialog *getTransferDialog() { return NULL; }
157
158
        /**
159
         * Can be used to explicitly indicate whether a device needs manual configuration
160
         * @return whether manual configuration is needed
161
         */
162
        virtual bool needsManualConfig() { return true; }
163
164
        virtual void addConfigElements( QWidget * /*parent*/ ) {}
165
        virtual void removeConfigElements( QWidget * /*parent*/ ) {}
166
        virtual void applyConfig() {}
167
        virtual void loadConfig();
168
169
        QString configString( const QString &name, const QString &defValue = QString() );
170
        void setConfigString( const QString &name, const QString &value );
171
        bool configBool( const QString &name, bool defValue=false );
172
        void setConfigBool( const QString &name, bool value );
173
174
        void         setRequireMount( const bool b ) { m_requireMount = b; }
175
        bool         hasMountPoint() { return m_hasMountPoint; }
176
        void         setDeviceType( const QString &type ) { m_type = type; }
177
        QString      type() { return m_type; }
178
        virtual bool autoConnect() { return false; }
179
        virtual bool asynchronousTransfer() { return false; }
180
        bool         isTransferring() { return m_transferring; }
181
        bool         isDeleting() { return m_deleting; }
182
        bool         isCanceled() { return m_canceled; }
183
        void         setCanceled( const bool b ) { m_canceled = b; }
184
185
        int          progress() const;
186
        void         setProgress( const int progress, const int total = -1 /* leave total unchanged by default */ );
187
        void         hideProgress();
188
189
190
        /**
191
         * @return a unique identifier that is constant across sessions
192
         */
193
        QString udi() const { return m_udi; }
194
195
        /**
196
         * @return the name for the device that should be presented to the user
197
         */
198
        QString name() const { return m_name; }
199
200
        /**
201
         * @return the filesystem type
202
         */
203
        QString fsType() const { return m_fsType; }
204
205
        /**
206
         * @return the device node
207
         */
208
        QString deviceNode() const { return m_deviceNode; }
209
210
        /*
211
         * @return the device mount point (or empty if non-applicable or unknown)
212
         */
213
        QString mountPoint() const { return m_mountPoint; }
214
215
        QString           getTransferDir() { return m_transferDir; }
216
217
        void              setSpacesToUnderscores( bool yesno ) { m_spacesToUnderscores = yesno;
218
            setConfigBool( "spacesToUnderscores", yesno); }
219
        bool              getSpacesToUnderscores() { return m_spacesToUnderscores; }
220
221
        void              setFirstSort( QString text ) { m_firstSort = text;
222
            setConfigString( "firstGrouping", text ); }
223
        void              setSecondSort( QString text ) { m_secondSort = text;
224
            setConfigString( "secondGrouping", text ); }
225
        void              setThirdSort( QString text ) { m_thirdSort = text;
226
            setConfigString( "thirdGrouping", text ); }
227
228
        virtual KUrl getProxyUrl( const KUrl& /*url*/) { return KUrl(); }
229
        virtual void customClicked() { return; }
230
231
        //BundleList bundlesToSync( const QString &playlistName, const QString &sql );
232
        Meta::TrackList tracksToSync( const QString &playlistName, const KUrl &url );
233
        void preparePlaylistForSync( const QString &playlistName, const Meta::TrackList &list );
234
        /**
235
        * @return true if track is on any playlist other than playlistToAvoid
236
        */
237
        bool isOnOtherPlaylist( const QString &playlistToAvoid, const Meta::TrackPtr track );
238
        bool isOnPlaylist( const MediaItem &playlist, const Meta::TrackPtr track );
239
        bool isInTrackList( const Meta::TrackList &list, const Meta::TrackPtr track );
240
        bool trackMatch( Meta::TrackPtr track1, Meta::TrackPtr track2 );
241
242
    public slots:
243
        void abortTransfer();
244
        void transferFiles();
245
        virtual void renameItem( Q3ListViewItem *item ) {(void)item; }
246
        virtual void expandItem( Q3ListViewItem *item ) {(void)item; }
247
        bool connectDevice( bool silent=false );
248
        bool disconnectDevice( bool postdisconnecthook=true );
249
        void scheduleDisconnect() { m_scheduledDisconnect = true; }
250
251
    protected slots:
252
        void fileTransferred( KIO::Job *job );
253
        void fileTransferFinished();
254
255
    private:
256
        int  sysCall(const QString & command);
257
        int  runPreConnectCommand();
258
        int  runPostDisconnectCommand();
259
        QString replaceVariables( const QString &cmd ); // replace %m with mount point and %d with device node
260
261
        void setUid( const QString &udi ) { m_udi = udi; }
262
263
        /**
264
         * Find a particular track
265
         * @param track The meta::track of the requested media item
266
         * @return The MediaItem of the item if found, otherwise NULL
267
         * @note This may not be worth implementing for non database driven devices, as it could be slow
268
         */
269
        virtual MediaItem *trackExists( Meta::TrackPtr track ) { Q_UNUSED(track); return 0; }
270
271
    protected:
272
        /**
273
         * Get the capacity and freespace available on the device, in bytes
274
         * @return true if successful
275
         */
276
        virtual bool getCapacity( KIO::filesize_t *total, KIO::filesize_t *available ) { Q_UNUSED(total); Q_UNUSED(available); return false; }
277
278
        /**
279
         * Lock device for exclusive access if possible
280
         */
281
        virtual bool lockDevice( bool tryOnly = false ) = 0;
282
283
        /**
284
         * Unlock device
285
         */
286
        virtual void unlockDevice() = 0;
287
288
        /**
289
         * Connect to device, and populate m_view with MediaItems
290
         * @return true if successful
291
         */
292
        virtual bool openDevice( bool silent=false ) = 0;
293
294
        /**
295
         * Wrap up any loose ends and close the device
296
         * @return true if successful
297
         */
298
        virtual bool closeDevice() = 0;
299
300
        /**
301
         * Write any pending changes to the device, such as database changes
302
         */
303
        virtual void synchronizeDevice() = 0;
304
305
        /**
306
         * Copy a track to the device
307
         * @param track The Meta::TrackPtr of the item to transfer. Will move the item specified by track->url()
308
         * @return If successful, the created MediaItem in the media device view, else 0
309
         */
310
        virtual MediaItem *copyTrackToDevice(const Meta::TrackPtr track) = 0;
311
312
        /**
313
         * Copy track from device to computer
314
         * @param item The MediaItem of the track to transfer.
315
         * @param url The URL to transfer the track to.
316
         * @return The MediaItem transfered.
317
         */
318
        virtual void copyTrackFromDevice(MediaItem *item);
319
320
        /**
321
         * Recursively remove MediaItem from the tracklist and the device
322
         * @param item MediaItem to remove
323
         * @param onlyPlayed True if item should be deleted only if it has been played
324
         * @return -1 on failure, number of files deleted otherwise
325
         */
326
        virtual int deleteItemFromDevice( MediaItem *item, int flags=DeleteTrack ) = 0;
327
328
        /**
329
         * Abort the currently active track transfer
330
         */
331
        virtual void cancelTransfer() { /* often checking m_cancel is enough */ }
332
333
        virtual void updateRootItems();
334
335
        virtual bool isSpecialItem( MediaItem *item );
336
337
        int deleteFromDevice( MediaItem *item=0, int flags=DeleteTrack );
338
339
        void purgeEmptyItems( MediaItem *root=0 );
340
        void syncStatsFromDevice( MediaItem *root=0 );
341
        void syncStatsToDevice( MediaItem *root=0 );
342
343
        bool kioCopyTrack( const KUrl &src, const KUrl &dst );
344
345
        QString     m_name;
346
347
        bool        m_hasMountPoint;
348
349
        QString     m_preconnectcmd;
350
        QString     m_postdisconnectcmd;
351
        bool        m_autoDeletePodcasts;
352
        bool        m_syncStats;
353
354
        bool        m_transcode;
355
        bool        m_transcodeAlways;
356
        bool        m_transcodeRemove;
357
358
        AmarokShellProcess *sysProc;
359
        MediaBrowser    *m_parent;
360
        MediaView       *m_view;
361
        QString          m_transferDir;
362
        QString          m_firstSort;
363
        QString          m_secondSort;
364
        QString          m_thirdSort;
365
        QString          m_udi;
366
        QString          m_deviceNode;
367
        QString          m_mountPoint;
368
        QString          m_fsType;
369
        bool             m_wait;
370
        bool             m_waitForDeletion;
371
        bool             m_copyFailed;
372
        bool             m_requireMount;
373
        bool             m_canceled;
374
        bool             m_transferring;
375
        bool             m_deleting;
376
        bool             m_deferredDisconnect;
377
        bool             m_scheduledDisconnect;
378
        bool             m_runDisconnectHook;
379
        bool             m_spacesToUnderscores;
380
        bool             m_transfer;
381
        bool             m_configure;
382
        bool             m_customButton;
383
384
        QString          m_type;
385
386
        // root listview items
387
        MediaItem *m_playlistItem;
388
        MediaItem *m_podcastItem;
389
        // items not on the master playlist and not on the podcast playlist are not visible on the ipod
390
        MediaItem *m_invisibleItem;
391
        // items in the database for which the file is missing
392
        MediaItem *m_staleItem;
393
        // files without database entry
394
        MediaItem *m_orphanedItem;
395
396
        // stow away all items below m_rootItems when device is not current
397
        QList<Q3ListViewItem*> m_rootItems;
398
};
399
400
401
#endif /* AMAROK_MEDIADEVICE_H */