1
/****************************************************************************************
2
* Copyright (c) 2009 Alejandro Wainzinger <aikawarazuni@gmail.com> *
4
* This program is free software; you can redistribute it and/or modify it under *
5
* the terms of the GNU General Public License as published by the Free Software *
6
* Foundation; either version 2 of the License, or (at your option) any later *
9
* This program is distributed in the hope that it will be useful, but WITHOUT ANY *
10
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A *
11
* PARTICULAR PURPOSE. See the GNU General Public License for more details. *
13
* You should have received a copy of the GNU General Public License along with *
14
* this program. If not, see <http://www.gnu.org/licenses/>. *
15
****************************************************************************************/
17
#include "MediaDeviceMeta.h"
18
#include "MediaDeviceCollection.h"
19
#include "MediaDeviceHandler.h"
21
#include "handler/capabilities/ArtworkCapability.h"
23
// HACK: used to test disconnect
24
#include "MediaDeviceMonitor.h"
26
#include "covermanager/CoverFetchingActions.h"
27
#include "core/support/Debug.h"
28
#include "SvgHandler.h"
29
#include "core/capabilities/ActionsCapability.h"
30
#include "core/capabilities/EditCapability.h"
31
#include "core/capabilities/UpdateCapability.h"
39
// Currently complaining about some vtable issue
41
class EditCapabilityMediaDevice : public Capabilities::EditCapability
45
EditCapabilityMediaDevice( MediaDeviceTrack *track )
46
: Capabilities::EditCapability()
49
virtual bool isEditable() const { return m_track->isEditable(); }
50
virtual void setAlbum( const QString &newAlbum ) { m_track->setAlbum( newAlbum ); }
51
virtual void setAlbumArtist( const QString &newAlbumArtist ) { m_track->setAlbumArtist( newAlbumArtist ); }
52
virtual void setArtist( const QString &newArtist ) { m_track->setArtist( newArtist ); }
53
virtual void setComposer( const QString &newComposer ) { m_track->setComposer( newComposer ); }
54
virtual void setGenre( const QString &newGenre ) { m_track->setGenre( newGenre ); }
55
virtual void setYear( int newYear ) { m_track->setYear( newYear ); }
56
virtual void setBpm( const qreal newBpm ) { m_track->setBpm( newBpm ); }
57
virtual void setTitle( const QString &newTitle ) { m_track->setTitle( newTitle ); }
58
virtual void setComment( const QString &newComment ) { m_track->setComment( newComment ); }
59
virtual void setTrackNumber( int newTrackNumber ) { m_track->setTrackNumber( newTrackNumber ); }
60
virtual void setDiscNumber( int newDiscNumber ) { m_track->setDiscNumber( newDiscNumber ); }
61
virtual void setUidUrl( const QString &newUidUrl ) { m_track->setUidUrl( newUidUrl ); }
62
virtual void beginMetaDataUpdate() { m_track->beginMetaDataUpdate(); }
63
virtual void endMetaDataUpdate() { m_track->endMetaDataUpdate(); }
66
KSharedPtr<MediaDeviceTrack> m_track;
69
class UpdateCapabilityMediaDevice : public Capabilities::UpdateCapability
73
UpdateCapabilityMediaDevice( Collections::MediaDeviceCollection *coll )
74
: Capabilities::UpdateCapability()
78
virtual void collectionUpdated() const
80
m_coll->collectionUpdated();
81
m_coll->writeDatabase();
85
Collections::MediaDeviceCollection *m_coll;
89
MediaDeviceTrack::MediaDeviceTrack( Collections::MediaDeviceCollection *collection )
91
, m_collection( collection )
114
MediaDeviceTrack::~MediaDeviceTrack()
120
MediaDeviceTrack::name() const
126
MediaDeviceTrack::playableUrl() const
128
return m_playableUrl;
132
MediaDeviceTrack::uidUrl() const
134
return m_playableUrl.isLocalFile() ? m_playableUrl.toLocalFile() : m_playableUrl.url();
138
MediaDeviceTrack::setUidUrl( const QString &newUidUrl ) const
140
Q_UNUSED( newUidUrl )
144
MediaDeviceTrack::prettyUrl() const
146
return m_playableUrl.isLocalFile() ? m_playableUrl.toLocalFile() : QString( collection()->prettyName() + ": " + artist()->prettyName() + " - " + prettyName() );
150
MediaDeviceTrack::isPlayable() const
156
MediaDeviceTrack::isEditable() const
158
// TODO: Should only be true if disk mounted read/write, implement check later
163
MediaDeviceTrack::album() const
165
return AlbumPtr::staticCast( m_album );
169
MediaDeviceTrack::artist() const
171
return ArtistPtr::staticCast( m_artist );
175
MediaDeviceTrack::genre() const
177
return GenrePtr::staticCast( m_genre );
181
MediaDeviceTrack::composer() const
183
return ComposerPtr::staticCast( m_composer );
187
MediaDeviceTrack::year() const
189
return YearPtr::staticCast( m_year );
193
MediaDeviceTrack::comment() const
199
MediaDeviceTrack::setComment( const QString &newComment )
201
m_comment = newComment;
205
MediaDeviceTrack::score() const
211
MediaDeviceTrack::setScore( double newScore )
217
MediaDeviceTrack::rating() const
223
MediaDeviceTrack::setRating( int newRating )
225
m_rating = newRating;
230
MediaDeviceTrack::length() const
236
MediaDeviceTrack::setFileSize( int newFileSize )
238
m_filesize = newFileSize;
242
MediaDeviceTrack::filesize() const
244
// TODO: NYI, seems to cause crashing on transferring tracks to mediadevice
249
MediaDeviceTrack::bitrate() const
255
MediaDeviceTrack::setBitrate( int newBitrate )
257
m_bitrate = newBitrate;
261
MediaDeviceTrack::sampleRate() const
267
MediaDeviceTrack::setSamplerate( int newSamplerate )
269
m_samplerate = newSamplerate;
273
MediaDeviceTrack::bpm() const
278
MediaDeviceTrack::setBpm( const qreal newBpm )
284
MediaDeviceTrack::trackNumber() const
286
return m_trackNumber;
290
MediaDeviceTrack::setTrackNumber( int newTrackNumber )
292
m_trackNumber = newTrackNumber;
296
MediaDeviceTrack::discNumber() const
302
MediaDeviceTrack::setDiscNumber( int newDiscNumber )
304
m_discNumber = newDiscNumber;
308
MediaDeviceTrack::playCount() const
314
MediaDeviceTrack::setPlayCount( const int newCount )
316
m_playCount = newCount;
320
MediaDeviceTrack::lastPlayed() const
326
MediaDeviceTrack::setLastPlayed( const QDateTime &newTime )
328
m_lastPlayed = newTime;
332
MediaDeviceTrack::type() const
334
if( m_type.isEmpty() && !m_playableUrl.path().isEmpty() )
336
QString path = m_playableUrl.path();
337
return path.mid( path.lastIndexOf( '.' ) + 1 );
343
MediaDeviceTrack::setType( const QString & type )
349
MediaDeviceTrack::prepareToPlay()
351
Meta::MediaDeviceTrackPtr ptr = Meta::MediaDeviceTrackPtr( this );
353
if( m_collection && m_collection.data()->handler() )
354
m_collection.data()->handler()->prepareToPlay( ptr );
357
// TODO: employ observers (e.g. Handler) to take care of updated
361
MediaDeviceTrack::subscribe( Observer *observer )
363
Q_UNUSED( observer ) //read only
367
MediaDeviceTrack::unsubscribe( Observer *observer )
369
Q_UNUSED( observer ) //read only
372
// TODO: implement this for MediaDeviceCollectionLocation
374
MediaDeviceTrack::inCollection() const
379
Collections::Collection*
380
MediaDeviceTrack::collection() const
382
return m_collection.data();
386
MediaDeviceTrack::hasCapabilityInterface( Capabilities::Capability::Type type ) const
390
case Capabilities::Capability::Editable:
391
return m_collection ? m_collection.data()->isWritable() : false;
393
case Capabilities::Capability::Updatable:
394
return m_collection ? m_collection.data()->isWritable() : false;
401
Capabilities::Capability*
402
MediaDeviceTrack::createCapabilityInterface( Capabilities::Capability::Type type )
406
case Capabilities::Capability::Editable:
407
return new EditCapabilityMediaDevice( this );
408
case Capabilities::Capability::Updatable:
409
return new UpdateCapabilityMediaDevice( m_collection.data() );
417
MediaDeviceTrack::setAlbum( const QString &newAlbum )
419
MediaDeviceAlbumPtr albumPtr;
420
MediaDeviceTrackPtr track( this );
421
AlbumMap albumMap = m_collection.data()->memoryCollection()->albumMap();
423
// do cleanup of soon to be previous album
426
if ( !albumPtr.isNull() )
428
// remove track from previous album's tracklist
429
albumPtr->remTrack( track );
430
// if album's tracklist is empty, remove album from albummap
431
if( albumPtr->tracks().isEmpty() )
432
albumMap.remove( albumPtr->name() );
435
// change to a new album
437
// check for the existence of the album to be set to,
438
// if album exists, reuse, else create
440
if ( albumMap.contains( newAlbum ) )
442
albumPtr = MediaDeviceAlbumPtr::staticCast( albumMap.value( newAlbum ) );
446
albumPtr = MediaDeviceAlbumPtr( new MediaDeviceAlbum( m_collection.data(), newAlbum ) );
447
albumMap.insert( newAlbum, AlbumPtr::staticCast( albumPtr ) );
450
// add track to album's tracklist
451
albumPtr->addTrack( track );
452
// set track's album to the new album
453
setAlbum( albumPtr );
455
m_collection.data()->memoryCollection()->acquireWriteLock();
456
m_collection.data()->memoryCollection()->setAlbumMap( albumMap );
457
m_collection.data()->memoryCollection()->releaseLock();
461
MediaDeviceTrack::setAlbumArtist( const QString &newAlbumArtist )
465
if( m_album.isNull() || newAlbumArtist.isEmpty() )
468
MediaDeviceArtistPtr artistPtr;
469
ArtistMap artistMap = m_collection.data()->memoryCollection()->artistMap();
470
artistPtr = MediaDeviceArtistPtr::staticCast( m_album->albumArtist() );
472
if( !artistPtr.isNull() )
474
artistPtr->remAlbum( m_album );
475
if( artistPtr->tracks().isEmpty() && artistPtr->albums().isEmpty() )
476
artistMap.remove( artistPtr->name() );
479
if( artistMap.contains( newAlbumArtist ) )
480
artistPtr = MediaDeviceArtistPtr::staticCast( artistMap.value( newAlbumArtist ) );
483
artistPtr = MediaDeviceArtistPtr( new MediaDeviceArtist( newAlbumArtist ) );
484
artistMap.insert( newAlbumArtist, ArtistPtr::staticCast( artistPtr ) );
487
artistPtr->addAlbum( m_album );
488
m_album->setAlbumArtist( artistPtr );
490
m_collection.data()->memoryCollection()->acquireWriteLock();
491
m_collection.data()->memoryCollection()->setArtistMap( artistMap );
492
m_collection.data()->memoryCollection()->releaseLock();
496
MediaDeviceTrack::setArtist( const QString &newArtist )
500
MediaDeviceArtistPtr artistPtr;
501
MediaDeviceTrackPtr track( this );
502
ArtistMap artistMap = m_collection.data()->memoryCollection()->artistMap();
504
// do cleanup of soon to be previous artist
506
artistPtr = m_artist;
507
// remove track from previous artist's tracklist
508
if ( !artistPtr.isNull() )
510
artistPtr->remTrack( track );
511
// if artist's tracklist is empty, remove artist from artistmap
512
if( artistPtr->tracks().isEmpty() && artistPtr->albums().isEmpty() )
513
artistMap.remove( artistPtr->name() );
516
// change to a new artist
518
// check for the existence of the artist to be set to,
519
// if artist exists, reuse, else create
521
if ( artistMap.contains( newArtist ) )
523
artistPtr = MediaDeviceArtistPtr::staticCast( artistMap.value( newArtist ) );
527
artistPtr = MediaDeviceArtistPtr( new MediaDeviceArtist( newArtist ) );
528
artistMap.insert( newArtist, ArtistPtr::staticCast( artistPtr ) );
531
// add track to artist's tracklist
532
artistPtr->addTrack( track );
533
// set track's artist to the new artist
534
setArtist( artistPtr );
536
m_collection.data()->memoryCollection()->acquireWriteLock();
537
m_collection.data()->memoryCollection()->setArtistMap( artistMap );
538
m_collection.data()->memoryCollection()->releaseLock();
542
MediaDeviceTrack::setGenre( const QString &newGenre )
546
MediaDeviceGenrePtr genrePtr;
547
MediaDeviceTrackPtr track( this );
548
GenreMap genreMap = m_collection.data()->memoryCollection()->genreMap();
550
// do cleanup of soon to be previous genre
553
if ( !genrePtr.isNull() )
555
// remove track from previous genre's tracklist
556
genrePtr->remTrack( track );
557
// if genre's tracklist is empty, remove genre from genremap
558
if( genrePtr->tracks().isEmpty() )
559
genreMap.remove( genrePtr->name() );
562
// change to a new genre
564
// check for the existence of the genre to be set to,
565
// if genre exists, reuse, else create
567
if ( genreMap.contains( newGenre ) )
569
genrePtr = MediaDeviceGenrePtr::staticCast( genreMap.value( newGenre ) );
573
genrePtr = MediaDeviceGenrePtr( new MediaDeviceGenre( newGenre ) );
574
genreMap.insert( newGenre, GenrePtr::staticCast( genrePtr ) );
577
// add track to genre's tracklist
578
genrePtr->addTrack( track );
579
// set track's genre to the new genre
580
setGenre( genrePtr );
582
m_collection.data()->memoryCollection()->acquireWriteLock();
583
m_collection.data()->memoryCollection()->setGenreMap( genreMap );
584
m_collection.data()->memoryCollection()->releaseLock();
588
MediaDeviceTrack::setComposer( const QString &newComposer )
592
MediaDeviceComposerPtr composerPtr;
593
MediaDeviceTrackPtr track( this );
594
ComposerMap composerMap = m_collection.data()->memoryCollection()->composerMap();
596
// do cleanup of soon to be previous composer
598
composerPtr = m_composer;
599
if ( !composerPtr.isNull() )
601
// remove track from previous composer's tracklist
602
composerPtr->remTrack( track );
603
// if composer's tracklist is empty, remove composer from composermap
604
if( composerPtr->tracks().isEmpty() )
605
composerMap.remove( composerPtr->name() );
608
// change to a new composer
610
// check for the existence of the composer to be set to,
611
// if composer exists, reuse, else create
613
if ( composerMap.contains( newComposer ) )
615
composerPtr = MediaDeviceComposerPtr::staticCast( composerMap.value( newComposer ) );
619
composerPtr = MediaDeviceComposerPtr( new MediaDeviceComposer( newComposer ) );
620
composerMap.insert( newComposer, ComposerPtr::staticCast( composerPtr ) );
623
// add track to composer's tracklist
624
composerPtr->addTrack( track );
625
// set track's composer to the new composer
626
setComposer( composerPtr );
628
m_collection.data()->memoryCollection()->acquireWriteLock();
629
m_collection.data()->memoryCollection()->setComposerMap( composerMap );
630
m_collection.data()->memoryCollection()->releaseLock();
634
MediaDeviceTrack::setYear( int newYear )
638
MediaDeviceYearPtr yearPtr;
639
MediaDeviceTrackPtr track( this );
640
YearMap yearMap = m_collection.data()->memoryCollection()->yearMap();
642
// do cleanup of soon to be previous year
645
if ( !yearPtr.isNull() )
647
// remove track from previous year's tracklist
648
yearPtr->remTrack( track );
649
// if year's tracklist is empty, remove year from yearmap
650
if( yearPtr->tracks().isEmpty() )
651
yearMap.remove( yearPtr->year() );
654
// change to a new year
656
// check for the existence of the year to be set to,
657
// if year exists, reuse, else create
659
if ( yearMap.contains( newYear ) )
661
yearPtr = MediaDeviceYearPtr::staticCast( yearMap.value( newYear ) );
665
yearPtr = MediaDeviceYearPtr( new MediaDeviceYear( QString::number(newYear) ) );
666
yearMap.insert( newYear, YearPtr::staticCast( yearPtr ) );
669
// add track to year's tracklist
670
yearPtr->addTrack( track );
671
// set track's year to the new year
674
m_collection.data()->memoryCollection()->acquireWriteLock();
675
m_collection.data()->memoryCollection()->setYearMap( yearMap );
676
m_collection.data()->memoryCollection()->releaseLock();
680
MediaDeviceTrack::setAlbum( MediaDeviceAlbumPtr album )
686
MediaDeviceTrack::setArtist( MediaDeviceArtistPtr artist )
692
MediaDeviceTrack::setGenre( MediaDeviceGenrePtr genre )
698
MediaDeviceTrack::setComposer( MediaDeviceComposerPtr composer )
700
m_composer = composer;
704
MediaDeviceTrack::setYear( MediaDeviceYearPtr year )
710
MediaDeviceTrack::title() const
716
MediaDeviceTrack::setTitle( const QString &title )
722
MediaDeviceTrack::setLength( qint64 length )
728
MediaDeviceTrack::endMetaDataUpdate()
731
// Update info in local mediadevice database struct
732
debug() << "Observer number: " << m_observers.count();
738
MediaDeviceArtist::MediaDeviceArtist( const QString &name )
746
MediaDeviceArtist::~MediaDeviceArtist()
752
MediaDeviceArtist::name() const
758
MediaDeviceArtist::tracks()
764
MediaDeviceArtist::albums()
770
MediaDeviceArtist::addTrack( MediaDeviceTrackPtr track )
772
m_tracks.append( TrackPtr::staticCast( track ) );
776
MediaDeviceArtist::remTrack( MediaDeviceTrackPtr track )
778
m_tracks.removeOne( TrackPtr::staticCast( track ) );
782
MediaDeviceArtist::addAlbum( MediaDeviceAlbumPtr album )
784
m_albums.append( AlbumPtr::staticCast( album ) );
788
MediaDeviceArtist::remAlbum( MediaDeviceAlbumPtr album )
790
m_albums.removeOne( AlbumPtr::staticCast( album ) );
793
//---------------MediaDeviceAlbum-----------------------------------
795
MediaDeviceAlbum::MediaDeviceAlbum( Collections::MediaDeviceCollection *collection, const QString &name )
797
, m_collection( collection )
798
, m_artworkCapability( 0 )
801
, m_isCompilation( false )
802
, m_hasImage( true ) // assume it has a cover until proven otherwise
803
, m_hasImageChecked( false )
804
, m_image( QImage() )
807
MediaDeviceHandler *handler = m_collection->handler();
808
if( handler && handler->hasCapabilityInterface( Handler::Capability::Artwork ) )
809
m_artworkCapability = handler->create<Handler::ArtworkCapability>();
812
MediaDeviceAlbum::~MediaDeviceAlbum()
818
MediaDeviceAlbum::name() const
824
MediaDeviceAlbum::isCompilation() const
826
return m_isCompilation;
830
MediaDeviceAlbum::setIsCompilation( bool compilation )
832
m_isCompilation = compilation;
836
MediaDeviceAlbum::hasAlbumArtist() const
838
return !m_albumArtist.isNull();
842
MediaDeviceAlbum::albumArtist() const
844
return ArtistPtr::staticCast( m_albumArtist );
848
MediaDeviceAlbum::tracks()
854
MediaDeviceAlbum::hasImage( int size ) const
858
if( !m_hasImageChecked )
859
m_hasImage = ! const_cast<MediaDeviceAlbum*>( this )->image().isNull();
864
MediaDeviceAlbum::image( int size )
866
if( m_name.isEmpty() || !m_hasImage )
867
return Meta::Album::image( size );
869
if( !m_image.isNull() )
872
return QPixmap::fromImage(m_image);
873
return QPixmap::fromImage(m_image).scaled( QSize( size, size ), Qt::KeepAspectRatio );
875
if( m_artworkCapability )
877
MediaDeviceTrackPtr track = MediaDeviceTrackPtr::dynamicCast( m_tracks.first() );
878
QImage cover = m_artworkCapability->getCover( track );
880
if( !cover.isNull() )
885
return QPixmap::fromImage(cover);
886
return QPixmap::fromImage(cover.scaled( QSize( size, size ), Qt::KeepAspectRatio ));
890
m_hasImageChecked = true;
892
return Meta::Album::image( size );
896
MediaDeviceAlbum::canUpdateImage() const
898
if( m_artworkCapability )
899
return m_artworkCapability->canUpdateCover();
903
// TODO: forward setImage calls to handler
905
MediaDeviceAlbum::setImage( const QImage &image )
907
if( m_artworkCapability && m_artworkCapability->canUpdateCover() )
911
m_artworkCapability->setCover( MediaDeviceAlbumPtr( this ), image );
916
MediaDeviceAlbum::setImagePath( const QString &path )
918
if( m_artworkCapability && m_artworkCapability->canUpdateCover() )
921
m_artworkCapability->setCoverPath( MediaDeviceAlbumPtr( this ), path );
925
// TODO: forward call to handler to remove image, etc.
927
MediaDeviceAlbum::removeImage()
929
Meta::Album::removeImage();
933
MediaDeviceAlbum::hasCapabilityInterface( Capabilities::Capability::Type type ) const
937
case Capabilities::Capability::Actions:
944
Capabilities::Capability*
945
MediaDeviceAlbum::createCapabilityInterface( Capabilities::Capability::Type type )
949
case Capabilities::Capability::Actions:
951
QList<QAction*> actions;
952
if( canUpdateImage() )
954
QAction *separator = new QAction( m_collection );
955
QAction *displayCoverAction = new DisplayCoverAction( m_collection, AlbumPtr::dynamicCast( MediaDeviceAlbumPtr(this) ) );
956
QAction *unsetCoverAction = new UnsetCoverAction( m_collection, AlbumPtr::dynamicCast( MediaDeviceAlbumPtr(this) ) );
958
separator->setSeparator( true );
960
actions.append( separator );
961
actions.append( displayCoverAction );
962
actions.append( new FetchCoverAction( m_collection, AlbumPtr::staticCast( MediaDeviceAlbumPtr(this) ) ) );
963
actions.append( new SetCustomCoverAction( m_collection, AlbumPtr::staticCast( MediaDeviceAlbumPtr(this) ) ) );
966
displayCoverAction->setEnabled( false );
967
unsetCoverAction->setEnabled( false );
969
actions.append( unsetCoverAction );
971
return new Capabilities::ActionsCapability( actions );
980
MediaDeviceAlbum::addTrack( MediaDeviceTrackPtr track )
982
m_tracks.append( TrackPtr::staticCast( track ) );
986
MediaDeviceAlbum::remTrack( MediaDeviceTrackPtr track )
988
m_tracks.removeOne( TrackPtr::staticCast( track ) );
992
MediaDeviceAlbum::setAlbumArtist( MediaDeviceArtistPtr artist )
994
m_albumArtist = artist;
997
//MediaDeviceComposer
999
MediaDeviceComposer::MediaDeviceComposer( const QString &name )
1007
MediaDeviceComposer::~MediaDeviceComposer()
1013
MediaDeviceComposer::name() const
1019
MediaDeviceComposer::tracks()
1025
MediaDeviceComposer::addTrack( MediaDeviceTrackPtr track )
1027
m_tracks.append( TrackPtr::staticCast( track ) );
1031
MediaDeviceComposer::remTrack( MediaDeviceTrackPtr track )
1033
m_tracks.removeOne( TrackPtr::staticCast( track ) );
1036
//---------------MediaDeviceGenre-----------------------------------
1038
MediaDeviceGenre::MediaDeviceGenre( const QString &name )
1046
MediaDeviceGenre::~MediaDeviceGenre()
1052
MediaDeviceGenre::name() const
1058
MediaDeviceGenre::tracks()
1064
MediaDeviceGenre::addTrack( MediaDeviceTrackPtr track )
1066
m_tracks.append( TrackPtr::staticCast( track ) );
1070
MediaDeviceGenre::remTrack( MediaDeviceTrackPtr track )
1072
m_tracks.removeOne( TrackPtr::staticCast( track ) );
1078
MediaDeviceYear::MediaDeviceYear( const QString &name )
1086
MediaDeviceYear::~MediaDeviceYear()
1092
MediaDeviceYear::name() const
1098
MediaDeviceYear::tracks()
1104
MediaDeviceYear::addTrack( MediaDeviceTrackPtr track )
1106
m_tracks.append( TrackPtr::staticCast( track ) );
1110
MediaDeviceYear::remTrack( MediaDeviceTrackPtr track )
1112
m_tracks.removeOne( TrackPtr::staticCast( track ) );
1115
#include "mediadevicemeta.moc"