bool Dynamic::EchoNestBias::trackMatches( int position, const Meta::TrackList& playlist, int contextCount ) const { Q_UNUSED( contextCount ); // collect the artist QStringList artists = currentArtists( position, playlist ); if( artists.isEmpty() ) return true; // the artist of this track if( position < 0 || position >= playlist.count() ) return false; Meta::TrackPtr track = playlist[position]; Meta::ArtistPtr artist = track->artist(); if( !artist || artist->name().isEmpty() ) return false; { QMutexLocker locker( &m_mutex ); QString key = artists.join("|"); if( m_similarArtistMap.contains( key ) ) return m_similarArtistMap.value( key ).contains( artist->name() ); } warning() << "didn't have artist suggestions saved for this artist:" << artist->name(); return false; }
void TestAmazonMetaFactory::testCreateArtist() { QStringList list, list2; list << "id" << "name" << "description"; list2 << "23" << "name" << "description"; AmazonMetaFactory factory( "Amazontest" ); Meta::ArtistPtr artistPtr = factory.createArtist( list ); Meta::ArtistPtr artistPtr2 = factory.createArtist( list2 ); QVERIFY( artistPtr ); QVERIFY( artistPtr2 ); Meta::AmazonArtist* amazonArtist = dynamic_cast<Meta::AmazonArtist*>( artistPtr.data() ); Meta::AmazonArtist* amazonArtist2 = dynamic_cast<Meta::AmazonArtist*>( artistPtr2.data() ); QVERIFY( amazonArtist ); QVERIFY( amazonArtist2 ); QCOMPARE( amazonArtist->id(), 0 ); QCOMPARE( amazonArtist->name(), QString( "name" ) ); QCOMPARE( amazonArtist->description(), QString( "description" ) ); QCOMPARE( amazonArtist2->id(), 23 ); }
void TestSqlArtist::testSortableName() { Meta::ArtistPtr artistWithThe = m_collection->registry()->getArtist( 1 ); QCOMPARE( artistWithThe->sortableName(), QString( "Foo, The" ) ); Meta::ArtistPtr artistWithoutThe = m_collection->registry()->getArtist( 2 ); QCOMPARE( artistWithoutThe->sortableName(), QString( "No The Foo" ) ); }
bool Dynamic::LastFmBias::trackMatches( int position, const Meta::TrackList& playlist, int contextCount ) const { Q_UNUSED( contextCount ); if( position <= 0 || position >= playlist.count()) return false; // determine the last track and artist Meta::TrackPtr lastTrack = playlist[position-1]; Meta::ArtistPtr lastArtist = lastTrack->artist(); QString lastTrackName = lastTrack->name(); QString lastArtistName = lastArtist ? lastArtist->name() : QString(); Meta::TrackPtr currentTrack = playlist[position]; Meta::ArtistPtr currentArtist = currentTrack->artist(); QString currentTrackName = currentTrack->name(); QString currentArtistName = currentArtist ? currentArtist->name() : QString(); { QMutexLocker locker( &m_mutex ); if( m_match == SimilarArtist ) { if( lastArtistName.isEmpty() ) return true; if( currentArtistName.isEmpty() ) return false; if( lastArtistName == currentArtistName ) return true; if( m_similarArtistMap.contains( lastArtistName ) ) return m_similarArtistMap.value( lastArtistName ).contains( currentArtistName ); } else if( m_match == SimilarTrack ) { if( lastTrackName.isEmpty() ) return true; if( currentTrackName.isEmpty() ) return false; if( lastTrackName == currentTrackName ) return true; TitleArtistPair lastKey( lastTrackName, lastArtistName ); TitleArtistPair currentKey( currentTrackName, currentArtistName ); if( m_similarTrackMap.contains( lastKey ) ) return m_similarTrackMap.value( lastKey ).contains( currentKey ); } } debug() << "didn't have a cached suggestions for track:" << lastTrackName; return false; }
/** * called whenever metadata of the current track has changed */ void TabsEngine::update() { DEBUG_BLOCK // get the current track Meta::TrackPtr track = The::engineController()->currentTrack(); if( !track ) { debug() << "no track"; m_titleName.clear(); m_artistName.clear(); removeAllData( "tabs" ); setData( "tabs", "state", "Stopped" ); return; } m_currentTrack = track; Meta::ArtistPtr artistPtr = track->artist(); QString newArtist; if( artistPtr ) { if( ( track->playableUrl().protocol() == "lastfm" ) || ( track->playableUrl().protocol() == "daap" ) || !The::engineController()->isStream() ) newArtist = artistPtr->name(); else newArtist = artistPtr->prettyName(); } QString newTitle = track->name(); if( newTitle.isEmpty() ) newTitle = track->prettyName(); // check if something changed if( newTitle == m_titleName && newArtist == m_artistName ) { debug() << "nothing changed"; return; } // stop fetching for unknown artists or titles if( newTitle.isEmpty() || newArtist.isEmpty() ) { setData("tabs", "state", "noTabs" ); return; } requestTab( newArtist, newTitle ); }
void CurrentEngine::update( Meta::AlbumPtr album ) { if( !m_requested.value( QLatin1String("albums") ) ) return; DEBUG_BLOCK m_lastQueryMaker = 0; Meta::TrackPtr track = The::engineController()->currentTrack(); if( !album ) return; Meta::ArtistPtr artist = track->artist(); // Prefer track artist to album artist BUG: 266682 if( !artist ) artist = album->albumArtist(); if( artist && !artist->name().isEmpty() ) { m_albums.clear(); m_albumData.clear(); m_albumData[ QLatin1String("currentTrack") ] = qVariantFromValue( track ); m_albumData[ QLatin1String("headerText") ] = QVariant( i18n( "Albums by %1", artist->name() ) ); // -- search the collection for albums with the same artist Collections::QueryMaker *qm = CollectionManager::instance()->queryMaker(); qm->setAutoDelete( true ); qm->addFilter( Meta::valArtist, artist->name(), true, true ); qm->setAlbumQueryMode( Collections::QueryMaker::AllAlbums ); qm->setQueryType( Collections::QueryMaker::Album ); connect( qm, SIGNAL(newResultReady( Meta::AlbumList)), SLOT(resultReady( Meta::AlbumList)), Qt::QueuedConnection ); connect( qm, SIGNAL(queryDone()), SLOT(setupAlbumsData()) ); m_lastQueryMaker = qm; qm->run(); } else { removeAllData( QLatin1String("albums") ); setData( QLatin1String("albums"), QLatin1String("headerText"), i18nc( "Header text for current album applet", "Albums" ) ); } }
bool Dynamic::WeeklyTopBias::trackMatches( int position, const Meta::TrackList& playlist, int contextCount ) const { Q_UNUSED( contextCount ); if( position < 0 || position >= playlist.count()) return false; // - determine the current artist Meta::TrackPtr currentTrack = playlist[position-1]; Meta::ArtistPtr currentArtist = currentTrack->artist(); QString currentArtistName = currentArtist ? currentArtist->name() : QString(); // - collect all the artists QStringList artists; bool weeksMissing = false; uint fromTime = m_range.from.toTime_t(); uint toTime = m_range.to.toTime_t(); uint lastWeekTime = 0; foreach( uint weekTime, m_weeklyFromTimes ) { if( weekTime > fromTime && weekTime < toTime && lastWeekTime ) { if( m_weeklyArtistMap.contains( lastWeekTime ) ) { artists.append( m_weeklyArtistMap.value( lastWeekTime ) ); // debug() << "found already-saved data for week:" << lastWeekTime << m_weeklyArtistMap.value( lastWeekTime ); } else { weeksMissing = true; } } lastWeekTime = weekTime; } if( weeksMissing ) warning() << "didn't have a cached suggestions for weeks:" << m_range.from << "to" << m_range.to; return artists.contains( currentArtistName ); }
Dynamic::TrackSet Dynamic::LastFmBias::matchingTracks( const Meta::TrackList& playlist, int contextCount, int finalCount, Dynamic::TrackCollectionPtr universe ) const { Q_UNUSED( contextCount ); Q_UNUSED( finalCount ); if( playlist.isEmpty() ) return Dynamic::TrackSet( universe, true ); // determine the last track and artist Meta::TrackPtr lastTrack = playlist.last(); Meta::ArtistPtr lastArtist = lastTrack->artist(); m_currentTrack = lastTrack->name(); m_currentArtist = lastArtist ? lastArtist->name() : QString(); { QMutexLocker locker( &m_mutex ); if( m_match == SimilarArtist ) { if( m_currentArtist.isEmpty() ) return Dynamic::TrackSet( universe, true ); if( m_tracksMap.contains( m_currentArtist ) ) return m_tracksMap.value( m_currentArtist ); } else if( m_match == SimilarTrack ) { if( m_currentTrack.isEmpty() ) return Dynamic::TrackSet( universe, true ); QString key = m_currentTrack + '|' + m_currentArtist; if( m_tracksMap.contains( key ) ) return m_tracksMap.value( key ); } } m_tracks = Dynamic::TrackSet( universe, false ); QTimer::singleShot(0, const_cast<LastFmBias*>(this), SLOT(newQuery())); // create the new query from my parent thread return Dynamic::TrackSet(); }
void ScrobblerAdapter::copyTrackMetadata( lastfm::MutableTrack &to, const Meta::TrackPtr &track ) { to.setTitle( track->name() ); QString artistOrComposer; Meta::ComposerPtr composer = track->composer(); if( m_config->scrobbleComposer() && composer ) artistOrComposer = composer->name(); Meta::ArtistPtr artist = track->artist(); if( artistOrComposer.isEmpty() && artist ) artistOrComposer = artist->name(); to.setArtist( artistOrComposer ); Meta::AlbumPtr album = track->album(); Meta::ArtistPtr albumArtist; if( album ) { to.setAlbum( album->name() ); albumArtist = album->hasAlbumArtist() ? album->albumArtist() : Meta::ArtistPtr(); } if( albumArtist ) to.setAlbumArtist( albumArtist->name() ); to.setDuration( track->length() / 1000 ); if( track->trackNumber() >= 0 ) to.setTrackNumber( track->trackNumber() ); lastfm::Track::Source source = lastfm::Track::Player; if( track->type() == "stream/lastfm" ) source = lastfm::Track::LastFmRadio; else if( track->type().startsWith( "stream" ) ) source = lastfm::Track::NonPersonalisedBroadcast; else if( track->collection() && track->collection()->collectionId() != "localCollection" ) source = lastfm::Track::MediaDevice; to.setSource( source ); }
AmarokUrl NavigationUrlGenerator::urlFromArtist( Meta::ArtistPtr artist ) { DEBUG_BLOCK AmarokUrl url; QScopedPointer<Capabilities::BookmarkThisCapability> btc( artist->create<Capabilities::BookmarkThisCapability>() ); if( btc ) { if( btc->isBookmarkable() ) { QString artistName = artist->prettyName(); url.setCommand( "navigate" ); QString path = btc->browserName(); if ( !btc->collectionName().isEmpty() ) path += ( '/' + btc->collectionName() ); url.setPath( path ); //debug() << "Path: " << url.path(); QString filter; if ( btc->simpleFiltering() ) { //for services only supporting simple filtering, do not try to set the sorting mode filter = "\"" + artistName + "\""; } else { url.setArg( "levels", "artist-album" ); filter = ( "artist:\"" + artistName + "\"" ); } url.setArg( "filter", filter ); if ( !btc->collectionName().isEmpty() ) url.setName( i18n( "Artist \"%1\" from %2", artistName, btc->collectionName() ) ); else url.setName( i18n( "Artist \"%1\"", artistName ) ); } } return url; }
QString TrackOrganizer::buildDestination(const QString& format, const Meta::TrackPtr& track) const { // get hold of the shared pointers Meta::AlbumPtr album = track->album(); Meta::ArtistPtr artist = track->artist(); Meta::ComposerPtr composer = track->composer(); Meta::ArtistPtr albumArtist = album ? album->albumArtist() : Meta::ArtistPtr(); Meta::GenrePtr genre = track->genre(); Meta::YearPtr year = track->year(); bool isCompilation = album && album->isCompilation(); QMap<QString, QString> args; QString strArtist = artist ? artist->name() : QString(); QString strAlbumArtist = isCompilation ? i18n( "Various Artists" ) : ( albumArtist ? albumArtist->name() : strArtist ); args["theartist"] = strArtist; args["thealbumartist"] = strAlbumArtist; if( m_postfixThe ) { Amarok::manipulateThe( strArtist, true ); Amarok::manipulateThe( strAlbumArtist, true ); } if ( track->trackNumber() ) { QString trackNum = QString("%1").arg( track->trackNumber(), 2, 10, QChar('0') ); args["track"] = trackNum; } args["title"] = track->name(); args["artist"] = strArtist; args["composer"] = composer ? composer->name() : QString(); // if year == 0 then we don't want include it QString strYear = year ? year->name() : QString(); args["year"] = strYear.localeAwareCompare( "0" ) == 0 ? QString() : strYear; args["album"] = track->album() ? track->album()->name() : QString(); args["albumartist"] = strAlbumArtist; args["comment"] = track->comment(); args["genre"] = genre ? genre->name() : QString(); if( m_targetFileExtension.isEmpty() ) args["filetype"] = track->type(); else args["filetype"] = m_targetFileExtension; QString strFolder = QFileInfo( track->playableUrl().toLocalFile() ).path(); strFolder = strFolder.mid( commonPrefixLength( m_folderPrefix, strFolder ) ); args["folder"] = strFolder; args["initial"] = strAlbumArtist.mid( 0, 1 ).toUpper(); //artists starting with The are already handled above if( track->discNumber() ) args["discnumber"] = QString::number( track->discNumber() ); args["collectionroot"] = m_folderPrefix; // some additional properties not supported by organize dialog. args["rating"] = track->statistics()->rating(); args["filesize"] = track->filesize(); args["length"] = track->length() / 1000; // Fill up default empty values for StringX formater // TODO make this values changeable by user args["default_album"] = i18n( "Unknown album" ); args["default_albumartist"] = i18n( "Unknown artist" ); args["default_artist"] = args["albumartist"]; args["default_thealbumartist"] = args["albumartist"]; args["default_theartist"] = args["albumartist"]; args["default_comment"] = i18n( "No comments" ); args["default_composer"] = i18n( "Unknown composer" ); args["default_discnumber"] = i18n( "Unknown disc number" ); args["default_genre"] = i18n( "Unknown genre" ); args["default_title"] = i18n( "Unknown title" ); args["default_year"] = i18n( "Unknown year" ); foreach( const QString &key, args.keys() ) if( key != "collectionroot" && key != "folder" ) args[key] = args[key].replace( '/', '-' ); Amarok::QStringx formatx( format ); QString result = formatx.namedOptArgs( args ); return cleanPath( result ); }
ArtistItem( QTreeWidget *parent, Meta::ArtistPtr artist ) : QTreeWidgetItem( parent ) , m_artist( artist ) { setText( 0, artist->prettyName() ); }
void CurrentTrack::setupLayoutActions( Meta::TrackPtr track ) { if( !track ) return; PERF_LOG( "Begin actions layout setup" ); //first, add any global CurrentTrackActions (iow, actions that are shown for all tracks) QList<QAction *> actions = The::globalCurrentTrackActions()->actions(); using namespace Capabilities; QScopedPointer<ActionsCapability> ac( track->create<ActionsCapability>() ); if( ac ) { QList<QAction*> trackActions = ac->actions(); // ensure that the actions get deleted afterwards foreach( QAction* action, trackActions ) { if( !action->parent() ) action->setParent( this ); actions << action; } } QScopedPointer<BookmarkThisCapability> btc( track->create<BookmarkThisCapability>() ); if( btc && btc->bookmarkAction() ) { actions << btc->bookmarkAction(); } if( m_showEditTrackDetailsAction && track->editor() ) { QAction *editAction = new QAction( KIcon("media-track-edit-amarok"), i18n("Edit Track Details"), this ); connect( editAction, SIGNAL(triggered()), SLOT(editTrack()) ); m_customActions << editAction; } if( track->has<FindInSourceCapability>() ) { if( !m_findInSourceSignalMapper ) { m_findInSourceSignalMapper = new QSignalMapper( this ); connect( m_findInSourceSignalMapper, SIGNAL(mapped(QString)), SLOT(findInSource(QString)) ); } Meta::AlbumPtr album = track->album(); Meta::ArtistPtr artist = track->artist(); Meta::ComposerPtr composer = track->composer(); Meta::GenrePtr genre = track->genre(); Meta::YearPtr year = track->year(); QAction *act( 0 ); if( album && !album->name().isEmpty() ) { act = new QAction( KIcon("current-track-amarok"), i18n("Show Album in Media Sources"), this ); connect( act, SIGNAL(triggered()), m_findInSourceSignalMapper, SLOT(map()) ); m_findInSourceSignalMapper->setMapping( act, QLatin1String("album") ); m_customActions << act; } if( artist && !artist->name().isEmpty() ) { act = new QAction( KIcon("filename-artist-amarok"), i18n("Show Artist in Media Sources"), this ); connect( act, SIGNAL(triggered()), m_findInSourceSignalMapper, SLOT(map()) ); m_findInSourceSignalMapper->setMapping( act, QLatin1String("artist") ); m_customActions << act; KPluginInfo::List services = The::pluginManager()->plugins( QLatin1String("Service") ); foreach( const KPluginInfo &service, services ) { if( service.pluginName() == QLatin1String("amarok_service_amazonstore") ) { if( service.isPluginEnabled() ) { act = new QAction( KIcon("view-services-amazon-amarok"), i18n("Search for Artist in the MP3 Music Store"), this ); connect( act, SIGNAL(triggered()), this, SLOT(findInStore()) ); m_customActions << act; } break; } } } if( composer && !composer->name().isEmpty() && (composer->name() != i18n("Unknown Composer")) ) { act = new QAction( KIcon("filename-composer-amarok"), i18n("Show Composer in Media Sources"), this ); connect( act, SIGNAL(triggered()), m_findInSourceSignalMapper, SLOT(map()) ); m_findInSourceSignalMapper->setMapping( act, QLatin1String("composer") ); m_customActions << act; } if( genre && !genre->name().isEmpty() ) { act = new QAction( KIcon("filename-genre-amarok"), i18n("Show Genre in Media Sources"), this ); connect( act, SIGNAL(triggered()), m_findInSourceSignalMapper, SLOT(map()) ); m_findInSourceSignalMapper->setMapping( act, QLatin1String("genre") ); m_customActions << act; } if( year && !year->name().isEmpty() ) { act = new QAction( KIcon("filename-year-amarok"), i18n("Show Year in Media Sources"), this ); connect( act, SIGNAL(triggered()), m_findInSourceSignalMapper, SLOT(map()) ); m_findInSourceSignalMapper->setMapping( act, QLatin1String("year") ); m_customActions << act; } }
void addMockTrack( Collections::CollectionTestImpl *coll, const QString &trackName, const QString &artistName, const QString &albumName ) { Meta::MockTrack *track = new Meta::MockTrack(); ::testing::Mock::AllowLeak( track ); Meta::TrackPtr trackPtr( track ); EXPECT_CALL( *track, name() ).Times( AnyNumber() ).WillRepeatedly( Return( trackName ) ); EXPECT_CALL( *track, prettyName() ).Times( AnyNumber() ).WillRepeatedly( Return( trackName ) ); EXPECT_CALL( *track, uidUrl() ).Times( AnyNumber() ).WillRepeatedly( Return( trackName + '_' + artistName + '_' + albumName ) ); EXPECT_CALL( *track, playableUrl() ).Times( AnyNumber() ).WillRepeatedly( Return( KUrl( '/' + track->uidUrl() ) ) ); EXPECT_CALL( *track, composer() ).Times( AnyNumber() ).WillRepeatedly( Return( Meta::ComposerPtr() ) ); EXPECT_CALL( *track, genre() ).Times( AnyNumber() ).WillRepeatedly( Return( Meta::GenrePtr() ) ); EXPECT_CALL( *track, year() ).Times( AnyNumber() ).WillRepeatedly( Return( Meta::YearPtr() ) ); coll->mc->addTrack( trackPtr ); Meta::AlbumPtr albumPtr = coll->mc->albumMap().value( albumName, QString() /* no album artist */ ); Meta::MockAlbum *album; Meta::TrackList albumTracks; if( albumPtr ) { album = dynamic_cast<Meta::MockAlbum*>( albumPtr.data() ); if( !album ) { QFAIL( "expected a Meta::MockAlbum" ); return; } albumTracks = albumPtr->tracks(); } else { album = new Meta::MockAlbum(); ::testing::Mock::AllowLeak( album ); albumPtr = Meta::AlbumPtr( album ); EXPECT_CALL( *album, name() ).Times( AnyNumber() ).WillRepeatedly( Return( albumName ) ); EXPECT_CALL( *album, prettyName() ).Times( AnyNumber() ).WillRepeatedly( Return( albumName ) ); EXPECT_CALL( *album, hasAlbumArtist() ).Times( AnyNumber() ).WillRepeatedly( Return( false ) ); EXPECT_CALL( *album, isCompilation() ).Times( AnyNumber() ).WillRepeatedly( Return( false ) ); //inconsistent coll->mc->addAlbum( albumPtr ); } albumTracks << trackPtr; EXPECT_CALL( *album, tracks() ).Times( AnyNumber() ).WillRepeatedly( Return( albumTracks ) ); EXPECT_CALL( *track, album() ).Times( AnyNumber() ).WillRepeatedly( Return( albumPtr ) ); Meta::ArtistPtr artistPtr = coll->mc->artistMap().value( artistName ); Meta::MockArtist *artist; Meta::TrackList artistTracks; if( artistPtr ) { artist = dynamic_cast<Meta::MockArtist*>( artistPtr.data() ); if( !artist ) { QFAIL( "expected a Meta::MockArtist" ); return; } artistTracks = artistPtr->tracks(); } else { artist = new Meta::MockArtist(); ::testing::Mock::AllowLeak( artist ); artistPtr = Meta::ArtistPtr( artist ); EXPECT_CALL( *artist, name() ).Times( AnyNumber() ).WillRepeatedly( Return( artistName ) ); EXPECT_CALL( *artist, prettyName() ).Times( AnyNumber() ).WillRepeatedly( Return( artistName ) ); coll->mc->addArtist( artistPtr ); } artistTracks << trackPtr; EXPECT_CALL( *artist, tracks() ).Times( AnyNumber() ).WillRepeatedly( Return( artistTracks ) ); EXPECT_CALL( *track, artist() ).Times( AnyNumber() ).WillRepeatedly( Return( artistPtr ) ); EXPECT_CALL( *album, albumArtist() ).Times( AnyNumber() ).WillRepeatedly( Return( artistPtr ) ); }