//Other constructor SoundSourceProxy::SoundSourceProxy(TrackPointer pTrack) : m_pTrack(pTrack) , m_pSecurityToken( openSecurityToken(pTrack->getLocation(), pTrack->getSecurityToken())) , m_pSoundSource(initialize(pTrack->getLocation())) { }
//Other constructor SoundSourceProxy::SoundSourceProxy(TrackPointer pTrack) : SoundSource(pTrack->getLocation()), m_pSoundSource(NULL) { m_pSoundSource = initialize(pTrack->getLocation()); m_pTrack = pTrack; }
void AutoDJFeature::slotAddRandomTrack(bool) { int failedRetrieveAttempts = 0; // Get access to the auto-DJ playlist PlaylistDAO& playlistDao = m_pTrackCollection->getPlaylistDAO(); if (m_iAutoDJPlaylistId >= 0) { while (failedRetrieveAttempts < kMaxRetrieveAttempts) { // Get the ID of a randomly-selected track. TrackId trackId(m_autoDjCratesDao.getRandomTrackId()); if (trackId.isValid()) { // Get Track Information TrackPointer addedTrack = (m_pTrackCollection->getTrackDAO()).getTrack(trackId); if(addedTrack->exists()) { playlistDao.appendTrackToPlaylist(trackId, m_iAutoDJPlaylistId); m_pAutoDJView->onShow(); return; } else { qDebug() << "Track does not exist:" << addedTrack->getInfo() << addedTrack->getLocation(); } } failedRetrieveAttempts += 1; } // If we couldn't get a track from the crates , get one from the library qDebug () << "Could not load tracks from crates, attempting to load from library."; failedRetrieveAttempts = 0; while ( failedRetrieveAttempts < kMaxRetrieveAttempts ) { TrackId trackId(m_autoDjCratesDao.getRandomTrackIdFromLibrary(m_iAutoDJPlaylistId)); if (trackId.isValid()) { TrackPointer addedTrack = m_pTrackCollection->getTrackDAO().getTrack(trackId); if(addedTrack->exists()) { if(!addedTrack->getPlayCounter().isPlayed()) { playlistDao.appendTrackToPlaylist(trackId, m_iAutoDJPlaylistId); m_pAutoDJView->onShow(); return; } } else { qDebug() << "Track does not exist:" << addedTrack->getInfo() << addedTrack->getLocation(); } } failedRetrieveAttempts += 1; } } // If control reaches here it implies that we couldn't load track qDebug() << "Could not load random track."; }
void BaseExternalTrackModel::trackLoaded(QString group, TrackPointer pTrack) { if (group == m_previewDeckGroup) { // If there was a previously loaded track, refresh its rows so the // preview state will update. if (m_previewDeckTrackId.isValid()) { const int numColumns = columnCount(); QLinkedList<int> rows = getTrackRows(m_previewDeckTrackId); m_previewDeckTrackId = TrackId(); // invalidate foreach (int row, rows) { QModelIndex left = index(row, 0); QModelIndex right = index(row, numColumns); emit(dataChanged(left, right)); } } if (pTrack) { // The external table has foreign Track IDs, so we need to compare // by location for (int row = 0; row < rowCount(); ++row) { QString location = index(row, fieldIndex("location")).data().toString(); if (location == pTrack->getLocation()) { m_previewDeckTrackId = TrackId(index(row, 0).data()); //qDebug() << "foreign track id" << m_previewDeckTrackId; break; } } } }
void CoverArtCache::guessCover(TrackPointer pTrack) { if (pTrack) { kLogger.debug() << "Guessing cover art for" << pTrack->getLocation(); CoverInfo cover = CoverArtUtils::guessCoverInfo(*pTrack); pTrack->setCoverInfo(cover); } }
void DlgTrackInfo::populateFields(TrackPointer pTrack) { setWindowTitle(pTrack->getTitle()); // Editable fields txtTrackName->setText(pTrack->getTitle()); txtArtist->setText(pTrack->getArtist()); txtAlbum->setText(pTrack->getAlbum()); txtAlbumArtist->setText(pTrack->getAlbumArtist()); txtGenre->setText(pTrack->getGenre()); txtComposer->setText(pTrack->getComposer()); txtGrouping->setText(pTrack->getGrouping()); txtYear->setText(pTrack->getYear()); txtTrackNumber->setText(pTrack->getTrackNumber()); txtComment->setText(pTrack->getComment()); spinBpm->setValue(pTrack->getBpm()); // Non-editable fields txtDuration->setText(pTrack->getDurationStr()); txtFilepath->setText(pTrack->getFilename()); txtLocation->setText(pTrack->getLocation()); txtType->setText(pTrack->getType()); txtBitrate->setText(QString(pTrack->getBitrateStr()) + (" ") + tr("kbps")); txtBpm->setText(pTrack->getBpmStr()); txtKey->setText(pTrack->getKeyText()); BeatsPointer pBeats = pTrack->getBeats(); bool beatsSupportsSet = !pBeats || (pBeats->getCapabilities() & Beats::BEATSCAP_SET); bool enableBpmEditing = !pTrack->hasBpmLock() && beatsSupportsSet; spinBpm->setEnabled(enableBpmEditing); bpmTap->setEnabled(enableBpmEditing); bpmDouble->setEnabled(enableBpmEditing); bpmHalve->setEnabled(enableBpmEditing); bpmTwoThirds->setEnabled(enableBpmEditing); bpmThreeFourth->setEnabled(enableBpmEditing); }
void CachingReaderWorker::loadTrack(const TrackPointer& pTrack) { //qDebug() << m_group << "CachingReaderWorker::loadTrack() lock acquired for load."; // Emit that a new track is loading, stops the current track emit(trackLoading()); ReaderStatusUpdate status; status.status = TRACK_NOT_LOADED; QString filename = pTrack->getLocation(); if (filename.isEmpty() || !pTrack->exists()) { // Must unlock before emitting to avoid deadlock qDebug() << m_group << "CachingReaderWorker::loadTrack() load failed for\"" << filename << "\", unlocked reader lock"; m_pReaderStatusFIFO->writeBlocking(&status, 1); emit(trackLoadFailed( pTrack, QString("The file '%1' could not be found.").arg(filename))); return; } Mixxx::AudioSourceConfig audioSrcCfg; audioSrcCfg.setChannelCount(CachingReaderChunk::kChannels); m_pAudioSource = openAudioSourceForReading(pTrack, audioSrcCfg); if (m_pAudioSource.isNull()) { m_maxReadableFrameIndex = Mixxx::AudioSource::getMinFrameIndex(); // Must unlock before emitting to avoid deadlock qDebug() << m_group << "CachingReaderWorker::loadTrack() load failed for\"" << filename << "\", file invalid, unlocked reader lock"; m_pReaderStatusFIFO->writeBlocking(&status, 1); emit(trackLoadFailed( pTrack, QString("The file '%1' could not be loaded.").arg(filename))); return; } // Initially assume that the complete content offered by audio source // is available for reading. Later if read errors occur this value will // be decreased to avoid repeated reading of corrupt audio data. m_maxReadableFrameIndex = m_pAudioSource->getMaxFrameIndex(); status.maxReadableFrameIndex = m_maxReadableFrameIndex; status.status = TRACK_LOADED; m_pReaderStatusFIFO->writeBlocking(&status, 1); // Clear the chunks to read list. CachingReaderChunkReadRequest request; while (m_pChunkReadRequestFIFO->read(&request, 1) == 1) { qDebug() << "Skipping read request for " << request.chunk->getIndex(); status.status = CHUNK_READ_INVALID; status.chunk = request.chunk; m_pReaderStatusFIFO->writeBlocking(&status, 1); } // Emit that the track is loaded. const SINT sampleCount = CachingReaderChunk::frames2samples( m_pAudioSource->getFrameCount()); emit(trackLoaded(pTrack, m_pAudioSource->getSamplingRate(), sampleCount)); }
void TrackExportWorker::exportTrack(TrackPointer track) { QString sourceFilename = track->getLocation(); auto source_fileinfo = track->getFileInfo(); const QString dest_filename = QDir(m_destDir).filePath( source_fileinfo.fileName()); QFileInfo dest_fileinfo(dest_filename); if (dest_fileinfo.exists()) { switch (m_overwriteMode) { // Give the user the option to overwrite existing files in the destination. case OverwriteMode::ASK: switch (makeOverwriteRequest(dest_filename)) { case OverwriteAnswer::SKIP: case OverwriteAnswer::SKIP_ALL: qDebug() << "skipping" << sourceFilename; return; case OverwriteAnswer::OVERWRITE: case OverwriteAnswer::OVERWRITE_ALL: break; case OverwriteAnswer::CANCEL: m_errorMessage = tr("Export process was canceled"); stop(); return; } break; case OverwriteMode::SKIP_ALL: qDebug() << "skipping" << sourceFilename; return; case OverwriteMode::OVERWRITE_ALL:; } // Remove the existing file in preparation for overwriting. QFile dest_file(dest_filename); qDebug() << "Removing existing file" << dest_filename; if (!dest_file.remove()) { const QString error_message = tr( "Error removing file %1: %2. Stopping.").arg( dest_filename, dest_file.errorString()); qWarning() << error_message; m_errorMessage = error_message; stop(); return; } } qDebug() << "Copying" << sourceFilename << "to" << dest_filename; QFile source_file(sourceFilename); if (!source_file.copy(dest_filename)) { const QString error_message = tr( "Error exporting track %1 to %2: %3. Stopping.").arg( sourceFilename, dest_filename, source_file.errorString()); qWarning() << error_message; m_errorMessage = error_message; stop(); return; } }
void BaseTrackPlayer::slotLoadFailed(TrackPointer track, QString reason) { if (track != NULL) { qDebug() << "Failed to load track" << track->getLocation() << reason; emit(loadTrackFailed(track)); } else { qDebug() << "Failed to load track (NULL track object)" << reason; } // Alert user. QMessageBox::warning(NULL, tr("Couldn't load track."), reason); }
void CachingReaderWorker::loadTrack(const TrackPointer& pTrack) { //qDebug() << m_group << "CachingReaderWorker::loadTrack() lock acquired for load."; // Emit that a new track is loading, stops the current track emit(trackLoading()); ReaderStatusUpdate status; status.status = TRACK_NOT_LOADED; status.chunk = NULL; status.trackFrameCount = 0; QString filename = pTrack->getLocation(); if (filename.isEmpty() || !pTrack->exists()) { // Must unlock before emitting to avoid deadlock qDebug() << m_group << "CachingReaderWorker::loadTrack() load failed for\"" << filename << "\", unlocked reader lock"; m_pReaderStatusFIFO->writeBlocking(&status, 1); emit(trackLoadFailed( pTrack, QString("The file '%1' could not be found.").arg(filename))); return; } Mixxx::AudioSourceConfig audioSrcCfg; audioSrcCfg.channelCountHint = kChunkChannels; m_pAudioSource = openAudioSourceForReading(pTrack, audioSrcCfg); if (m_pAudioSource.isNull()) { // Must unlock before emitting to avoid deadlock qDebug() << m_group << "CachingReaderWorker::loadTrack() load failed for\"" << filename << "\", file invalid, unlocked reader lock"; m_pReaderStatusFIFO->writeBlocking(&status, 1); emit(trackLoadFailed( pTrack, QString("The file '%1' could not be loaded.").arg(filename))); return; } status.trackFrameCount = m_pAudioSource->getFrameCount(); status.status = TRACK_LOADED; m_pReaderStatusFIFO->writeBlocking(&status, 1); // Clear the chunks to read list. ChunkReadRequest request; while (m_pChunkReadRequestFIFO->read(&request, 1) == 1) { qDebug() << "Skipping read request for " << request.chunk->chunk_number; status.status = CHUNK_READ_INVALID; status.chunk = request.chunk; m_pReaderStatusFIFO->writeBlocking(&status, 1); } // Emit that the track is loaded. const SINT sampleCount = m_pAudioSource->getFrameCount() * kChunkChannels; emit(trackLoaded(pTrack, m_pAudioSource->getFrameRate(), sampleCount)); }
void BaseTrackPlayerImpl::slotLoadFailed(TrackPointer track, QString reason) { // TODO(rryan): Currently load failed doesn't clear the deck as an unload // would. Should we? if (track != NULL) { qDebug() << "Failed to load track" << track->getLocation() << reason; emit(loadTrackFailed(track)); } else { qDebug() << "Failed to load track (NULL track object)" << reason; } // Alert user. QMessageBox::warning(NULL, tr("Couldn't load track."), reason); }
void DlgTagFetcher::fetchTagFinished(const TrackPointer track, const QList<TrackPointer>& tracks) { // check if the answer is for this track if (m_track->getLocation() != track->getLocation()) { return; } m_data.m_pending = false; m_data.m_results = tracks; // qDebug() << "number of results = " << tracks.size(); updateStack(); }
void BaseTrackPlayerImpl::slotLoadFailed(TrackPointer track, QString reason) { // This slot can be delayed until a new track is already loaded // We must not unload the track here if (track != NULL) { qDebug() << "Failed to load track" << track->getLocation() << reason; emit(loadTrackFailed(track)); } else { qDebug() << "Failed to load track (NULL track object)" << reason; } // Alert user. QMessageBox::warning(NULL, tr("Couldn't load track."), reason); }
bool PlayerInfo::isFileLoaded(const QString& track_location) const { QMutexLocker locker(&m_mutex); QMapIterator<QString, TrackPointer> it(m_loadedTrackMap); while (it.hasNext()) { it.next(); TrackPointer pTrack = it.value(); if (pTrack) { if (pTrack->getLocation() == track_location) { return true; } } } return false; }
// This is called from the AnalyserQueue thread TrackPointer AnalyserQueue::dequeueNextBlocking() { m_qm.lock(); if (m_tioq.isEmpty()) { Event::end("AnalyserQueue process"); m_qwait.wait(&m_qm); Event::start("AnalyserQueue process"); if (m_exit) { m_qm.unlock(); return TrackPointer(); } } const PlayerInfo& info = PlayerInfo::instance(); TrackPointer pLoadTrack; QMutableListIterator<TrackPointer> it(m_tioq); while (it.hasNext()) { TrackPointer& pTrack = it.next(); if (!pTrack) { it.remove(); continue; } // Prioritize tracks that are loaded. if (info.isTrackLoaded(pTrack)) { qDebug() << "Prioritizing" << pTrack->getTitle() << pTrack->getLocation(); pLoadTrack = pTrack; it.remove(); break; } } if (!pLoadTrack && !m_tioq.isEmpty()) { pLoadTrack = m_tioq.dequeue(); } m_qm.unlock(); if (pLoadTrack) { qDebug() << "Analyzing" << pLoadTrack->getTitle() << pLoadTrack->getLocation(); } // pTrack might be NULL, up to the caller to check. return pLoadTrack; }
void BrowseTableModel::trackLoaded(QString group, TrackPointer pTrack) { if (group == m_previewDeckGroup) { for (int row = 0; row < rowCount(); ++row) { QModelIndex i = index(row, COLUMN_PREVIEW); if (i.data().toBool()) { QStandardItem* item = itemFromIndex(i); item->setText("0"); } } if (pTrack) { for (int row = 0; row < rowCount(); ++row) { QModelIndex i = index(row, COLUMN_PREVIEW); QString location = index(row, COLUMN_LOCATION).data().toString(); if (location == pTrack->getLocation()) { QStandardItem* item = itemFromIndex(i); item->setText("1"); break; } } } } }
void AnalyzerGain::finalize(TrackPointer tio) { //TODO: We are going to store values as relative peaks so that "0" means that no replaygain has been evaluated. // This means that we are going to transform from dB to peaks and viceversa. // One may think to digg into replay_gain code and modify it so that // it directly sends results as relative peaks. // In that way there is no need to spend resources in calculating log10 or pow. if(!m_initalized) return; float fReplayGainOutput = m_pReplayGain->end(); if (fReplayGainOutput == GAIN_NOT_ENOUGH_SAMPLES) { qDebug() << "ReplayGain 1.0 analysis failed"; m_initalized = false; return; } Mixxx::ReplayGain replayGain(tio->getReplayGain()); replayGain.setRatio(db2ratio(fReplayGainOutput)); tio->setReplayGain(replayGain); qDebug() << "ReplayGain 1.0 result is" << fReplayGainOutput << "dB for" << tio->getLocation(); m_initalized = false; }
void SamplerBank::slotSaveSamplerBank(double v) { if (v == 0.0f) return; QString s = QFileDialog::getSaveFileName(NULL, tr("Save Sampler Bank")); QFile file(s); if (!file.open(QIODevice::WriteOnly)) { QMessageBox::warning(NULL, tr("Error Saving Sampler Bank"), tr("Could not write the sampler bank to '%1'.").arg(s)); return; } QDomDocument doc("SamplerBank"); QDomElement root = doc.createElement("samplerbank"); doc.appendChild(root); for (unsigned int i = 0; i < m_pPlayerManager->numSamplers(); ++i) { Sampler* pSampler = m_pPlayerManager->getSampler(i); QDomElement samplerNode = doc.createElement(QString("sampler")); samplerNode.setAttribute("group", pSampler->getGroup()); TrackPointer pTrack = PlayerInfo::instance().getTrackInfo(pSampler->getGroup()); if (pTrack) { QString samplerLocation = pTrack->getLocation(); samplerNode.setAttribute("location", samplerLocation); } root.appendChild(samplerNode); } QString docStr = doc.toString(); file.write(docStr.toUtf8().constData()); file.close(); }
QString ChromaPrinter::getFingerprint(TrackPointer pTrack) { mixxx::AudioSource::OpenParams config; config.setChannelCount(2); // always stereo / 2 channels (see below) auto pAudioSource = SoundSourceProxy(pTrack).openAudioSource(config); if (!pAudioSource) { qDebug() << "Failed to open file for fingerprinting" << pTrack->getLocation() << *pAudioSource; return QString(); } const auto fingerprintRange = intersect( pAudioSource->frameIndexRange(), mixxx::IndexRange::forward( pAudioSource->frameIndexMin(), kFingerprintDuration * pAudioSource->sampleRate())); mixxx::AudioSourceStereoProxy audioSourceProxy( pAudioSource, fingerprintRange.length()); return calcFingerprint(audioSourceProxy, fingerprintRange); }
bool BaseTrackCache::updateIndexWithTrackpointer(TrackPointer pTrack) { if (sDebug) { qDebug() << "updateIndexWithTrackpointer:" << pTrack->getLocation(); } if (!pTrack) { return false; } int numColumns = columnCount(); TrackId trackId(pTrack->getId()); if (trackId.isValid()) { // m_trackInfo[id] will insert a QVector<QVariant> into the // m_trackInfo HashTable with the key "id" QVector<QVariant>& record = m_trackInfo[trackId]; // prealocate memory for all columns at once record.resize(numColumns); for (int i = 0; i < numColumns; ++i) { getTrackValueForColumn(pTrack, i, record[i]); } } return true; }
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 BrowseThread::populateModel() { m_path_mutex.lock(); MDir thisPath = m_path; BrowseTableModel* thisModelObserver = m_model_observer; m_path_mutex.unlock(); // Refresh the name filters in case we loaded new SoundSource plugins. QStringList nameFilters(SoundSourceProxy::getSupportedFileNamePatterns()); QDirIterator fileIt(thisPath.dir().absolutePath(), nameFilters, QDir::Files | QDir::NoDotAndDotDot); // remove all rows // This is a blocking operation // see signal/slot connection in BrowseTableModel emit(clearModel(thisModelObserver)); QList< QList<QStandardItem*> > rows; int row = 0; // Iterate over the files while (fileIt.hasNext()) { // If a user quickly jumps through the folders // the current task becomes "dirty" m_path_mutex.lock(); MDir newPath = m_path; m_path_mutex.unlock(); if (thisPath.dir() != newPath.dir()) { qDebug() << "Abort populateModel()"; return populateModel(); } QList<QStandardItem*> row_data; QStandardItem* item = new QStandardItem("0"); item->setData("0", Qt::UserRole); row_data.insert(COLUMN_PREVIEW, item); const QString filepath = fileIt.next(); { const TrackPointer pTrack = SoundSourceProxy::importTemporaryTrack( filepath, thisPath.token()); item = new QStandardItem(pTrack->getFileName()); item->setToolTip(item->text()); item->setData(item->text(), Qt::UserRole); row_data.insert(COLUMN_FILENAME, item); item = new QStandardItem(pTrack->getArtist()); item->setToolTip(item->text()); item->setData(item->text(), Qt::UserRole); row_data.insert(COLUMN_ARTIST, item); item = new QStandardItem(pTrack->getTitle()); item->setToolTip(item->text()); item->setData(item->text(), Qt::UserRole); row_data.insert(COLUMN_TITLE, item); item = new QStandardItem(pTrack->getAlbum()); item->setToolTip(item->text()); item->setData(item->text(), Qt::UserRole); row_data.insert(COLUMN_ALBUM, item); item = new QStandardItem(pTrack->getAlbumArtist()); item->setToolTip(item->text()); item->setData(item->text(), Qt::UserRole); row_data.insert(COLUMN_ALBUMARTIST, item); item = new QStandardItem(pTrack->getTrackNumber()); item->setToolTip(item->text()); item->setData(item->text().toInt(), Qt::UserRole); row_data.insert(COLUMN_TRACK_NUMBER, item); const QString year(pTrack->getYear()); item = new YearItem(year); item->setToolTip(year); // The year column is sorted according to the numeric calendar year item->setData(mixxx::TrackMetadata::parseCalendarYear(year), Qt::UserRole); row_data.insert(COLUMN_YEAR, item); item = new QStandardItem(pTrack->getGenre()); item->setToolTip(item->text()); item->setData(item->text(), Qt::UserRole); row_data.insert(COLUMN_GENRE, item); item = new QStandardItem(pTrack->getComposer()); item->setToolTip(item->text()); item->setData(item->text(), Qt::UserRole); row_data.insert(COLUMN_COMPOSER, item); item = new QStandardItem(pTrack->getGrouping()); item->setToolTip(item->text()); item->setData(item->text(), Qt::UserRole); row_data.insert(COLUMN_GROUPING, item); item = new QStandardItem(pTrack->getComment()); item->setToolTip(item->text()); item->setData(item->text(), Qt::UserRole); row_data.insert(COLUMN_COMMENT, item); QString duration = pTrack->getDurationText(mixxx::Duration::Precision::SECONDS); item = new QStandardItem(duration); item->setToolTip(item->text()); item->setData(item->text(), Qt::UserRole); row_data.insert(COLUMN_DURATION, item); item = new QStandardItem(pTrack->getBpmText()); item->setToolTip(item->text()); item->setData(pTrack->getBpm(), Qt::UserRole); row_data.insert(COLUMN_BPM, item); item = new QStandardItem(pTrack->getKeyText()); item->setToolTip(item->text()); item->setData(item->text(), Qt::UserRole); row_data.insert(COLUMN_KEY, item); item = new QStandardItem(pTrack->getType()); item->setToolTip(item->text()); item->setData(item->text(), Qt::UserRole); row_data.insert(COLUMN_TYPE, item); item = new QStandardItem(pTrack->getBitrateText()); item->setToolTip(item->text()); item->setData(pTrack->getBitrate(), Qt::UserRole); row_data.insert(COLUMN_BITRATE, item); QString location = pTrack->getLocation(); QString nativeLocation = QDir::toNativeSeparators(location); item = new QStandardItem(nativeLocation); item->setToolTip(nativeLocation); item->setData(location, Qt::UserRole); row_data.insert(COLUMN_NATIVELOCATION, item); QDateTime modifiedTime = pTrack->getFileModifiedTime().toLocalTime(); item = new QStandardItem(modifiedTime.toString(Qt::DefaultLocaleShortDate)); item->setToolTip(item->text()); item->setData(modifiedTime, Qt::UserRole); row_data.insert(COLUMN_FILE_MODIFIED_TIME, item); QDateTime creationTime = pTrack->getFileCreationTime().toLocalTime(); item = new QStandardItem(creationTime.toString(Qt::DefaultLocaleShortDate)); item->setToolTip(item->text()); item->setData(creationTime, Qt::UserRole); row_data.insert(COLUMN_FILE_CREATION_TIME, item); const mixxx::ReplayGain replayGain(pTrack->getReplayGain()); item = new QStandardItem( mixxx::ReplayGain::ratioToString(replayGain.getRatio())); item->setToolTip(item->text()); item->setData(item->text(), Qt::UserRole); row_data.insert(COLUMN_REPLAYGAIN, item); } // implicitly release track pointer and unlock cache rows.append(row_data); ++row; // If 10 tracks have been analyzed, send it to GUI // Will limit GUI freezing if (row % 10 == 0) { // this is a blocking operation emit(rowsAppended(rows, thisModelObserver)); qDebug() << "Append " << rows.count() << " from " << filepath; rows.clear(); } // Sleep additionally for 10ms which prevents us from GUI freezes msleep(20); } emit(rowsAppended(rows, thisModelObserver)); qDebug() << "Append last " << rows.count(); }
void SamplerBank::slotSaveSamplerBank(double v) { if (v == 0.0 || m_pPlayerManager == NULL) { return; } QString filefilter = tr("Mixxx Sampler Banks (*.xml)"); QString samplerBankPath = QFileDialog::getSaveFileName( NULL, tr("Save Sampler Bank"), QString(), tr("Mixxx Sampler Banks (*.xml)"), &filefilter); if (samplerBankPath.isNull() || samplerBankPath.isEmpty()) { return; } // Manually add extension due to bug in QFileDialog // via https://bugreports.qt-project.org/browse/QTBUG-27186 // Can be removed after switch to Qt5 QFileInfo fileName(samplerBankPath); if (fileName.suffix().isEmpty()) { QString ext = filefilter.section(".",1,1); ext.chop(1); samplerBankPath.append(".").append(ext); } // The user has picked a new directory via a file dialog. This means the // system sandboxer (if we are sandboxed) has granted us permission to this // folder. We don't need access to this file on a regular basis so we do not // register a security bookmark. QFile file(samplerBankPath); if (!file.open(QIODevice::WriteOnly)) { QMessageBox::warning(NULL, tr("Error Saving Sampler Bank"), tr("Could not write the sampler bank to '%1'.") .arg(samplerBankPath)); return; } QDomDocument doc("SamplerBank"); QDomElement root = doc.createElement("samplerbank"); doc.appendChild(root); for (unsigned int i = 0; i < m_pPlayerManager->numSamplers(); ++i) { Sampler* pSampler = m_pPlayerManager->getSampler(i + 1); if (pSampler == NULL) { continue; } QDomElement samplerNode = doc.createElement(QString("sampler")); samplerNode.setAttribute("group", pSampler->getGroup()); TrackPointer pTrack = pSampler->getLoadedTrack(); if (pTrack) { QString samplerLocation = pTrack->getLocation(); samplerNode.setAttribute("location", samplerLocation); } root.appendChild(samplerNode); } QString docStr = doc.toString(); file.write(docStr.toUtf8().constData()); file.close(); }
void CachingReaderWorker::loadTrack(TrackPointer pTrack) { //qDebug() << m_pGroup << "CachingReaderWorker::loadTrack() lock acquired for load."; // Emit that a new track is loading, stops the current track emit(trackLoading()); ReaderStatusUpdate status; status.status = TRACK_LOADED; status.chunk = NULL; status.trackNumSamples = 0; if (m_pCurrentSoundSource != NULL) { delete m_pCurrentSoundSource; m_pCurrentSoundSource = NULL; } m_iTrackNumSamples = 0; QString filename = pTrack->getLocation(); if (filename.isEmpty() || !pTrack->exists()) { // Must unlock before emitting to avoid deadlock qDebug() << m_pGroup << "CachingReaderWorker::loadTrack() load failed for\"" << filename << "\", unlocked reader lock"; status.status = TRACK_NOT_LOADED; m_pReaderStatusFIFO->writeBlocking(&status, 1); emit(trackLoadFailed( pTrack, QString("The file '%1' could not be found.").arg(filename))); return; } m_pCurrentSoundSource = new SoundSourceProxy(pTrack); bool openSucceeded = (m_pCurrentSoundSource->open() == OK); //Open the song for reading unsigned int trackSampleRate = m_pCurrentSoundSource->getSampleRate(); m_iTrackNumSamples = status.trackNumSamples = m_pCurrentSoundSource->length(); if (!openSucceeded || m_iTrackNumSamples == 0 || trackSampleRate == 0) { // Must unlock before emitting to avoid deadlock qDebug() << m_pGroup << "CachingReaderWorker::loadTrack() load failed for\"" << filename << "\", file invalid, unlocked reader lock"; status.status = TRACK_NOT_LOADED; m_pReaderStatusFIFO->writeBlocking(&status, 1); emit(trackLoadFailed( pTrack, QString("The file '%1' could not be loaded.").arg(filename))); return; } m_pReaderStatusFIFO->writeBlocking(&status, 1); // Clear the chunks to read list. ChunkReadRequest request; while (m_pChunkReadRequestFIFO->read(&request, 1) == 1) { qDebug() << "Skipping read request for " << request.chunk->chunk_number; status.status = CHUNK_READ_INVALID; status.chunk = request.chunk; m_pReaderStatusFIFO->writeBlocking(&status, 1); } // Emit that the track is loaded. emit(trackLoaded(pTrack, trackSampleRate, m_iTrackNumSamples)); }
void AnalyserQueue::run() { unsigned static id = 0; //the id of this thread, for debugging purposes QThread::currentThread()->setObjectName(QString("AnalyserQueue %1").arg(++id)); // If there are no analyzers, don't waste time running. if (m_aq.size() == 0) return; m_progressInfo.current_track = TrackPointer(); m_progressInfo.track_progress = 0; m_progressInfo.queue_size = 0; m_progressInfo.sema.release(); // Initalise with one while (!m_exit) { TrackPointer nextTrack = dequeueNextBlocking(); // It's important to check for m_exit here in case we decided to exit // while blocking for a new track. if (m_exit) return; // If the track is NULL, try to get the next one. // Could happen if the track was queued but then deleted. // Or if dequeueNextBlocking is unblocked by exit == true if (!nextTrack) { m_qm.lock(); m_queue_size = m_tioq.size(); m_qm.unlock(); if (m_queue_size == 0) { emit(queueEmpty()); // emit asynchrony for no deadlock } continue; } Trace trace("AnalyserQueue analyzing track"); // Get the audio SoundSourceProxy soundSource(nextTrack); soundSource.open(); //Open the file for reading int iNumSamples = soundSource.length(); int iSampleRate = soundSource.getSampleRate(); if (iNumSamples == 0 || iSampleRate == 0) { qDebug() << "Skipping invalid file:" << nextTrack->getLocation(); continue; } QListIterator<Analyser*> it(m_aq); bool processTrack = false; while (it.hasNext()) { // Make sure not to short-circuit initialise(...) if (it.next()->initialise(nextTrack, iSampleRate, iNumSamples)) { processTrack = true; } } m_qm.lock(); m_queue_size = m_tioq.size(); m_qm.unlock(); if (processTrack) { emitUpdateProgress(nextTrack, 0); bool completed = doAnalysis(nextTrack, &soundSource); if (!completed) { //This track was cancelled QListIterator<Analyser*> itf(m_aq); while (itf.hasNext()) { itf.next()->cleanup(nextTrack); } queueAnalyseTrack(nextTrack); emitUpdateProgress(nextTrack, 0); } else { // 100% - FINALIZE_PERCENT finished emitUpdateProgress(nextTrack, 1000 - FINALIZE_PERCENT); // This takes around 3 sec on a Atom Netbook QListIterator<Analyser*> itf(m_aq); while (itf.hasNext()) { itf.next()->finalise(nextTrack); } emit(trackDone(nextTrack)); emitUpdateProgress(nextTrack, 1000); // 100% } } else { emitUpdateProgress(nextTrack, 1000); // 100% qDebug() << "Skipping track analysis because no analyzer initialized."; } m_qm.lock(); m_queue_size = m_tioq.size(); m_qm.unlock(); if (m_queue_size == 0) { emit(queueEmpty()); // emit asynchrony for no deadlock } } emit(queueEmpty()); // emit in case of exit; }