Exemplo n.º 1
0
void CueControl::trackLoaded(TrackPointer pTrack) {
    QMutexLocker lock(&m_mutex);
    if (m_pLoadedTrack)
        trackUnloaded(m_pLoadedTrack);

    if (!pTrack) {
        return;
    }

    m_pLoadedTrack = pTrack;
    connect(pTrack.data(), SIGNAL(cuesUpdated()),
            this, SLOT(trackCuesUpdated()),
            Qt::DirectConnection);

    Cue* loadCue = NULL;
    const QList<Cue*>& cuePoints = pTrack->getCuePoints();
    QListIterator<Cue*> it(cuePoints);
    while (it.hasNext()) {
        Cue* pCue = it.next();
        if (pCue->getType() == Cue::LOAD) {
            loadCue = pCue;
        } else if (pCue->getType() != Cue::CUE) {
            continue;
        }
        int hotcue = pCue->getHotCue();
        if (hotcue != -1)
            attachCue(pCue, hotcue);
    }

    double loadCuePoint = 0.0;
    // If cue recall is ON in the prefs, then we're supposed to seek to the cue
    // point on song load. Note that [Controls],cueRecall == 0 corresponds to "ON", not OFF.
    bool cueRecall = (getConfig()->getValueString(
                ConfigKey("[Controls]","CueRecall"), "0").toInt() == 0);
    if (loadCue != NULL) {
        m_pCuePoint->set(loadCue->getPosition());
        if (cueRecall) {
            loadCuePoint = loadCue->getPosition();
        }
    } else {
        // If no cue point is stored, set one at track start
        m_pCuePoint->set(0.0);
    }

    // Need to unlock before emitting any signals to prevent deadlock.
    lock.unlock();
    // If cueRecall is on, seek to it even if we didn't find a cue value (we'll
    // seek to 0.
    if (cueRecall) {
        seekExact(loadCuePoint);
    } else if (!(m_pVinylControlEnabled->get() &&
            m_pVinylControlMode->get() == MIXXX_VCMODE_ABSOLUTE)) {
        // If cuerecall is off, seek to zero unless
        // vinylcontrol is on and set to absolute.  This allows users to
        // load tracks and have the needle-drop be maintained.
        seekExact(0.0);
    }
}
Exemplo n.º 2
0
void PlayerInfo::setTrackInfo(const QString& group, const TrackPointer& track) {
    QMutexLocker locker(&m_mutex);
    TrackPointer pOld = m_loadedTrackMap.value(group);
    if (pOld) {
        emit(trackUnloaded(group, pOld));
    }
    m_loadedTrackMap.insert(group, track);
    emit(trackLoaded(group, track));
}
Exemplo n.º 3
0
void BpmControl::trackLoaded(TrackPointer pTrack) {
    trackUnloaded(m_pTrack);

    if (pTrack) {
        m_pTrack = pTrack;
        m_pBeats = m_pTrack->getBeats();
        connect(m_pTrack.data(), SIGNAL(beatsUpdated()),
                this, SLOT(slotUpdatedTrackBeats()));
    }
}
Exemplo n.º 4
0
void CueControl::trackLoaded(TrackPointer pTrack) {
    QMutexLocker lock(&m_mutex);
    if (m_pLoadedTrack)
        trackUnloaded(m_pLoadedTrack);

    if (!pTrack) {
        return;
    }

    m_pLoadedTrack = pTrack;
    connect(pTrack.data(), SIGNAL(cuesUpdated()),
            this, SLOT(trackCuesUpdated()),
            Qt::DirectConnection);

    Cue* loadCue = NULL;
    const QList<Cue*>& cuePoints = pTrack->getCuePoints();
    QListIterator<Cue*> it(cuePoints);
    while (it.hasNext()) {
        Cue* pCue = it.next();
        if (pCue->getType() == Cue::LOAD) {
            loadCue = pCue;
        } else if (pCue->getType() != Cue::CUE) {
            continue;
        }
        int hotcue = pCue->getHotCue();
        if (hotcue != -1)
            attachCue(pCue, hotcue);
    }

    double loadCuePoint = 0.0;
    if (loadCue != NULL) {
        m_pCuePoint->set(loadCue->getPosition());

        // If cue recall is ON in the prefs, then we're supposed to seek to the cue
        // point on song load. Note that [Controls],cueRecall == 0 corresponds to "ON", not OFF.
        if (!getConfig()->getValueString(
                ConfigKey("[Controls]","CueRecall")).toInt()) {
            loadCuePoint = loadCue->getPosition();
        }
    } else {
        // If no cue point is stored, set one at track start
        m_pCuePoint->set(0.0);
    }

    // Need to unlock before emitting any signals to prevent deadlock.
    lock.unlock();
    seekExact(loadCuePoint);
}
Exemplo n.º 5
0
// Create the temporary auto-DJ-crates table.
// Done the first time it's used, since the user might not even make
// use of this feature.
void AutoDJCratesDAO::createAutoDjCratesDatabase() {
    // If the use of tracks that haven't been played in a while has changed,
    // then the active-tracks view must be recreated.
    bool bUseIgnoreTime = (bool) m_pConfig->getValueString(
                              ConfigKey("[Auto DJ]", "UseIgnoreTime"), "0").toInt();
    if (m_bAutoDjCratesDbCreated) {
        if (m_bUseIgnoreTime != bUseIgnoreTime) {
            // Do all this in a single transaction.
            ScopedTransaction oTransaction(m_rDatabase);

            // Get rid of the old active-tracks view.
            QSqlQuery oQuery(m_rDatabase);
            oQuery.exec ("DROP VIEW IF EXISTS " AUTODJACTIVETRACKS_TABLE);
            if (!oQuery.exec()) {
                LOG_FAILED_QUERY(oQuery);
                return;
            }

            // Create the new active-tracks view.
            if (!createActiveTracksView (bUseIgnoreTime)) {
                return;
            }

            // Remember the new setting.
            m_bUseIgnoreTime = bUseIgnoreTime;

            // Commit these changes.
            oTransaction.commit();
        }
    } else {
        m_bUseIgnoreTime = bUseIgnoreTime;
    }

    // If this database has already been created, skip this.
    if (m_bAutoDjCratesDbCreated) {
        return;
    }

    // Do all of this in a single transaction.
    ScopedTransaction oTransaction(m_rDatabase);

    // The auto-DJ-crates table contains the track ID, the number of references
    // to that track ID in all of the auto-DJ crates, the number of times that
    // track has been played, and the number of references to the track in the
    // auto-DJ playlist (or in loaded decks).  It filters out tracks that have
    // been deleted from the database (i.e. "hidden" tracks).

    // Create an empty table.
    QSqlQuery oQuery(m_rDatabase);
    // CREATE TEMP TABLE temp_autodj_crates (track_id INTEGER UNIQUE, craterefs INTEGER, timesplayed INTEGER, autodjrefs INTEGER, lastplayed DATETIME);
    //oQuery.exec ("DROP TABLE IF EXISTS " AUTODJCRATES_TABLE);
    QString strQuery("CREATE TEMP TABLE " AUTODJCRATES_TABLE
                     " (" AUTODJCRATESTABLE_TRACKID " INTEGER UNIQUE, "
                     AUTODJCRATESTABLE_CRATEREFS " INTEGER, "
                     AUTODJCRATESTABLE_TIMESPLAYED " INTEGER, "
                     AUTODJCRATESTABLE_AUTODJREFS " INTEGER, "
                     AUTODJCRATESTABLE_LASTPLAYED " DATETIME)");
    oQuery.prepare(strQuery);
    if (!oQuery.exec()) {
        LOG_FAILED_QUERY(oQuery);
        return;
    }

    // Fill out the first three columns.
    // Supply default values for the last two.
    // INSERT INTO temp_autodj_crates (track_id, craterefs, timesplayed, autodjrefs, lastplayed) SELECT crate_tracks.track_id, COUNT (*), library.timesplayed, 0, "" FROM crate_tracks, library WHERE crate_tracks.crate_id IN (SELECT id FROM crates WHERE autodj = 1) AND crate_tracks.track_id = library.id AND library.mixxx_deleted = 0 GROUP BY crate_tracks.track_id, library.timesplayed;
    strQuery = QString("INSERT INTO " AUTODJCRATES_TABLE
                       " (" AUTODJCRATESTABLE_TRACKID ", " AUTODJCRATESTABLE_CRATEREFS ", "
                       AUTODJCRATESTABLE_TIMESPLAYED ", " AUTODJCRATESTABLE_AUTODJREFS ", "
                       AUTODJCRATESTABLE_LASTPLAYED ") SELECT " CRATE_TRACKS_TABLE
                       ".%1 , COUNT (*), " LIBRARY_TABLE ".%2, 0, \"\" FROM "
                       CRATE_TRACKS_TABLE ", " LIBRARY_TABLE " WHERE " CRATE_TRACKS_TABLE
                       ".%4 IN (SELECT %5 FROM " CRATE_TABLE " WHERE %6 = 1) AND "
                       CRATE_TRACKS_TABLE ".%1 = " LIBRARY_TABLE ".%7 AND " LIBRARY_TABLE
                       ".%3 == 0 GROUP BY " CRATE_TRACKS_TABLE ".%1, " LIBRARY_TABLE ".%2")
               .arg(CRATETRACKSTABLE_TRACKID, // %1
                    LIBRARYTABLE_TIMESPLAYED, // %2
                    LIBRARYTABLE_MIXXXDELETED, // %3
                    CRATETRACKSTABLE_CRATEID, // %4
                    CRATETABLE_ID, // %5
                    CRATETABLE_AUTODJ_SOURCE, // %6
                    LIBRARYTABLE_ID); // %7
    oQuery.prepare(strQuery);
    if (!oQuery.exec()) {
        LOG_FAILED_QUERY(oQuery);
        return;
    }

    // Fill out the number of auto-DJ-playlist references.
    if (!updateAutoDjPlaylistReferences()) {
        return;
    }

    // Fill out the last-played date/time.
    if (!updateLastPlayedDateTime()) {
        return;
    }

    // Create the active-tracks view.
    //oQuery.exec ("DROP VIEW IF EXISTS " AUTODJACTIVETRACKS_TABLE);
    if (!createActiveTracksView (m_bUseIgnoreTime)) {
        return;
    }

    // Make a list of the IDs of every set-log playlist.
    // SELECT id FROM Playlists WHERE hidden = 2;
    oQuery.prepare(QString("SELECT %1 FROM " PLAYLIST_TABLE " WHERE %2 = %3")
                   .arg(PLAYLISTTABLE_ID, // %1
                        PLAYLISTTABLE_HIDDEN, // %2
                        QString::number(PlaylistDAO::PLHT_SET_LOG))); // %3
    if (oQuery.exec()) {
        while (oQuery.next())
            m_lstSetLogPlaylistIds.append(oQuery.value(0).toInt());
    } else {
        LOG_FAILED_QUERY(oQuery);
        return;
    }

    // Now the auto-DJ crates database is initialized.
    // Externally-driven updates to the database from now on are driven by
    // signals.
    oTransaction.commit();

    // Be notified when a track is modified.
    // We only care when the number of times it's been played changes.
    connect(&m_rTrackDAO, SIGNAL(trackDirty(int)),
            this, SLOT(slotTrackDirty(int)));

    // Be notified when the status of crates changes.
    // We only care about the crates labeled as auto-DJ, and tracks added to,
    // and removed from, such crates.
    connect(&m_rCrateDAO, SIGNAL(added(int)),
            this, SLOT(slotCrateAdded(int)));
    connect(&m_rCrateDAO, SIGNAL(deleted(int)),
            this, SLOT(slotCrateDeleted(int)));
    connect(&m_rCrateDAO, SIGNAL(autoDjChanged(int,bool)),
            this, SLOT(slotCrateAutoDjChanged(int,bool)));
    connect(&m_rCrateDAO, SIGNAL(trackAdded(int,int)),
            this, SLOT(slotCrateTrackAdded(int,int)));
    connect(&m_rCrateDAO, SIGNAL(trackRemoved(int,int)),
            this, SLOT(slotCrateTrackRemoved(int,int)));

    // Be notified when playlists are added/removed.
    // We only care about set-log playlists.
    connect(&m_rPlaylistDAO, SIGNAL(added(int)),
            this, SLOT(slotPlaylistAdded(int)));
    connect(&m_rPlaylistDAO, SIGNAL(deleted(int)),
            this, SLOT(slotPlaylistDeleted(int)));

    // Be notified when tracks are added/removed from playlists.
    // We only care about the auto-DJ playlist and the set-log playlists.
    connect(&m_rPlaylistDAO, SIGNAL(trackAdded(int,int,int)),
            this, SLOT(slotPlaylistTrackAdded(int,int,int)));
    connect(&m_rPlaylistDAO, SIGNAL(trackRemoved(int,int,int)),
            this, SLOT(slotPlaylistTrackRemoved(int,int,int)));

    // Be notified when tracks are loaded to, or unloaded from, a deck.
    // These count as auto-DJ references, i.e. prevent the track from being
    // selected randomly.
    connect(&PlayerInfo::Instance(), SIGNAL(trackLoaded(QString,TrackPointer)),
            this, SLOT(slotPlayerInfoTrackLoaded(QString,TrackPointer)));
    connect(&PlayerInfo::Instance(),
            SIGNAL(trackUnloaded(QString,TrackPointer)),
            this, SLOT(slotPlayerInfoTrackUnloaded(QString,TrackPointer)));

    // Remember that the auto-DJ-crates database has been created.
    m_bAutoDjCratesDbCreated = true;
}
Exemplo n.º 6
0
void RateControl::trackLoaded(TrackPointer pTrack) {
    if (m_pTrack) {
        trackUnloaded(m_pTrack);
    }
    m_pTrack = pTrack;
}
Exemplo n.º 7
0
BaseTrackPlayer::BaseTrackPlayer(QObject* pParent,
                                 ConfigObject<ConfigValue>* pConfig,
                                 EngineMaster* pMixingEngine,
                                 EffectsManager* pEffectsManager,
                                 EngineChannel::ChannelOrientation defaultOrientation,
                                 QString group,
                                 bool defaultMaster,
                                 bool defaultHeadphones)
        : BasePlayer(pParent, group),
          m_pConfig(pConfig),
          m_pLoadedTrack(),
          m_pLowFilter(NULL),
          m_pMidFilter(NULL),
          m_pHighFilter(NULL),
          m_pLowFilterKill(NULL),
          m_pMidFilterKill(NULL),
          m_pHighFilterKill(NULL),
          m_replaygainPending(false) {
    m_pChannel = new EngineDeck(getGroup(), pConfig, pMixingEngine,
                                pEffectsManager, defaultOrientation);

    EngineBuffer* pEngineBuffer = m_pChannel->getEngineBuffer();
    pMixingEngine->addChannel(m_pChannel);

    // Set the routing option defaults for the master and headphone mixes.
    {
        ControlObject::set(ConfigKey(getGroup(), "master"), (double)defaultMaster);
        ControlObject::set(ConfigKey(getGroup(), "pfl"), (double)defaultHeadphones);
    }

    // Connect our signals and slots with the EngineBuffer's signals and
    // slots. This will let us know when the reader is done loading a track, and
    // let us request that the reader load a track.
    connect(this, SIGNAL(loadTrack(TrackPointer, bool)),
            pEngineBuffer, SLOT(slotLoadTrack(TrackPointer, bool)));
    connect(pEngineBuffer, SIGNAL(trackLoaded(TrackPointer)),
            this, SLOT(slotFinishLoading(TrackPointer)));
    connect(pEngineBuffer, SIGNAL(trackLoadFailed(TrackPointer, QString)),
            this, SLOT(slotLoadFailed(TrackPointer, QString)));
    connect(pEngineBuffer, SIGNAL(trackUnloaded(TrackPointer)),
            this, SLOT(slotUnloadTrack(TrackPointer)));

    // Get loop point control objects
    m_pLoopInPoint = new ControlObjectThread(
            getGroup(),"loop_start_position");
    m_pLoopOutPoint = new ControlObjectThread(
            getGroup(),"loop_end_position");

    // Duration of the current song, we create this one because nothing else does.
    m_pDuration = new ControlObject(ConfigKey(getGroup(), "duration"));

    // Waveform controls
    m_pWaveformZoom = new ControlPotmeter(ConfigKey(group, "waveform_zoom"),
                                          WaveformWidgetRenderer::s_waveformMinZoom,
                                          WaveformWidgetRenderer::s_waveformMaxZoom);
    m_pWaveformZoom->set(1.0);
    m_pWaveformZoom->setStepCount(WaveformWidgetRenderer::s_waveformMaxZoom -
            WaveformWidgetRenderer::s_waveformMinZoom);
    m_pWaveformZoom->setSmallStepCount(WaveformWidgetRenderer::s_waveformMaxZoom -
            WaveformWidgetRenderer::s_waveformMinZoom);

    m_pEndOfTrack = new ControlObject(ConfigKey(group, "end_of_track"));
    m_pEndOfTrack->set(0.);

    m_pPreGain = new ControlObjectSlave(ConfigKey(group, "pregain"));
    //BPM of the current song
    m_pBPM = new ControlObjectThread(group, "file_bpm");
    m_pKey = new ControlObjectThread(group, "file_key");
    m_pReplayGain = new ControlObjectThread(group, "replaygain");
    m_pPlay = new ControlObjectThread(group, "play");
    connect(m_pPlay, SIGNAL(valueChanged(double)),
            this, SLOT(slotPlayToggled(double)));
}
Exemplo n.º 8
0
BaseTrackPlayer::BaseTrackPlayer(QObject* pParent,
                                 ConfigObject<ConfigValue>* pConfig,
                                 EngineMaster* pMixingEngine,
                                 EngineChannel::ChannelOrientation defaultOrientation,
                                 QString group,
                                 bool defaultMaster,
                                 bool defaultHeadphones) :
        BasePlayer(pParent, group),
        m_pConfig(pConfig),
        m_pLoadedTrack() {

    // Need to strdup the string because EngineChannel will save the pointer,
    // but we might get deleted before the EngineChannel. TODO(XXX)
    // pSafeGroupName is leaked. It's like 5 bytes so whatever.
    const char* pSafeGroupName = strdup(getGroup().toAscii().constData());

    m_pChannel = new EngineDeck(pSafeGroupName,
                                pConfig, defaultOrientation);

    EngineBuffer* pEngineBuffer = m_pChannel->getEngineBuffer();
    pMixingEngine->addChannel(m_pChannel);

    // Set the routing option defaults for the master and headphone mixes.
    {
        ControlObjectThreadMain* pMaster = new ControlObjectThreadMain(
                getGroup(), "master");
        pMaster->slotSet(defaultMaster);
        delete pMaster;

        ControlObjectThreadMain* pHeadphones = new ControlObjectThreadMain(
                getGroup(), "pfl");
        pHeadphones->slotSet(defaultHeadphones);
        delete pHeadphones;
    }

    // Connect our signals and slots with the EngineBuffer's signals and
    // slots. This will let us know when the reader is done loading a track, and
    // let us request that the reader load a track.
    connect(this, SIGNAL(loadTrack(TrackPointer, bool)),
            pEngineBuffer, SLOT(slotLoadTrack(TrackPointer, bool)));
    connect(pEngineBuffer, SIGNAL(trackLoaded(TrackPointer)),
            this, SLOT(slotFinishLoading(TrackPointer)));
    connect(pEngineBuffer, SIGNAL(trackLoadFailed(TrackPointer, QString)),
            this, SLOT(slotLoadFailed(TrackPointer, QString)));
    connect(pEngineBuffer, SIGNAL(trackUnloaded(TrackPointer)),
            this, SLOT(slotUnloadTrack(TrackPointer)));

    //Get cue point control object
    m_pCuePoint = new ControlObjectThreadMain(
            getGroup(),"cue_point");
    // Get loop point control objects
    m_pLoopInPoint = new ControlObjectThreadMain(
            getGroup(),"loop_start_position");
    m_pLoopOutPoint = new ControlObjectThreadMain(
            getGroup(),"loop_end_position");
    //Playback position within the currently loaded track (in this player).
    m_pPlayPosition = new ControlObjectThreadMain(
            getGroup(), "playposition");

    // Duration of the current song, we create this one because nothing else does.
    m_pDuration = new ControlObject(ConfigKey(getGroup(), "duration"));

    // Waveform controls
    m_pWaveformZoom = new ControlPotmeter(ConfigKey(group, "waveform_zoom"),
                                          WaveformWidgetRenderer::s_waveformMinZoom,
                                          WaveformWidgetRenderer::s_waveformMaxZoom);
    m_pWaveformZoom->set(1.0);
    m_pWaveformZoom->setStep(1.0);
    m_pWaveformZoom->setSmallStep(1.0);

    m_pEndOfTrack = new ControlObject(ConfigKey(group, "end_of_track"));
    m_pEndOfTrack->set(0.);

    //BPM of the current song
    m_pBPM = new ControlObjectThreadMain(group, "file_bpm");
    m_pReplayGain = new ControlObjectThreadMain(group, "replaygain");
    m_pPlay = new ControlObjectThreadMain(group, "play");
}