예제 #1
0
//Other constructor
SoundSourceProxy::SoundSourceProxy(TrackPointer pTrack)
        : m_pTrack(pTrack)
                , m_pSecurityToken(
                openSecurityToken(pTrack->getLocation(),
                        pTrack->getSecurityToken()))
                        , m_pSoundSource(initialize(pTrack->getLocation())) {
}
예제 #2
0
//Other constructor
SoundSourceProxy::SoundSourceProxy(TrackPointer pTrack)
    : SoundSource(pTrack->getLocation()),
      m_pSoundSource(NULL) {

    m_pSoundSource = initialize(pTrack->getLocation());
    m_pTrack = pTrack;
}
예제 #3
0
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.";
}
예제 #4
0
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;
                }
            }
        }
    }
예제 #5
0
void CoverArtCache::guessCover(TrackPointer pTrack) {
    if (pTrack) {
        kLogger.debug() << "Guessing cover art for" << pTrack->getLocation();
        CoverInfo cover = CoverArtUtils::guessCoverInfo(*pTrack);
        pTrack->setCoverInfo(cover);
    }
}
예제 #6
0
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);
}
예제 #7
0
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));
}
예제 #8
0
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;
    }
}
예제 #9
0
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);
}
예제 #10
0
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));
}
예제 #11
0
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);
}
예제 #12
0
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();
}
예제 #13
0
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);
}
예제 #14
0
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;
}
예제 #15
0
// 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;
}
예제 #16
0
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;
                }
            }
        }
    }
}
예제 #17
0
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;
}
예제 #18
0
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();
}
예제 #19
0
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);
}
예제 #20
0
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;
}
예제 #21
0
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));
    }
}
예제 #22
0
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();
}
예제 #23
0
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();
}
예제 #24
0
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));
}
예제 #25
0
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;
}