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"
12 #include "browserToolBar.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
21 #include <kio/global.h> //filesize_t
22 #include <KUrl> //stack allocated
23 #include <KVBox> //baseclass
52 class AMAROK_EXPORT MediaItem
: public K3ListViewItem
55 MediaItem( Q3ListView
* parent
);
56 MediaItem( Q3ListViewItem
* parent
);
57 MediaItem( Q3ListView
* parent
, Q3ListViewItem
* after
);
58 MediaItem( Q3ListViewItem
* parent
, Q3ListViewItem
* after
);
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
; }
101 void paintCell( QPainter
*p
, const QColorGroup
&cg
, int column
, int width
, int align
);
106 QString m_playlistName
;
108 MediaDevice
*m_device
;
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
;
129 mutable MetaBundle
*m_bundle
;
132 class MediaQueue
: public K3ListView
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();
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();
164 void itemCountChanged();
167 void selectAll() {Q3ListView::selectAll(true); }
168 void slotShowContextMenu( Q3ListViewItem
* item
, const QPoint
& point
, int );
169 void slotDropped (QDropEvent
* e
, Q3ListViewItem
* parent
, Q3ListViewItem
* after
);
172 void keyPressEvent( QKeyEvent
*e
);
173 MediaBrowser
*m_parent
;
174 mutable KIO::filesize_t m_totalSize
;
178 class MediaBrowser
: public QWidget
181 friend class DeviceConfigureDialog
;
182 friend class MediaDevice
;
183 friend class MediaView
;
184 friend class MediaQueue
;
185 friend class MediumPluginChooser
;
186 friend class MediaItem
;
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
; }
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
; }
222 void availabilityChanged( bool isAvailable
);
225 void transferClicked();
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();
246 MediaDevice
*loadDevicePlugin( const QString
&udi
);
247 void unloadDevicePlugin( MediaDevice
*device
);
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
);
261 bool m_waitForTranscode
;
262 KUrl m_transcodedUrl
;
263 QString m_transcodeSrc
;
266 KHBox
* m_progressBox
;
267 QProgressBar
* m_progress
;
269 KPushButton
* m_cancelButton
;
270 //KPushButton* m_playlistButton;
272 KComboBox
* m_configPluginCombo
;
273 KComboBox
* m_deviceCombo
;
274 Browser::ToolBar
*m_toolbar
;
275 typedef QMap
<QString
, MediaItem
*> ItemMap
;
276 mutable QMutex m_itemMapMutex
;
278 KService::List m_plugins
;
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
292 friend class MediaBrowser
;
293 friend class MediaDevice
;
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
);
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
* );
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();
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
338 friend class DeviceConfigureDialog
;
339 friend class TransferDialog
;
340 friend class MediaBrowser
;
341 friend class MediaView
;
342 friend class MediaQueue
;
354 virtual void init( MediaBrowser
* parent
);
355 virtual ~MediaDevice();
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 */ );
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
);
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; }
534 void fileTransferred( KIO::Job
*job
);
535 void fileTransferFinished();
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;
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;
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
);
630 bool m_hasMountPoint
;
632 QString m_preconnectcmd
;
633 QString m_postdisconnectcmd
;
634 bool m_autoDeletePodcasts
;
638 bool m_transcodeAlways
;
639 bool m_transcodeRemove
;
641 K3ShellProcess
*sysProc
;
642 MediaBrowser
*m_parent
;
645 QString m_transferDir
;
647 QString m_secondSort
;
651 bool m_waitForDeletion
;
657 bool m_deferredDisconnect
;
658 bool m_scheduledDisconnect
;
659 bool m_runDisconnectHook
;
660 bool m_spacesToUnderscores
;
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 */