Divest ourselves of kded/mediamanager. Use Solid to discover PMP devices. I highly...
[amarok.git] / src / mediabrowser.h
blobdfadb11dc94a53b0291b5f334158f6579d21524c
1 // (c) 2004 Christian Muehlhaeuser <chris@chris.de>
2 // (c) 2005 Martin Aumueller <aumuell@reserv.at>
3 // (c) 2005 Seb Ruiz <me@sebruiz.net>
4 // (c) 2006 T.R.Shashwath <trshash84@gmail.com>
5 // See COPYING file for licensing information
7 #ifndef AMAROK_MEDIABROWSER_H
8 #define AMAROK_MEDIABROWSER_H
10 #include "amarok_export.h"
11 #include "amarok.h"
12 #include "browserToolBar.h"
13 #include "medium.h"
14 #include "metabundle.h"
15 #include "pluginmanager.h"
16 #include "plugin/plugin.h" //baseclass
17 #include "scrobbler.h" //SubmitItem
19 #include <k3listview.h> //baseclass
20 #include <KHBox>
21 #include <kio/global.h> //filesize_t
22 #include <KUrl> //stack allocated
23 #include <KVBox> //baseclass
25 #include <Q3PtrList>
26 #include <QDateTime>
27 #include <QLabel>
28 #include <QMutex>
29 #include <QPixmap>
30 #include <QWidget>
33 class MediaBrowser;
34 class MediaDevice;
35 class MediaView;
36 class SpaceLabel;
37 class TransferDialog;
38 class SearchWidget;
40 class KAction;
41 class KComboBox;
42 class KPushButton;
43 class K3ShellProcess;
45 class QDropEvent;
46 class QKeyEvent;
47 class QPaintEvent;
48 class Q3DragObject;
49 class QLabel;
50 class QProgressBar;
52 class AMAROK_EXPORT MediaItem : public K3ListViewItem
54 public:
55 MediaItem( Q3ListView* parent );
56 MediaItem( Q3ListViewItem* parent );
57 MediaItem( Q3ListView* parent, Q3ListViewItem* after );
58 MediaItem( Q3ListViewItem* parent, Q3ListViewItem* after );
59 void init();
60 virtual ~MediaItem();
62 MediaItem *lastChild() const;
64 virtual KUrl url() const;
65 const MetaBundle *bundle() const;
66 void setBundle( MetaBundle *bundle );
68 enum Type { UNKNOWN, ARTIST, ALBUM, TRACK, PODCASTSROOT, PODCASTCHANNEL,
69 PODCASTITEM, PLAYLISTSROOT, PLAYLIST, PLAYLISTITEM, INVISIBLEROOT,
70 INVISIBLE, STALEROOT, STALE, ORPHANEDROOT, ORPHANED, DIRECTORY };
72 enum Flags { Failed=1, BeginTransfer=2, StopTransfer=4, Transferring=8, SmartPlaylist=16 };
74 void setType( Type type );
75 void setFailed( bool failed=true );
76 Type type() const { return m_type; }
77 MediaItem *findItem(const QString &key, const MediaItem *after=0) const;
78 const QString &data() const { return m_data; }
79 void setData( const QString &data ) { m_data = data; }
81 virtual bool isLeafItem() const; // A leaf node of the tree
82 virtual bool isFileBacked() const; // Should the file be deleted of the device when removed
83 virtual QDateTime playTime() const { return QDateTime(); }
84 virtual int played() const { return 0; }
85 virtual int recentlyPlayed() const { return 0; } // no of times played on device since last sync
86 virtual void setPlayCount( int ) {}
87 virtual int rating() const { return 0; } // rating on device, normalized to 100
88 virtual void setRating( int /*rating*/ ) {}
89 virtual bool ratingChanged() const { return false; }
90 virtual void setLastPlayed( uint ) {}
91 virtual void syncStatsFromPath( const QString &path );
92 virtual long size() const;
93 virtual MediaDevice *device() const { return m_device; }
94 virtual bool listened() const { return m_listened; }
95 virtual void setListened( bool listened=true ) { m_listened = listened; }
97 int compare( Q3ListViewItem *i, int col, bool ascending ) const;
98 int flags() const { return m_flags; }
99 void createToolTip();
101 void paintCell( QPainter *p, const QColorGroup &cg, int column, int width, int align );
103 //attributes:
104 int m_order;
105 Type m_type;
106 QString m_playlistName;
107 QString m_data;
108 MediaDevice *m_device;
109 int m_flags;
110 bool m_listened;
112 static QPixmap *s_pixUnknown;
113 static QPixmap *s_pixRootItem;
114 static QPixmap *s_pixFile;
115 static QPixmap *s_pixArtist;
116 static QPixmap *s_pixAlbum;
117 static QPixmap *s_pixPlaylist;
118 static QPixmap *s_pixPodcast;
119 static QPixmap *s_pixTrack;
120 static QPixmap *s_pixInvisible;
121 static QPixmap *s_pixStale;
122 static QPixmap *s_pixOrphaned;
123 static QPixmap *s_pixDirectory;
124 static QPixmap *s_pixTransferFailed;
125 static QPixmap *s_pixTransferBegin;
126 static QPixmap *s_pixTransferEnd;
128 private:
129 mutable MetaBundle *m_bundle;
132 class MediaQueue : public K3ListView
134 Q_OBJECT
136 public:
137 MediaQueue(MediaBrowser *parent);
138 MediaItem *findPath( QString path );
140 KIO::filesize_t totalSize() const; // total size of items to transfer in KB
141 void computeSize() const; // compute total size of items to transfer in KB
142 void addItemToSize( const MediaItem *item ) const;
143 void subtractItemFromSize( const MediaItem *item, bool unconditonally=false ) const;
145 void removeSelected();
146 void clearItems();
148 void load( const QString &path );
149 void save( const QString &path );
150 void syncPlaylist( const QString &playlistName, const QString &sql, bool loading=false );
151 void syncPlaylist( const QString &playlistName, const KUrl &url, bool loading=false );
152 void addUrl( const KUrl& url, MetaBundle *bundle=NULL, const QString &playlistName=QString() );
153 void addUrl( const KUrl& url, MediaItem *item );
154 void addUrls( const KUrl::List urls, const QString &playlistName=QString() );
156 void URLsAdded(); // call after finishing adding single urls
158 void dropProxyEvent( QDropEvent *e );
159 // Reimplemented from K3ListView
160 bool acceptDrag( QDropEvent *e ) const;
161 Q3DragObject *dragObject();
163 public slots:
164 void itemCountChanged();
166 private slots:
167 void selectAll() {Q3ListView::selectAll(true); }
168 void slotShowContextMenu( Q3ListViewItem* item, const QPoint& point, int );
169 void slotDropped (QDropEvent* e, Q3ListViewItem* parent, Q3ListViewItem* after);
171 private:
172 void keyPressEvent( QKeyEvent *e );
173 MediaBrowser *m_parent;
174 mutable KIO::filesize_t m_totalSize;
178 class MediaBrowser : public QWidget
180 Q_OBJECT
181 friend class DeviceConfigureDialog;
182 friend class MediaDevice;
183 friend class MediaView;
184 friend class MediaQueue;
185 friend class MediumPluginChooser;
186 friend class MediaItem;
188 public:
189 static bool isAvailable();
190 AMAROK_EXPORT static MediaBrowser *instance() { return s_instance; }
191 AMAROK_EXPORT static MediaQueue *queue() { return s_instance ? s_instance->m_queue : 0; }
193 MediaBrowser( const char *name );
194 virtual ~MediaBrowser();
195 bool blockQuit() const;
196 MediaDevice *currentDevice() const { return m_currentDevice; }
197 MediaDevice *deviceFromId( const QString &id ) const;
198 QStringList deviceNames() const;
199 bool deviceSwitch( const QString &name );
201 QString getInternalPluginName ( const QString string ) { return m_pluginName[string]; }
202 QString getDisplayPluginName ( const QString string ) { return m_pluginAmarokName[string]; }
203 const KService::List &getPlugins() { return m_plugins; }
204 void transcodingFinished( const QString &src, const QString &dst );
205 bool isTranscoding() const { return m_waitForTranscode; }
206 void updateStats();
207 void updateButtons();
208 void updateDevices();
209 // return bundle for url if it is known to MediaBrowser
210 bool getBundle( const KUrl &url, MetaBundle *bundle ) const;
211 bool isQuitting() const { return m_quitting; }
213 KUrl getProxyUrl( const KUrl& daapUrl ) const;
214 KToolBar* getToolBar() const { return m_toolbar; }
215 KAction *connectAction() const { return m_connectAction; }
216 KAction *disconnectAction() const { return m_disconnectAction; }
217 KAction *transferAction() const { return m_transferAction; }
218 KAction *configAction() const { return m_configAction; }
219 KAction *customAction() const { return m_customAction; }
221 signals:
222 void availabilityChanged( bool isAvailable );
224 protected slots:
225 void transferClicked();
227 private slots:
228 void slotSetFilterTimeout();
229 void slotSetFilter();
230 void slotSetFilter( const QString &filter );
231 void slotEditFilter();
232 void deviceAdded( const QString &udi );
233 void deviceRemoved( const QString &udi );
234 void activateDevice( const MediaDevice *device );
235 void activateDevice( int index, bool skipDummy = true );
236 void cancelClicked();
237 void connectClicked();
238 void disconnectClicked();
239 void customClicked();
240 bool config(); // false if canceled by user
241 KUrl transcode( const KUrl &src, const QString &filetype );
242 void tagsChanged( const MetaBundle &bundle );
243 void prepareToQuit();
245 private:
246 MediaDevice *loadDevicePlugin( const QString &udi );
247 void unloadDevicePlugin( MediaDevice *device );
249 QTimer *m_timer;
250 AMAROK_EXPORT static MediaBrowser *s_instance;
252 QList<MediaDevice *> m_devices;
253 MediaDevice * m_currentDevice;
255 QMap<QString, QString> m_pluginName;
256 QMap<QString, QString> m_pluginAmarokName;
257 void addDevice( MediaDevice *device );
258 void removeDevice( MediaDevice *device );
260 MediaQueue* m_queue;
261 bool m_waitForTranscode;
262 KUrl m_transcodedUrl;
263 QString m_transcodeSrc;
265 SpaceLabel* m_stats;
266 KHBox* m_progressBox;
267 QProgressBar* m_progress;
268 QWidget* m_views;
269 KPushButton* m_cancelButton;
270 //KPushButton* m_playlistButton;
271 KVBox* m_configBox;
272 KComboBox* m_configPluginCombo;
273 KComboBox* m_deviceCombo;
274 Browser::ToolBar*m_toolbar;
275 typedef QMap<QString, MediaItem*> ItemMap;
276 mutable QMutex m_itemMapMutex;
277 ItemMap m_itemMap;
278 KService::List m_plugins;
279 bool m_haveDevices;
280 bool m_quitting;
281 KAction *m_connectAction;
282 KAction *m_disconnectAction;
283 KAction *m_customAction;
284 KAction *m_configAction;
285 KAction *m_transferAction;
286 SearchWidget *m_searchWidget;
289 class MediaView : public K3ListView
291 Q_OBJECT
292 friend class MediaBrowser;
293 friend class MediaDevice;
295 public:
296 enum Flags
298 None = 0,
299 OnlySelected = 1,
300 OnlyPlayed = 2
303 MediaView( QWidget *parent, MediaDevice *device );
304 virtual ~MediaView();
305 AMAROK_EXPORT KUrl::List nodeBuildDragList( MediaItem* item, int flags=OnlySelected );
306 int getSelectedLeaves(MediaItem *parent, Q3PtrList<MediaItem> *list, int flags=OnlySelected );
307 AMAROK_EXPORT MediaItem *newDirectory( MediaItem* parent );
308 bool setFilter( const QString &filter, MediaItem *parent=NULL );
310 private slots:
311 void rmbPressed( Q3ListViewItem*, const QPoint&, int );
312 void renameItem( Q3ListViewItem *item );
313 void slotExpand( Q3ListViewItem* );
314 void selectAll() { Q3ListView::selectAll(true); }
315 void invokeItem( Q3ListViewItem*, const QPoint &, int column );
316 void invokeItem( Q3ListViewItem* );
318 private:
319 void keyPressEvent( QKeyEvent *e );
320 // Reimplemented from K3ListView
321 void contentsDropEvent( QDropEvent *e );
322 void viewportPaintEvent( QPaintEvent* );
323 bool acceptDrag( QDropEvent *e ) const;
324 Q3DragObject *dragObject();
326 QWidget *m_parent;
327 MediaDevice *m_device;
331 /* at least the pure virtual functions have to be implemented by a media device,
332 all items are stored in a hierarchy of MediaItems,
333 when items are manipulated the MediaItems have to be updated accordingly */
335 class AMAROK_EXPORT MediaDevice : public QObject, public Amarok::Plugin
337 Q_OBJECT
338 friend class DeviceConfigureDialog;
339 friend class TransferDialog;
340 friend class MediaBrowser;
341 friend class MediaView;
342 friend class MediaQueue;
344 public:
345 enum Flags
347 None = 0,
348 OnlyPlayed = 1,
349 DeleteTrack = 2,
350 Recursing = 4
353 MediaDevice();
354 virtual void init( MediaBrowser* parent );
355 virtual ~MediaDevice();
357 MediaView *view();
360 * @return a KAction that will be plugged into the media device browser toolbar
362 virtual KAction *customAction() { return 0; }
364 virtual void rmbPressed( Q3ListViewItem *item, const QPoint &point, int ) { (void)item; (void) point; }
367 * @return list of filetypes playable on this device
368 * (empty list is interpreted as all types are good)
370 virtual QStringList supportedFiletypes() { return QStringList(); }
373 * @param bundle describes track that should be checked
374 * @return true if the device is capable of playing the track referred to by bundle
376 virtual bool isPlayable( const MetaBundle &bundle );
379 * @param bundle describes track that should be checked
380 * @return true if the track is in the preferred (first in list) format of the device
382 virtual bool isPreferredFormat( const MetaBundle &bundle );
385 * @return true if the device is connected
387 virtual bool isConnected() = 0;
390 * Adds particular tracks to a playlist
391 * @param playlist parent playlist for tracks to be added to
392 * @param after insert following this item
393 * @param items tracks to add to playlist
395 virtual void addToPlaylist(MediaItem *playlist, MediaItem *after, Q3PtrList<MediaItem> items) { Q_UNUSED(playlist); Q_UNUSED(after); Q_UNUSED(items); }
398 * Create a new playlist
399 * @param name playlist title
400 * @param parent parent MediaItem of the new playlist
401 * @param items tracks to add to the new playlist
402 * @return the newly created playlist
404 virtual MediaItem *newPlaylist(const QString &name, MediaItem *parent, Q3PtrList<MediaItem> items) { Q_UNUSED(name); Q_UNUSED(parent); Q_UNUSED(items); return 0; }
407 * Move items to a directory
408 * @param directory new parent of dropped items
409 * @param items tracks to add to the directory
411 virtual void addToDirectory( MediaItem *directory, Q3PtrList<MediaItem> items ) { Q_UNUSED(directory); Q_UNUSED(items); }
414 * Create a new directory
415 * @param name directory title
416 * @param parent parent MediaItem of the new directory
417 * @param items tracks to add to the new directory
418 * @return the newly created directory
420 virtual MediaItem *newDirectory( const QString &name, MediaItem *parent ) { Q_UNUSED(name); Q_UNUSED(parent); return 0; }
423 * Notify device of changed tags
424 * @param item item to be updated
425 * @param changed bundle containing new tags
426 * @return the changed MediaItem
428 virtual MediaItem *tagsChanged( MediaItem *item, const MetaBundle &changed ) { Q_UNUSED(item); Q_UNUSED(changed); return 0; }
431 * Indicate whether the device has a custom transfer dialog
432 * @return whether there is a custom dialog
434 virtual bool hasTransferDialog() { return false; }
437 * Run the transfer dialog to be used when Transfer is clicked
439 virtual void runTransferDialog() {}
442 * Get the transfer dialog, if any
443 * @return the transfer dialog, if any, else NULL;
445 virtual TransferDialog *getTransferDialog() { return NULL; }
448 * Can be used to explicitly indicate whether a device needs manual configuration
449 * @return whether manual configuration is needed
451 virtual bool needsManualConfig() { return true; }
453 virtual void addConfigElements( QWidget * /*parent*/ ) {}
454 virtual void removeConfigElements( QWidget * /*parent*/ ) {}
455 virtual void applyConfig() {}
456 virtual void loadConfig();
458 QString configString( const QString &name, const QString &defValue = QString() );
459 void setConfigString( const QString &name, const QString &value );
460 bool configBool( const QString &name, bool defValue=false );
461 void setConfigBool( const QString &name, bool value );
463 void setRequireMount( const bool b ) { m_requireMount = b; }
464 bool hasMountPoint() { return m_hasMountPoint; }
465 void setDeviceType( const QString &type ) { m_type = type; }
466 QString deviceType() { return m_type; }
467 virtual bool autoConnect() { return false; }
468 virtual bool asynchronousTransfer() { return false; }
469 bool isTransferring() { return m_transferring; }
470 bool isDeleting() { return m_deleting; }
471 bool isCanceled() { return m_canceled; }
472 void setCanceled( const bool b ) { m_canceled = b; }
474 int progress() const;
475 void setProgress( const int progress, const int total = -1 /* leave total unchanged by default */ );
476 void hideProgress();
480 * @return a unique identifier that is constant across sessions
482 QString uniqueId() const { return m_uid; }
485 * @return the name for the device that should be presented to the user
487 QString name() const { return m_name; }
490 * @return the device node
492 QString deviceNode() const { return m_medium.deviceNode(); }
495 * @return the device mount point (or empty if non-applicable or unknown)
497 QString mountPoint() const { return m_medium.mountPoint(); }
499 QString getTransferDir() { return m_transferDir; }
500 Medium &getMedium() { return m_medium; }
502 void setSpacesToUnderscores( bool yesno ) { m_spacesToUnderscores = yesno;
503 setConfigBool( "spacesToUnderscores", yesno); }
504 bool getSpacesToUnderscores() { return m_spacesToUnderscores; }
506 void setFirstSort( QString text ) { m_firstSort = text;
507 setConfigString( "firstGrouping", text ); }
508 void setSecondSort( QString text ) { m_secondSort = text;
509 setConfigString( "secondGrouping", text ); }
510 void setThirdSort( QString text ) { m_thirdSort = text;
511 setConfigString( "thirdGrouping", text ); }
513 virtual KUrl getProxyUrl( const KUrl& /*url*/) { return KUrl(); }
514 virtual void customClicked() { return; }
516 BundleList bundlesToSync( const QString &playlistName, const QString &sql );
517 BundleList bundlesToSync( const QString &playlistName, const KUrl &url );
518 void preparePlaylistForSync( const QString &playlistName, const BundleList &bundles );
519 bool isOnOtherPlaylist( const QString &playlistToAvoid, const MetaBundle &bundle );
520 bool isOnPlaylist( const MediaItem &playlist, const MetaBundle &bundle );
521 bool isInBundleList( const BundleList &bundles, const MetaBundle &bundle );
522 bool bundleMatch( const MetaBundle &b1, const MetaBundle &b2 );
524 public slots:
525 void abortTransfer();
526 void transferFiles();
527 virtual void renameItem( Q3ListViewItem *item ) {(void)item; }
528 virtual void expandItem( Q3ListViewItem *item ) {(void)item; }
529 bool connectDevice( bool silent=false );
530 bool disconnectDevice( bool postdisconnecthook=true );
531 void scheduleDisconnect() { m_scheduledDisconnect = true; }
533 protected slots:
534 void fileTransferred( KIO::Job *job );
535 void fileTransferFinished();
537 private:
538 int sysCall(const QString & command);
539 int runPreConnectCommand();
540 int runPostDisconnectCommand();
541 QString replaceVariables( const QString &cmd ); // replace %m with mount point and %d with device node
543 QString uid() { return m_uid; }
544 void setUid( const QString &uid ) { m_uid = uid; }
547 * Find a particular track
548 * @param bundle The metabundle of the requested media item
549 * @return The MediaItem of the item if found, otherwise NULL
550 * @note This may not be worth implementing for non database driven devices, as it could be slow
552 virtual MediaItem *trackExists( const MetaBundle& bundle ) = 0;
554 protected:
556 * Get the capacity and freespace available on the device, in bytes
557 * @return true if successful
559 virtual bool getCapacity( KIO::filesize_t *total, KIO::filesize_t *available ) { Q_UNUSED(total); Q_UNUSED(available); return false; }
562 * Lock device for exclusive access if possible
564 virtual bool lockDevice( bool tryOnly = false ) = 0;
567 * Unlock device
569 virtual void unlockDevice() = 0;
572 * Connect to device, and populate m_view with MediaItems
573 * @return true if successful
575 virtual bool openDevice( bool silent=false ) = 0;
578 * Wrap up any loose ends and close the device
579 * @return true if successful
581 virtual bool closeDevice() = 0;
584 * Write any pending changes to the device, such as database changes
586 virtual void synchronizeDevice() = 0;
589 * Copy a track to the device
590 * @param bundle The MetaBundle of the item to transfer. Will move the item specified by bundle().url().path()
591 * @return If successful, the created MediaItem in the media device view, else 0
593 virtual MediaItem *copyTrackToDevice(const MetaBundle& bundle) = 0;
596 * Copy track from device to computer
597 * @param item The MediaItem of the track to transfer.
598 * @param url The URL to transfer the track to.
599 * @return The MediaItem transfered.
601 virtual void copyTrackFromDevice(MediaItem *item);
604 * Recursively remove MediaItem from the tracklist and the device
605 * @param item MediaItem to remove
606 * @param onlyPlayed True if item should be deleted only if it has been played
607 * @return -1 on failure, number of files deleted otherwise
609 virtual int deleteItemFromDevice( MediaItem *item, int flags=DeleteTrack ) = 0;
612 * Abort the currently active track transfer
614 virtual void cancelTransfer() { /* often checking m_cancel is enough */ }
616 virtual void updateRootItems();
618 virtual bool isSpecialItem( MediaItem *item );
620 int deleteFromDevice( MediaItem *item=0, int flags=DeleteTrack );
622 void purgeEmptyItems( MediaItem *root=0 );
623 void syncStatsFromDevice( MediaItem *root=0 );
624 void syncStatsToDevice( MediaItem *root=0 );
626 bool kioCopyTrack( const KUrl &src, const KUrl &dst );
628 QString m_name;
630 bool m_hasMountPoint;
632 QString m_preconnectcmd;
633 QString m_postdisconnectcmd;
634 bool m_autoDeletePodcasts;
635 bool m_syncStats;
637 bool m_transcode;
638 bool m_transcodeAlways;
639 bool m_transcodeRemove;
641 K3ShellProcess *sysProc;
642 MediaBrowser *m_parent;
643 MediaView *m_view;
644 Medium m_medium;
645 QString m_transferDir;
646 QString m_firstSort;
647 QString m_secondSort;
648 QString m_thirdSort;
649 QString m_uid;
650 bool m_wait;
651 bool m_waitForDeletion;
652 bool m_copyFailed;
653 bool m_requireMount;
654 bool m_canceled;
655 bool m_transferring;
656 bool m_deleting;
657 bool m_deferredDisconnect;
658 bool m_scheduledDisconnect;
659 bool m_runDisconnectHook;
660 bool m_spacesToUnderscores;
661 bool m_transfer;
662 bool m_configure;
663 bool m_customButton;
665 QString m_type;
667 // root listview items
668 MediaItem *m_playlistItem;
669 MediaItem *m_podcastItem;
670 // items not on the master playlist and not on the podcast playlist are not visible on the ipod
671 MediaItem *m_invisibleItem;
672 // items in the database for which the file is missing
673 MediaItem *m_staleItem;
674 // files without database entry
675 MediaItem *m_orphanedItem;
677 // stow away all items below m_rootItems when device is not current
678 Q3PtrList<Q3ListViewItem> m_rootItems;
682 #endif /* AMAROK_MEDIABROWSER_H */