Meta::TrackPtr SqlRegistry::getTrack( int urlId ) { QString query = "SELECT %1 FROM urls %2 " "WHERE urls.id = %3"; query = query.arg( Meta::SqlTrack::getTrackReturnValues(), Meta::SqlTrack::getTrackJoinConditions(), QString::number( urlId ) ); QStringList rowData = m_collection->sqlStorage()->query( query ); if( rowData.isEmpty() ) return Meta::TrackPtr(); TrackPath id( rowData[Meta::SqlTrack::returnIndex_urlDeviceId].toInt(), rowData[Meta::SqlTrack::returnIndex_urlRPath] ); QString uid = rowData[Meta::SqlTrack::returnIndex_urlUid]; QMutexLocker locker( &m_trackMutex ); if( m_trackMap.contains( id ) ) { Meta::SqlTrackPtr track = Meta::SqlTrackPtr::staticCast( m_trackMap[ id ] ); // yes, it may happen that we get a different track in corner cases, see bug 323156 if( track->urlId() == urlId ) return Meta::TrackPtr::staticCast( track ); warning() << Q_FUNC_INFO << "track with (deviceId, rpath)" << id << "found in" << "m_trackMap, but it had different urlId (" << track->urlId() << ")" << "than requested (" << urlId << "). This may happen in corner-cases."; } if( m_uidMap.contains( uid ) ) { Meta::SqlTrackPtr track = Meta::SqlTrackPtr::staticCast( m_uidMap[ uid ] ); // yes, it may happen that we get a different track in corner cases, see bug 323156 if( track->urlId() == urlId ) return Meta::TrackPtr::staticCast( track ); warning() << Q_FUNC_INFO << "track with uid" << uid << "found in m_uidMap, but it" << "had different urlId (" << track->urlId() << ") than requested (" << urlId << "). This may happen in corner-cases."; } Meta::SqlTrack *sqlTrack = new Meta::SqlTrack( m_collection, rowData ); Meta::TrackPtr trackPtr( sqlTrack ); m_trackMap.insert( id, trackPtr ); m_uidMap.insert( sqlTrack->uidUrl(), trackPtr ); return trackPtr; }
void SqlScanResultProcessor::commitTrack( CollectionScanner::Track *track, CollectionScanner::Album *srcAlbum ) { // debug() << "commitTrack on"<<track->title()<< "album"<<srcAlbum->name() << "dir:" << track->directory()->path()<<track->directory(); Q_ASSERT( track ); Q_ASSERT( srcAlbum ); Q_ASSERT( m_directoryIds.contains( track->directory() ) ); int directoryId = m_directoryIds.value( track->directory() ); Q_ASSERT( m_albumIds.contains( srcAlbum ) ); int albumId = m_albumIds.value( srcAlbum ); QString uid = track->uniqueid(); if( uid.isEmpty() ) { warning() << "commitTrack(): got track with empty unique id from the scanner," << "not adding it"; m_messages.append( QString( "Not adding track %1 because it has no unique id." ). arg(track->path()) ); return; } uid = m_collection->generateUidUrl( uid ); int deviceId = m_collection->mountPointManager()->getIdForUrl( track->path() ); QString rpath = m_collection->mountPointManager()->getRelativePath( deviceId, track->path() ); if( m_foundTracks.contains( uid ) ) { const UrlEntry old = m_urlsCache.value( m_uidCache.value( uid ) ); const char *pattern = I18N_NOOP( "Duplicates found, the second file will be ignored:\n%1\n%2" ); // we want translated version for GUI and non-translated for debug log warning() << "commitTrack():" << QString( pattern ).arg( old.path, track->path() ); m_messages.append( i18n( pattern, old.path, track->path() ) ); return; } Meta::SqlTrackPtr metaTrack; UrlEntry entry; // find an existing track by uid if( m_uidCache.contains( uid ) ) { // uid is sadly not unique. Try to find the best url id. int urlId = findBestUrlId( uid, track->path() ); Q_ASSERT( urlId > 0 ); Q_ASSERT( m_urlsCache.contains( urlId ) ); entry = m_urlsCache.value( urlId ); entry.path = track->path(); entry.directoryId = directoryId; metaTrack = Meta::SqlTrackPtr::staticCast( m_collection->registry()->getTrack( urlId ) ); Q_ASSERT( metaTrack->urlId() == entry.id ); } // find an existing track by path else if( m_pathCache.contains( track->path() ) ) { int urlId = m_pathCache.value( track->path() ); Q_ASSERT( m_urlsCache.contains( urlId ) ); entry = m_urlsCache.value( urlId ); entry.uid = uid; entry.directoryId = directoryId; metaTrack = Meta::SqlTrackPtr::staticCast( m_collection->registry()->getTrack( urlId ) ); Q_ASSERT( metaTrack->urlId() == entry.id ); } // create a new one else { static int autoDecrementId = -1; entry.id = autoDecrementId--; entry.path = track->path(); entry.uid = uid; entry.directoryId = directoryId; metaTrack = Meta::SqlTrackPtr::staticCast( m_collection->getTrack( deviceId, rpath, directoryId, uid ) ); } if( !metaTrack ) { QString text = QString( "Something went wrong when importing track %1, metaTrack " "is null while it shouldn't be." ).arg( track->path() ); warning() << "commitTrack():" << text.toLocal8Bit().data(); m_messages.append( text ); return; } urlsCacheInsert( entry ); // removes the previous entry (by id) first if necessary m_foundTracks.insert( uid, entry.id ); // TODO: we need to check the modified date of the file agains the last updated of the file // to figure out if the track information was updated from outside Amarok. // In such a case we would fully reread all the information as if in a FullScan // -- set the values metaTrack->setWriteFile( false ); // no need to write the tags back metaTrack->beginUpdate(); metaTrack->setUidUrl( uid ); metaTrack->setUrl( deviceId, rpath, directoryId ); if( m_type == GenericScanManager::FullScan || !track->title().isEmpty() ) metaTrack->setTitle( track->title() ); if( m_type == GenericScanManager::FullScan || albumId != -1 ) metaTrack->setAlbum( albumId ); if( m_type == GenericScanManager::FullScan || !track->artist().isEmpty() ) metaTrack->setArtist( track->artist() ); if( m_type == GenericScanManager::FullScan || !track->composer().isEmpty() ) metaTrack->setComposer( track->composer() ); if( m_type == GenericScanManager::FullScan || track->year() >= 0 ) metaTrack->setYear( (track->year() >= 0) ? track->year() : 0 ); if( m_type == GenericScanManager::FullScan || !track->genre().isEmpty() ) metaTrack->setGenre( track->genre() ); metaTrack->setType( track->filetype() ); if( m_type == GenericScanManager::FullScan || track->bpm() >= 0 ) metaTrack->setBpm( track->bpm() ); if( m_type == GenericScanManager::FullScan || !track->comment().isEmpty() ) metaTrack->setComment( track->comment() ); if( (m_type == GenericScanManager::FullScan || metaTrack->score() == 0) && track->score() >= 0 ) metaTrack->setScore( track->score() ); if( (m_type == GenericScanManager::FullScan || metaTrack->rating() == 0.0) && track->rating() >= 0 ) metaTrack->setRating( track->rating() ); if( (m_type == GenericScanManager::FullScan || metaTrack->length() == 0) && track->length() >= 0 ) metaTrack->setLength( track->length() ); // the filesize is updated every time after the // file is changed. Doesn't make sense to set it. if( (m_type == GenericScanManager::FullScan || !metaTrack->modifyDate().isValid()) && track->modified().isValid() ) metaTrack->setModifyDate( track->modified() ); if( (m_type == GenericScanManager::FullScan || metaTrack->sampleRate() == 0) && track->samplerate() >= 0 ) metaTrack->setSampleRate( track->samplerate() ); if( (m_type == GenericScanManager::FullScan || metaTrack->bitrate() == 0) && track->bitrate() >= 0 ) metaTrack->setBitrate( track->bitrate() ); if( (m_type == GenericScanManager::FullScan || metaTrack->trackNumber() == 0) && track->track() >= 0 ) metaTrack->setTrackNumber( track->track() ); if( (m_type == GenericScanManager::FullScan || metaTrack->discNumber() == 0) && track->disc() >= 0 ) metaTrack->setDiscNumber( track->disc() ); if( m_type == GenericScanManager::FullScan && track->playcount() >= metaTrack->playCount() ) metaTrack->setPlayCount( track->playcount() ); Meta::ReplayGainTag modes[] = { Meta::ReplayGain_Track_Gain, Meta::ReplayGain_Track_Peak, Meta::ReplayGain_Album_Gain, Meta::ReplayGain_Album_Peak }; for( int i=0; i<4; i++ ) { if( track->replayGain( modes[i] ) != 0.0 ) metaTrack->setReplayGain( modes[i], track->replayGain( modes[i] ) ); } metaTrack->endUpdate(); metaTrack->setWriteFile( true ); }