⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sequencemanager.cpp

📁 LINUX下的混音软件
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: *//*    Rosegarden    A MIDI and audio sequencer and musical notation editor.     This program is Copyright 2000-2007        Guillaume Laurent   <glaurent@telegraph-road.org>,        Chris Cannam        <cannam@all-day-breakfast.com>,        Richard Bown        <richard.bown@ferventsoftware.com>     The moral rights of Guillaume Laurent, Chris Cannam, and Richard    Bown to claim authorship of this work have been asserted.     Other copyrights also apply to some parts of this work.  Please    see the AUTHORS file and individual file headers for details.     This program is free software; you can redistribute it and/or    modify it under the terms of the GNU General Public License as    published by the Free Software Foundation; either version 2 of the    License, or (at your option) any later version.  See the file    COPYING included with this distribution for more information.*/#include "SequenceManager.h"#include "sound/Midi.h"#include "misc/Debug.h"#include "document/ConfigGroups.h"#include "base/Composition.h"#include "base/Device.h"#include "base/Exception.h"#include "base/Instrument.h"#include "base/MidiProgram.h"#include "base/RealTime.h"#include "base/Segment.h"#include "base/Studio.h"#include "base/Track.h"#include "base/TriggerSegment.h"#include "CompositionMmapper.h"#include "document/RosegardenGUIDoc.h"#include "document/MultiViewCommandHistory.h"#include "gui/application/RosegardenApplication.h"#include "gui/application/RosegardenGUIApp.h"#include "gui/application/RosegardenGUIView.h"#include "gui/dialogs/AudioManagerDialog.h"#include "gui/dialogs/CountdownDialog.h"#include "gui/dialogs/TransportDialog.h"#include "gui/kdeext/KStartupLogo.h"#include "gui/studio/StudioControl.h"#include "gui/widgets/CurrentProgressDialog.h"#include "MetronomeMmapper.h"#include "SegmentMmapperFactory.h"#include "SequencerMapper.h"#include "ControlBlockMmapper.h"#include "sound/AudioFile.h"#include "sound/MappedComposition.h"#include "sound/MappedEvent.h"#include "sound/MappedInstrument.h"#include "sound/SoundDriver.h"#include "TempoSegmentMmapper.h"#include "TimeSigSegmentMmapper.h"#include <klocale.h>#include <kstddirs.h>#include <kconfig.h>#include <kglobal.h>#include <kmessagebox.h>#include <qapplication.h>#include <qcstring.h>#include <qcursor.h>#include <qdatastream.h>#include <qevent.h>#include <qobject.h>#include <qpushbutton.h>#include <qstring.h>#include <qstringlist.h>#include <qtimer.h>#include <algorithm>namespace Rosegarden{SequenceManager::SequenceManager(RosegardenGUIDoc *doc,                                 TransportDialog *transport):            m_doc(doc),            m_compositionMmapper(new CompositionMmapper(m_doc)),            m_controlBlockMmapper(new ControlBlockMmapper(m_doc)),            m_metronomeMmapper(SegmentMmapperFactory::makeMetronome(m_doc)),            m_tempoSegmentMmapper(SegmentMmapperFactory::makeTempo(m_doc)),            m_timeSigSegmentMmapper(SegmentMmapperFactory::makeTimeSig(m_doc)),            m_transportStatus(STOPPED),            m_soundDriverStatus(NO_DRIVER),            m_transport(transport),            m_lastRewoundAt(clock()),            m_countdownDialog(0),            m_countdownTimer(new QTimer(m_doc)),            m_shownOverrunWarning(false),            m_recordTime(new QTime()),            m_compositionRefreshStatusId(m_doc->getComposition().getNewRefreshStatusId()),            m_updateRequested(true),            m_compositionMmapperResetTimer(new QTimer(m_doc)),            m_sequencerMapper(0),            m_reportTimer(new QTimer(m_doc)),            m_canReport(true),            m_lastLowLatencySwitchSent(false),            m_lastTransportStartPosition(0),            m_sampleRate(0){// Replaced this with a call to cleanup() from composition mmapper ctor:// if done here, this removes the mmapped versions of any segments stored// in the autoload (that have only just been mapped by the ctor!)//    m_compositionMmapper->cleanup();m_countdownDialog = new CountdownDialog(dynamic_cast<QWidget*>                                        (m_doc->parent())->parentWidget());// Connect these for use later//connect(m_countdownTimer, SIGNAL(timeout()),        this, SLOT(slotCountdownTimerTimeout()));connect(m_reportTimer, SIGNAL(timeout()),        this, SLOT(slotAllowReport()));connect(m_compositionMmapperResetTimer, SIGNAL(timeout()),        this, SLOT(slotScheduledCompositionMmapperReset()));connect(doc->getCommandHistory(), SIGNAL(commandExecuted()),        this, SLOT(update()));m_doc->getComposition().addObserver(this);// The owner of this sequence manager will need to call// checkSoundDriverStatus on it to set up its status appropriately// immediately after construction; we used to do it from here but// we're not well placed to handle reporting to the user if it// throws an exception (and we don't want to leave the object half// constructed).// Try to map the sequencer file//mapSequencer();}SequenceManager::~SequenceManager(){    m_doc->getComposition().removeObserver(this);    SEQMAN_DEBUG << "SequenceManager::~SequenceManager()\n";    delete m_compositionMmapper;    delete m_controlBlockMmapper;    delete m_metronomeMmapper;    delete m_tempoSegmentMmapper;    delete m_timeSigSegmentMmapper;    delete m_sequencerMapper;}void SequenceManager::setDocument(RosegardenGUIDoc* doc){    SEQMAN_DEBUG << "SequenceManager::setDocument(" << doc << ")\n";    DataBlockRepository::clear();    m_doc->getComposition().removeObserver(this);    disconnect(m_doc->getCommandHistory(), SIGNAL(commandExecuted()));    m_segments.clear();    m_triggerSegments.clear();    m_doc = doc;    Composition &comp = m_doc->getComposition();    // Must recreate and reconnect the countdown timer and dialog    // (bug 729039)    //    delete m_countdownDialog;    delete m_countdownTimer;    delete m_compositionMmapperResetTimer;    m_countdownDialog = new CountdownDialog(dynamic_cast<QWidget*>                                            (m_doc->parent())->parentWidget());    // Bug 933041: no longer connect the CountdownDialog from    // SequenceManager; instead let the RosegardenGUIApp connect it to    // its own slotStop to ensure the right housekeeping is done    m_countdownTimer = new QTimer(m_doc);    // Connect this for use later    //    connect(m_countdownTimer, SIGNAL(timeout()),            this, SLOT(slotCountdownTimerTimeout()));    m_compositionRefreshStatusId = comp.getNewRefreshStatusId();    comp.addObserver(this);    connect(m_doc->getCommandHistory(), SIGNAL(commandExecuted()),            this, SLOT(update()));    for (Composition::iterator i = comp.begin(); i != comp.end(); ++i) {        SEQMAN_DEBUG << "Adding segment with rid " << (*i)->getRuntimeId() << endl;        m_segments.insert(SegmentRefreshMap::value_type                          (*i, (*i)->getNewRefreshStatusId()));    }    for (Composition::triggersegmentcontaineriterator i =                comp.getTriggerSegments().begin();            i != comp.getTriggerSegments().end(); ++i) {        m_triggerSegments.insert(SegmentRefreshMap::value_type                                 ((*i)->getSegment(),                                  (*i)->getSegment()->getNewRefreshStatusId()));    }    m_compositionMmapperResetTimer = new QTimer(m_doc);    connect(m_compositionMmapperResetTimer, SIGNAL(timeout()),            this, SLOT(slotScheduledCompositionMmapperReset()));    resetCompositionMmapper();    // Try to map the sequencer file    //    mapSequencer();}voidSequenceManager::setTransportStatus(const TransportStatus &status){    m_transportStatus = status;}voidSequenceManager::mapSequencer(){    if (m_sequencerMapper)        return ;    try {        m_sequencerMapper = new SequencerMapper(                                KGlobal::dirs()->resourceDirs("tmp").last() + "/rosegarden_sequencer_timing_block");    } catch (Exception) {        m_sequencerMapper = 0;    }}boolSequenceManager::play(){    mapSequencer();    Composition &comp = m_doc->getComposition();    // If already playing or recording then stop    //    if (m_transportStatus == PLAYING ||            m_transportStatus == RECORDING ) {        stopping();        return true;    }    // This check may throw an exception    checkSoundDriverStatus(false);    // Align Instrument lists and send initial program changes    //    preparePlayback();    m_lastTransportStartPosition = comp.getPosition();    // Update play metronome status    //    m_controlBlockMmapper->updateMetronomeData    (m_metronomeMmapper->getMetronomeInstrument());    m_controlBlockMmapper->updateMetronomeForPlayback();    // make sure we toggle the play button    //    m_transport->PlayButton()->setOn(true);    //!!! disable the record button, because recording while playing is horribly    // broken, and disabling it is less complicated than fixing it    // see #1223025 - DMM    //    SEQMAN_DEBUG << "SequenceManager::play() - disabling record button, as we are playing\n";    //    m_transport->RecordButton()->setEnabled(false);    if (comp.getCurrentTempo() == 0) {        comp.setCompositionDefaultTempo(comp.getTempoForQpm(120.0));        SEQMAN_DEBUG << "SequenceManager::play() - setting Tempo to Default value of 120.000\n";    } else {        SEQMAN_DEBUG << "SequenceManager::play() - starting to play\n";    }    // Send initial tempo    //    double qnD = 60.0 / comp.getTempoQpm(comp.getCurrentTempo());    RealTime qnTime =        RealTime(long(qnD),                 long((qnD - double(long(qnD))) * 1000000000.0));    StudioControl::sendQuarterNoteLength(qnTime);    // set the tempo in the transport    m_transport->setTempo(comp.getCurrentTempo());    // The arguments for the Sequencer    RealTime startPos = comp.getElapsedRealTime(comp.getPosition());    // If we're looping then jump to loop start    if (comp.isLooping())        startPos = comp.getElapsedRealTime(comp.getLoopStart());    KConfig* config = kapp->config();    config->setGroup(SequencerOptionsConfigGroup);    bool lowLat = config->readBoolEntry("audiolowlatencymonitoring", true);    if (lowLat != m_lastLowLatencySwitchSent) {        QByteArray data;        QDataStream streamOut(data, IO_WriteOnly);        streamOut << lowLat;        rgapp->sequencerSend("setLowLatencyMode(bool)", data);        m_lastLowLatencySwitchSent = lowLat;    }    QByteArray data;    QCString replyType;    QByteArray replyData;    QDataStream streamOut(data, IO_WriteOnly);    // playback start position    streamOut << (long)startPos.sec;    streamOut << (long)startPos.nsec;    // Apart from perhaps the small file size, I think with hindsight    // that these options are more easily set to reasonable defaults    // here than left to the user.  Mostly.    //!!! need some cleverness somewhere to ensure the read-ahead    //is larger than the JACK period size    if (lowLat) {        streamOut << 0L; // read-ahead sec        streamOut << 160000000L; // read-ahead nsec        streamOut << 0L; // audio mix sec        streamOut << 60000000L; // audio mix nsec: ignored in lowlat mode        streamOut << 2L; // audio read sec        streamOut << 500000000L; // audio read nsec        streamOut << 4L; // audio write sec        streamOut << 0L; // audio write nsec        streamOut << 256L; // cacheable small file size in K    } else {        streamOut << 0L; // read-ahead sec        streamOut << 500000000L; // read-ahead nsec        streamOut << 0L; // audio mix sec        streamOut << 400000000L; // audio mix nsec        streamOut << 2L; // audio read sec        streamOut << 500000000L; // audio read nsec        streamOut << 4L; // audio write sec        streamOut << 0L; // audio write nsec        streamOut << 256L; // cacheable small file size in K    }    // Send Play to the Sequencer    if (!rgapp->sequencerCall("play(long int, long int, long int, long int, long int, long int, long int, long int, long int, long int, long int)",                              replyType, replyData, data)) {        m_transportStatus = STOPPED;        return false;    }    // ensure the return type is ok    QDataStream streamIn(replyData, IO_ReadOnly);    int result;    streamIn >> result;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -