1 // (c) 2004 Christian Muehlhaeuser <chris@chris.de>
2 // (c) 2005 Martin Aumueller <aumuell@reserv.at>
3 // (c) 2005 Seb Ruiz <ruiz@kde.org>
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
55 class MediaQueue
: public K3ListView
60 MediaQueue(MediaBrowser
*parent
);
61 MediaItem
*findPath( QString path
);
63 KIO::filesize_t
totalSize() const; // total size of items to transfer in KB
64 void computeSize() const; // compute total size of items to transfer in KB
65 void addItemToSize( const MediaItem
*item
) const;
66 void subtractItemFromSize( const MediaItem
*item
, bool unconditonally
=false ) const;
68 void removeSelected();
71 void load( const QString
&path
);
72 void save( const QString
&path
);
73 void syncPlaylist( const QString
&playlistName
, const QString
&sql
, bool loading
=false );
74 void syncPlaylist( const QString
&playlistName
, const KUrl
&url
, bool loading
=false );
75 void addUrl( const KUrl
& url
, MetaBundle
*bundle
=NULL
, const QString
&playlistName
=QString() );
76 void addUrl( const KUrl
& url
, MediaItem
*item
);
77 void addUrls( const KUrl::List urls
, const QString
&playlistName
=QString() );
79 void URLsAdded(); // call after finishing adding single urls
81 void dropProxyEvent( QDropEvent
*e
);
82 // Reimplemented from K3ListView
83 bool acceptDrag( QDropEvent
*e
) const;
84 Q3DragObject
*dragObject();
87 void itemCountChanged();
90 void selectAll() {Q3ListView::selectAll(true); }
91 void slotShowContextMenu( Q3ListViewItem
* item
, const QPoint
& point
, int );
92 void slotDropped (QDropEvent
* e
, Q3ListViewItem
* parent
, Q3ListViewItem
* after
);
95 void keyPressEvent( QKeyEvent
*e
);
96 MediaBrowser
*m_parent
;
97 mutable KIO::filesize_t m_totalSize
;
101 class MediaBrowser
: public QWidget
104 friend class DeviceConfigureDialog
;
105 friend class MediaDevice
;
106 friend class MediaView
;
107 friend class MediaQueue
;
108 friend class MediumPluginChooser
;
109 friend class MediaItem
;
112 static bool isAvailable();
113 AMAROK_EXPORT
static MediaBrowser
*instance() { return s_instance
; }
114 AMAROK_EXPORT
static MediaQueue
*queue() { return s_instance
? s_instance
->m_queue
: 0; }
116 MediaBrowser( const char *name
);
117 virtual ~MediaBrowser();
118 bool blockQuit() const;
119 MediaDevice
*currentDevice() const { return m_currentDevice
; }
120 MediaDevice
*deviceFromId( const QString
&id
) const;
121 QStringList
deviceNames() const;
122 bool deviceSwitch( const QString
&name
);
124 QString
getInternalPluginName ( const QString string
) { return m_pluginName
[string
]; }
125 QString
getDisplayPluginName ( const QString string
) { return m_pluginAmarokName
[string
]; }
126 const KService::List
&getPlugins() { return m_plugins
; }
127 void transcodingFinished( const QString
&src
, const QString
&dst
);
128 bool isTranscoding() const { return m_waitForTranscode
; }
130 void updateButtons();
131 void updateDevices();
132 // return bundle for url if it is known to MediaBrowser
133 bool getBundle( const KUrl
&url
, MetaBundle
*bundle
) const;
134 bool isQuitting() const { return m_quitting
; }
136 KUrl
getProxyUrl( const KUrl
& daapUrl
) const;
137 KToolBar
* getToolBar() const { return m_toolbar
; }
138 KAction
*connectAction() const { return m_connectAction
; }
139 KAction
*disconnectAction() const { return m_disconnectAction
; }
140 KAction
*transferAction() const { return m_transferAction
; }
141 KAction
*configAction() const { return m_configAction
; }
142 KAction
*customAction() const { return m_customAction
; }
145 void availabilityChanged( bool isAvailable
);
148 void transferClicked();
151 void slotSetFilterTimeout();
152 void slotSetFilter();
153 void slotSetFilter( const QString
&filter
);
154 void slotEditFilter();
155 void deviceAdded( const QString
&udi
);
156 void deviceRemoved( const QString
&udi
);
157 void activateDevice( const MediaDevice
*device
);
158 void activateDevice( int index
, bool skipDummy
= true );
159 void cancelClicked();
160 void connectClicked();
161 void disconnectClicked();
162 void customClicked();
163 bool config(); // false if canceled by user
164 KUrl
transcode( const KUrl
&src
, const QString
&filetype
);
165 void tagsChanged( const MetaBundle
&bundle
);
166 void prepareToQuit();
169 MediaDevice
*loadDevicePlugin( const QString
&udi
);
170 void unloadDevicePlugin( MediaDevice
*device
);
173 AMAROK_EXPORT
static MediaBrowser
*s_instance
;
175 QList
<MediaDevice
*> m_devices
;
176 MediaDevice
* m_currentDevice
;
178 QMap
<QString
, QString
> m_pluginName
;
179 QMap
<QString
, QString
> m_pluginAmarokName
;
180 void addDevice( MediaDevice
*device
);
181 void removeDevice( MediaDevice
*device
);
184 bool m_waitForTranscode
;
185 KUrl m_transcodedUrl
;
186 QString m_transcodeSrc
;
189 KHBox
* m_progressBox
;
190 QProgressBar
* m_progress
;
192 KPushButton
* m_cancelButton
;
193 //KPushButton* m_playlistButton;
195 KComboBox
* m_configPluginCombo
;
196 KComboBox
* m_deviceCombo
;
197 Browser::ToolBar
*m_toolbar
;
198 typedef QMap
<QString
, MediaItem
*> ItemMap
;
199 mutable QMutex m_itemMapMutex
;
201 KService::List m_plugins
;
204 KAction
*m_connectAction
;
205 KAction
*m_disconnectAction
;
206 KAction
*m_customAction
;
207 KAction
*m_configAction
;
208 KAction
*m_transferAction
;
209 SearchWidget
*m_searchWidget
;
212 class MediaView
: public K3ListView
215 friend class MediaBrowser
;
216 friend class MediaDevice
;
226 MediaView( QWidget
*parent
, MediaDevice
*device
);
227 virtual ~MediaView();
228 AMAROK_EXPORT
KUrl::List
nodeBuildDragList( MediaItem
* item
, int flags
=OnlySelected
);
229 int getSelectedLeaves(MediaItem
*parent
, Q3PtrList
<MediaItem
> *list
, int flags
=OnlySelected
);
230 AMAROK_EXPORT MediaItem
*newDirectory( MediaItem
* parent
);
231 bool setFilter( const QString
&filter
, MediaItem
*parent
=NULL
);
234 void rmbPressed( Q3ListViewItem
*, const QPoint
&, int );
235 void renameItem( Q3ListViewItem
*item
);
236 void slotExpand( Q3ListViewItem
* );
237 void selectAll() { Q3ListView::selectAll(true); }
238 void invokeItem( Q3ListViewItem
*, const QPoint
&, int column
);
239 void invokeItem( Q3ListViewItem
* );
242 void keyPressEvent( QKeyEvent
*e
);
243 // Reimplemented from K3ListView
244 void contentsDropEvent( QDropEvent
*e
);
245 void viewportPaintEvent( QPaintEvent
* );
246 bool acceptDrag( QDropEvent
*e
) const;
247 Q3DragObject
*dragObject();
250 MediaDevice
*m_device
;
254 /* at least the pure virtual functions have to be implemented by a media device,
255 all items are stored in a hierarchy of MediaItems,
256 when items are manipulated the MediaItems have to be updated accordingly */
258 class AMAROK_EXPORT MediaDevice
: public QObject
, public Amarok::Plugin
261 friend class DeviceConfigureDialog
;
262 friend class TransferDialog
;
263 friend class MediaBrowser
;
264 friend class MediaView
;
265 friend class MediaQueue
;
277 virtual void init( MediaBrowser
* parent
);
278 virtual ~MediaDevice();
283 * @return a KAction that will be plugged into the media device browser toolbar
285 virtual KAction
*customAction() { return 0; }
287 virtual void rmbPressed( Q3ListViewItem
*item
, const QPoint
&point
, int ) { (void)item
; (void) point
; }
290 * @return list of filetypes playable on this device
291 * (empty list is interpreted as all types are good)
293 virtual QStringList
supportedFiletypes() { return QStringList(); }
296 * @param bundle describes track that should be checked
297 * @return true if the device is capable of playing the track referred to by bundle
299 virtual bool isPlayable( const MetaBundle
&bundle
);
302 * @param bundle describes track that should be checked
303 * @return true if the track is in the preferred (first in list) format of the device
305 virtual bool isPreferredFormat( const MetaBundle
&bundle
);
308 * @return true if the device is connected
310 virtual bool isConnected() = 0;
313 * Adds particular tracks to a playlist
314 * @param playlist parent playlist for tracks to be added to
315 * @param after insert following this item
316 * @param items tracks to add to playlist
318 virtual void addToPlaylist(MediaItem
*playlist
, MediaItem
*after
, Q3PtrList
<MediaItem
> items
) { Q_UNUSED(playlist
); Q_UNUSED(after
); Q_UNUSED(items
); }
321 * Create a new playlist
322 * @param name playlist title
323 * @param parent parent MediaItem of the new playlist
324 * @param items tracks to add to the new playlist
325 * @return the newly created playlist
327 virtual MediaItem
*newPlaylist(const QString
&name
, MediaItem
*parent
, Q3PtrList
<MediaItem
> items
) { Q_UNUSED(name
); Q_UNUSED(parent
); Q_UNUSED(items
); return 0; }
330 * Move items to a directory
331 * @param directory new parent of dropped items
332 * @param items tracks to add to the directory
334 virtual void addToDirectory( MediaItem
*directory
, Q3PtrList
<MediaItem
> items
) { Q_UNUSED(directory
); Q_UNUSED(items
); }
337 * Create a new directory
338 * @param name directory title
339 * @param parent parent MediaItem of the new directory
340 * @param items tracks to add to the new directory
341 * @return the newly created directory
343 virtual MediaItem
*newDirectory( const QString
&name
, MediaItem
*parent
) { Q_UNUSED(name
); Q_UNUSED(parent
); return 0; }
346 * Notify device of changed tags
347 * @param item item to be updated
348 * @param changed bundle containing new tags
349 * @return the changed MediaItem
351 virtual MediaItem
*tagsChanged( MediaItem
*item
, const MetaBundle
&changed
) { Q_UNUSED(item
); Q_UNUSED(changed
); return 0; }
354 * Indicate whether the device has a custom transfer dialog
355 * @return whether there is a custom dialog
357 virtual bool hasTransferDialog() { return false; }
360 * Run the transfer dialog to be used when Transfer is clicked
362 virtual void runTransferDialog() {}
365 * Get the transfer dialog, if any
366 * @return the transfer dialog, if any, else NULL;
368 virtual TransferDialog
*getTransferDialog() { return NULL
; }
371 * Can be used to explicitly indicate whether a device needs manual configuration
372 * @return whether manual configuration is needed
374 virtual bool needsManualConfig() { return true; }
376 virtual void addConfigElements( QWidget
* /*parent*/ ) {}
377 virtual void removeConfigElements( QWidget
* /*parent*/ ) {}
378 virtual void applyConfig() {}
379 virtual void loadConfig();
381 QString
configString( const QString
&name
, const QString
&defValue
= QString() );
382 void setConfigString( const QString
&name
, const QString
&value
);
383 bool configBool( const QString
&name
, bool defValue
=false );
384 void setConfigBool( const QString
&name
, bool value
);
386 void setRequireMount( const bool b
) { m_requireMount
= b
; }
387 bool hasMountPoint() { return m_hasMountPoint
; }
388 void setDeviceType( const QString
&type
) { m_type
= type
; }
389 QString
deviceType() { return m_type
; }
390 virtual bool autoConnect() { return false; }
391 virtual bool asynchronousTransfer() { return false; }
392 bool isTransferring() { return m_transferring
; }
393 bool isDeleting() { return m_deleting
; }
394 bool isCanceled() { return m_canceled
; }
395 void setCanceled( const bool b
) { m_canceled
= b
; }
397 int progress() const;
398 void setProgress( const int progress
, const int total
= -1 /* leave total unchanged by default */ );
403 * @return a unique identifier that is constant across sessions
405 QString
uniqueId() const { return m_uid
; }
408 * @return the name for the device that should be presented to the user
410 QString
name() const { return m_name
; }
413 * @return the device node
415 QString
deviceNode() const { return m_medium
.deviceNode(); }
418 * @return the device mount point (or empty if non-applicable or unknown)
420 QString
mountPoint() const { return m_medium
.mountPoint(); }
422 QString
getTransferDir() { return m_transferDir
; }
423 Medium
&getMedium() { return m_medium
; }
425 void setSpacesToUnderscores( bool yesno
) { m_spacesToUnderscores
= yesno
;
426 setConfigBool( "spacesToUnderscores", yesno
); }
427 bool getSpacesToUnderscores() { return m_spacesToUnderscores
; }
429 void setFirstSort( QString text
) { m_firstSort
= text
;
430 setConfigString( "firstGrouping", text
); }
431 void setSecondSort( QString text
) { m_secondSort
= text
;
432 setConfigString( "secondGrouping", text
); }
433 void setThirdSort( QString text
) { m_thirdSort
= text
;
434 setConfigString( "thirdGrouping", text
); }
436 virtual KUrl
getProxyUrl( const KUrl
& /*url*/) { return KUrl(); }
437 virtual void customClicked() { return; }
439 BundleList
bundlesToSync( const QString
&playlistName
, const QString
&sql
);
440 BundleList
bundlesToSync( const QString
&playlistName
, const KUrl
&url
);
441 void preparePlaylistForSync( const QString
&playlistName
, const BundleList
&bundles
);
442 bool isOnOtherPlaylist( const QString
&playlistToAvoid
, const MetaBundle
&bundle
);
443 bool isOnPlaylist( const MediaItem
&playlist
, const MetaBundle
&bundle
);
444 bool isInBundleList( const BundleList
&bundles
, const MetaBundle
&bundle
);
445 bool bundleMatch( const MetaBundle
&b1
, const MetaBundle
&b2
);
448 void abortTransfer();
449 void transferFiles();
450 virtual void renameItem( Q3ListViewItem
*item
) {(void)item
; }
451 virtual void expandItem( Q3ListViewItem
*item
) {(void)item
; }
452 bool connectDevice( bool silent
=false );
453 bool disconnectDevice( bool postdisconnecthook
=true );
454 void scheduleDisconnect() { m_scheduledDisconnect
= true; }
457 void fileTransferred( KIO::Job
*job
);
458 void fileTransferFinished();
461 int sysCall(const QString
& command
);
462 int runPreConnectCommand();
463 int runPostDisconnectCommand();
464 QString
replaceVariables( const QString
&cmd
); // replace %m with mount point and %d with device node
466 QString
uid() { return m_uid
; }
467 void setUid( const QString
&uid
) { m_uid
= uid
; }
470 * Find a particular track
471 * @param bundle The metabundle of the requested media item
472 * @return The MediaItem of the item if found, otherwise NULL
473 * @note This may not be worth implementing for non database driven devices, as it could be slow
475 virtual MediaItem
*trackExists( const MetaBundle
& bundle
) = 0;
479 * Get the capacity and freespace available on the device, in bytes
480 * @return true if successful
482 virtual bool getCapacity( KIO::filesize_t
*total
, KIO::filesize_t
*available
) { Q_UNUSED(total
); Q_UNUSED(available
); return false; }
485 * Lock device for exclusive access if possible
487 virtual bool lockDevice( bool tryOnly
= false ) = 0;
492 virtual void unlockDevice() = 0;
495 * Connect to device, and populate m_view with MediaItems
496 * @return true if successful
498 virtual bool openDevice( bool silent
=false ) = 0;
501 * Wrap up any loose ends and close the device
502 * @return true if successful
504 virtual bool closeDevice() = 0;
507 * Write any pending changes to the device, such as database changes
509 virtual void synchronizeDevice() = 0;
512 * Copy a track to the device
513 * @param bundle The MetaBundle of the item to transfer. Will move the item specified by bundle().url().path()
514 * @return If successful, the created MediaItem in the media device view, else 0
516 virtual MediaItem
*copyTrackToDevice(const MetaBundle
& bundle
) = 0;
519 * Copy track from device to computer
520 * @param item The MediaItem of the track to transfer.
521 * @param url The URL to transfer the track to.
522 * @return The MediaItem transfered.
524 virtual void copyTrackFromDevice(MediaItem
*item
);
527 * Recursively remove MediaItem from the tracklist and the device
528 * @param item MediaItem to remove
529 * @param onlyPlayed True if item should be deleted only if it has been played
530 * @return -1 on failure, number of files deleted otherwise
532 virtual int deleteItemFromDevice( MediaItem
*item
, int flags
=DeleteTrack
) = 0;
535 * Abort the currently active track transfer
537 virtual void cancelTransfer() { /* often checking m_cancel is enough */ }
539 virtual void updateRootItems();
541 virtual bool isSpecialItem( MediaItem
*item
);
543 int deleteFromDevice( MediaItem
*item
=0, int flags
=DeleteTrack
);
545 void purgeEmptyItems( MediaItem
*root
=0 );
546 void syncStatsFromDevice( MediaItem
*root
=0 );
547 void syncStatsToDevice( MediaItem
*root
=0 );
549 bool kioCopyTrack( const KUrl
&src
, const KUrl
&dst
);
553 bool m_hasMountPoint
;
555 QString m_preconnectcmd
;
556 QString m_postdisconnectcmd
;
557 bool m_autoDeletePodcasts
;
561 bool m_transcodeAlways
;
562 bool m_transcodeRemove
;
564 K3ShellProcess
*sysProc
;
565 MediaBrowser
*m_parent
;
568 QString m_transferDir
;
570 QString m_secondSort
;
574 bool m_waitForDeletion
;
580 bool m_deferredDisconnect
;
581 bool m_scheduledDisconnect
;
582 bool m_runDisconnectHook
;
583 bool m_spacesToUnderscores
;
590 // root listview items
591 MediaItem
*m_playlistItem
;
592 MediaItem
*m_podcastItem
;
593 // items not on the master playlist and not on the podcast playlist are not visible on the ipod
594 MediaItem
*m_invisibleItem
;
595 // items in the database for which the file is missing
596 MediaItem
*m_staleItem
;
597 // files without database entry
598 MediaItem
*m_orphanedItem
;
600 // stow away all items below m_rootItems when device is not current
601 Q3PtrList
<Q3ListViewItem
> m_rootItems
;
605 #endif /* AMAROK_MEDIABROWSER_H */