void BaseTrackCache::getTrackValueForColumn(TrackPointer pTrack, int column, QVariant& trackValue) const { if (!pTrack || column < 0) { return; } // TODO(XXX) Qt properties could really help here. // TODO(rryan) this is all TrackDAO specific. What about iTunes/RB/etc.? if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_ARTIST) == column) { trackValue.setValue(pTrack->getArtist()); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_TITLE) == column) { trackValue.setValue(pTrack->getTitle()); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_ALBUM) == column) { trackValue.setValue(pTrack->getAlbum()); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_ALBUMARTIST) == column) { trackValue.setValue(pTrack->getAlbumArtist()); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_YEAR) == column) { trackValue.setValue(pTrack->getYear()); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_DATETIMEADDED) == column) { trackValue.setValue(pTrack->getDateAdded()); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_GENRE) == column) { trackValue.setValue(pTrack->getGenre()); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COMPOSER) == column) { trackValue.setValue(pTrack->getComposer()); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_GROUPING) == column) { trackValue.setValue(pTrack->getGrouping()); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_FILETYPE) == column) { trackValue.setValue(pTrack->getType()); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_TRACKNUMBER) == column) { trackValue.setValue(pTrack->getTrackNumber()); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_LOCATION) == column) { trackValue.setValue(QDir::toNativeSeparators(pTrack->getLocation())); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COMMENT) == column) { trackValue.setValue(pTrack->getComment()); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_DURATION) == column) { trackValue.setValue(pTrack->getDuration()); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_BITRATE) == column) { trackValue.setValue(pTrack->getBitrate()); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_BPM) == column) { trackValue.setValue(pTrack->getBpm()); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_REPLAYGAIN) == column) { trackValue.setValue(pTrack->getReplayGain().getRatio()); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_PLAYED) == column) { trackValue.setValue(pTrack->getPlayCounter().isPlayed()); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_TIMESPLAYED) == column) { trackValue.setValue(pTrack->getPlayCounter().getTimesPlayed()); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_RATING) == column) { trackValue.setValue(pTrack->getRating()); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_KEY) == column) { trackValue.setValue(pTrack->getKeyText()); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_KEY_ID) == column) { trackValue.setValue(static_cast<int>(pTrack->getKey())); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_BPM_LOCK) == column) { trackValue.setValue(pTrack->isBpmLocked()); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COVERART_LOCATION) == column) { trackValue.setValue(pTrack->getCoverInfo().coverLocation); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COVERART_HASH) == column || fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COVERART) == column) { // For sorting, we give COLUMN_LIBRARYTABLE_COVERART the same value as // the cover hash. trackValue.setValue(pTrack->getCoverHash()); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COVERART_SOURCE) == column) { trackValue.setValue(static_cast<int>(pTrack->getCoverInfo().source)); } else if (fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COVERART_TYPE) == column) { trackValue.setValue(static_cast<int>(pTrack->getCoverInfo().type)); } }
void AnalyzerBeats::finalize(TrackPointer tio) { if (m_pVamp == NULL) { return; } // Call End() here, because the number of total samples may have been // estimated incorrectly. bool success = m_pVamp->End(); qDebug() << "Beat Calculation" << (success ? "complete" : "failed"); QVector<double> beats = m_pVamp->GetInitFramesVector(); delete m_pVamp; m_pVamp = NULL; if (beats.isEmpty()) { qDebug() << "Could not detect beat positions from Vamp."; return; } QHash<QString, QString> extraVersionInfo = getExtraVersionInfo( m_pluginId, m_bPreferencesFastAnalysis); BeatsPointer pBeats = BeatFactory::makePreferredBeats( *tio, beats, extraVersionInfo, m_bPreferencesFixedTempo, m_bPreferencesOffsetCorrection, m_iSampleRate, m_iTotalSamples, m_iMinBpm, m_iMaxBpm); BeatsPointer pCurrentBeats = tio->getBeats(); // If the track has no beats object then set our newly generated one // regardless of beat lock. if (!pCurrentBeats) { tio->setBeats(pBeats); return; } // If the track received the beat lock while we were analyzing it then we // abort setting it. if (tio->isBpmLocked()) { qDebug() << "Track was BPM-locked as we were analyzing it. Aborting analysis."; return; } // If the user prefers to replace old beatgrids with newly generated ones or // the old beatgrid has 0-bpm then we replace it. bool zeroCurrentBpm = pCurrentBeats->getBpm() == 0.0; if (m_bPreferencesReanalyzeOldBpm || zeroCurrentBpm) { if (zeroCurrentBpm) { qDebug() << "Replacing 0-BPM beatgrid with a" << pBeats->getBpm() << "beatgrid."; } tio->setBeats(pBeats); return; } // If we got here then the user doesn't want to replace the beatgrid but // since the first beat is zero we'll apply the offset we just detected. double currentFirstBeat = pCurrentBeats->findNextBeat(0); double newFirstBeat = pBeats->findNextBeat(0); if (currentFirstBeat == 0.0 && newFirstBeat > 0) { pCurrentBeats->translate(newFirstBeat); } }
bool AnalyzerBeats::initialize(TrackPointer tio, int sampleRate, int totalSamples) { if (totalSamples == 0) { return false; } bool bPreferencesBeatDetectionEnabled = m_pConfig->getValue<bool>( ConfigKey(BPM_CONFIG_KEY, BPM_DETECTION_ENABLED)); if (!bPreferencesBeatDetectionEnabled) { qDebug() << "Beat calculation is deactivated"; return false; } bool bpmLock = tio->isBpmLocked(); if (bpmLock) { qDebug() << "Track is BpmLocked: Beat calculation will not start"; return false; } bool allow_above = m_pConfig->getValue<bool>( ConfigKey(BPM_CONFIG_KEY, BPM_ABOVE_RANGE_ENABLED)); if (allow_above) { m_iMinBpm = 0; m_iMaxBpm = 9999; } else { m_iMinBpm = m_pConfig->getValueString(ConfigKey(BPM_CONFIG_KEY, BPM_RANGE_START)).toInt(); m_iMaxBpm = m_pConfig->getValueString(ConfigKey(BPM_CONFIG_KEY, BPM_RANGE_END)).toInt(); } m_bPreferencesFixedTempo = m_pConfig->getValue<bool>( ConfigKey(BPM_CONFIG_KEY, BPM_FIXED_TEMPO_ASSUMPTION)); m_bPreferencesOffsetCorrection = m_pConfig->getValue<bool>( ConfigKey(BPM_CONFIG_KEY, BPM_FIXED_TEMPO_OFFSET_CORRECTION)); m_bPreferencesReanalyzeOldBpm = m_pConfig->getValue<bool>( ConfigKey(BPM_CONFIG_KEY, BPM_REANALYZE_WHEN_SETTINGS_CHANGE)); m_bPreferencesFastAnalysis = m_pConfig->getValue<bool>( ConfigKey(BPM_CONFIG_KEY, BPM_FAST_ANALYSIS_ENABLED)); QString library = m_pConfig->getValueString( ConfigKey(VAMP_CONFIG_KEY, VAMP_ANALYZER_BEAT_LIBRARY)); QString pluginID = m_pConfig->getValueString( ConfigKey(VAMP_CONFIG_KEY, VAMP_ANALYZER_BEAT_PLUGIN_ID)); m_pluginId = pluginID; m_iSampleRate = sampleRate; m_iTotalSamples = totalSamples; // if we can load a stored track don't reanalyze it bool bShouldAnalyze = !isDisabledOrLoadStoredSuccess(tio); if (bShouldAnalyze) { m_pVamp = new VampAnalyzer(); bShouldAnalyze = m_pVamp->Init(library, pluginID, m_iSampleRate, totalSamples, m_bPreferencesFastAnalysis); if (!bShouldAnalyze) { delete m_pVamp; m_pVamp = NULL; } } if (bShouldAnalyze) { qDebug() << "Beat calculation started with plugin" << pluginID; } else { qDebug() << "Beat calculation will not start"; } return bShouldAnalyze; }
bool AnalyzerBeats::isDisabledOrLoadStoredSuccess(TrackPointer tio) const { int iMinBpm; int iMaxBpm; bool allow_above = m_pConfig->getValue<bool>( ConfigKey(BPM_CONFIG_KEY, BPM_ABOVE_RANGE_ENABLED)); if (allow_above) { iMinBpm = 0; iMaxBpm = 9999; } else { iMinBpm = m_pConfig->getValueString(ConfigKey(BPM_CONFIG_KEY, BPM_RANGE_START)).toInt(); iMaxBpm = m_pConfig->getValueString(ConfigKey(BPM_CONFIG_KEY, BPM_RANGE_END)).toInt(); } bool bpmLock = tio->isBpmLocked(); if (bpmLock) { qDebug() << "Track is BpmLocked: Beat calculation will not start"; return true; } QString library = m_pConfig->getValueString( ConfigKey(VAMP_CONFIG_KEY, VAMP_ANALYZER_BEAT_LIBRARY)); QString pluginID = m_pConfig->getValueString( ConfigKey(VAMP_CONFIG_KEY, VAMP_ANALYZER_BEAT_PLUGIN_ID)); // At first start config for QM and Vamp does not exist --> set default // TODO(XXX): This is no longer present in initialize. Remove? if (library.isEmpty() || library.isNull()) library = "libmixxxminimal"; if (pluginID.isEmpty() || pluginID.isNull()) pluginID = "qm-tempotracker:0"; // If the track already has a Beats object then we need to decide whether to // analyze this track or not. BeatsPointer pBeats = tio->getBeats(); if (pBeats) { QString version = pBeats->getVersion(); QString subVersion = pBeats->getSubVersion(); QHash<QString, QString> extraVersionInfo = getExtraVersionInfo( pluginID, m_bPreferencesFastAnalysis); QString newVersion = BeatFactory::getPreferredVersion( m_bPreferencesOffsetCorrection); QString newSubVersion = BeatFactory::getPreferredSubVersion( m_bPreferencesFixedTempo, m_bPreferencesOffsetCorrection, iMinBpm, iMaxBpm, extraVersionInfo); if (version == newVersion && subVersion == newSubVersion) { // If the version and settings have not changed then if the world is // sane, re-analyzing will do nothing. return true; } else if (m_bPreferencesReanalyzeOldBpm) { return false; } else if (pBeats->getBpm() == 0.0) { qDebug() << "BPM is 0 for track so re-analyzing despite preference settings."; return false; } else if (pBeats->findNextBeat(0) <= 0.0) { qDebug() << "First beat is 0 for grid so analyzing track to find first beat."; return false; } else { qDebug() << "Beat calculation skips analyzing because the track has" << "a BPM computed by a previous Mixxx version and user" << "preferences indicate we should not change it."; return true; } } else { // If we got here, we want to analyze this track. return false; } }