You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
323 lines
10 KiB
323 lines
10 KiB
15 years ago
|
|
||
|
/* -*- 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-2008
|
||
|
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.
|
||
|
*/
|
||
|
|
||
|
#ifndef _RG_SEQUENCEMANAGER_H_
|
||
|
#define _RG_SEQUENCEMANAGER_H_
|
||
|
|
||
|
#include "base/Composition.h"
|
||
|
#include "base/Event.h"
|
||
|
#include "base/MidiProgram.h"
|
||
|
#include "base/RealTime.h"
|
||
|
#include "base/Track.h"
|
||
|
#include "gui/application/RosegardenDCOP.h"
|
||
|
#include "sound/MappedComposition.h"
|
||
|
#include "sound/MappedEvent.h"
|
||
|
#include <qobject.h>
|
||
|
#include <qstring.h>
|
||
|
#include <vector>
|
||
|
#include <map>
|
||
|
|
||
|
|
||
|
class QTimer;
|
||
|
class QTime;
|
||
|
class QEvent;
|
||
|
|
||
|
|
||
|
namespace Rosegarden
|
||
|
{
|
||
|
|
||
|
class TransportDialog;
|
||
|
class Track;
|
||
|
class TimeSigSegmentMmapper;
|
||
|
class TempoSegmentMmapper;
|
||
|
class SequencerMapper;
|
||
|
class Segment;
|
||
|
class RosegardenGUIDoc;
|
||
|
class MetronomeMmapper;
|
||
|
class CountdownDialog;
|
||
|
class ControlBlockMmapper;
|
||
|
class CompositionMmapper;
|
||
|
class Composition;
|
||
|
class AudioManagerDialog;
|
||
|
|
||
|
|
||
|
class SequenceManager : public QObject, public CompositionObserver
|
||
|
{
|
||
|
Q_OBJECT
|
||
|
public:
|
||
|
SequenceManager(RosegardenGUIDoc *doc,
|
||
|
TransportDialog *transport);
|
||
|
~SequenceManager();
|
||
|
|
||
|
/**
|
||
|
* Replaces the internal document
|
||
|
*/
|
||
|
void setDocument(RosegardenGUIDoc*);
|
||
|
|
||
|
/**
|
||
|
* Return the current internal document
|
||
|
*/
|
||
|
RosegardenGUIDoc* getDocument();
|
||
|
|
||
|
//
|
||
|
// Transport controls
|
||
|
//
|
||
|
|
||
|
/// returns true if the call actually paused playback
|
||
|
bool play();
|
||
|
|
||
|
// We don't call stop() directly - using stopping() and then
|
||
|
// call stop().
|
||
|
//
|
||
|
void stop();
|
||
|
|
||
|
void stopping();
|
||
|
void rewind();
|
||
|
void fastforward();
|
||
|
void record(bool countIn);
|
||
|
void rewindToBeginning();
|
||
|
void fastForwardToEnd();
|
||
|
|
||
|
void setLoop(const timeT &lhs, const timeT &rhs);
|
||
|
void notifySequencerStatus(TransportStatus status);
|
||
|
void sendSequencerJump(const RealTime &time);
|
||
|
|
||
|
// Events coming in
|
||
|
void processAsynchronousMidi(const MappedComposition &mC,
|
||
|
AudioManagerDialog *aMD);
|
||
|
|
||
|
// Before playing and recording. If warnUser is true, show the
|
||
|
// user a warning dialog if there is a problem with the setup.
|
||
|
//
|
||
|
void checkSoundDriverStatus(bool warnUser);
|
||
|
|
||
|
/**
|
||
|
* Send program changes and align Instrument lists before playback
|
||
|
* starts.
|
||
|
* Also called at document loading (with arg set to true) to reset all instruments
|
||
|
* (fix for bug 820174)
|
||
|
*
|
||
|
* @arg forceProgramChanges if true, always send program changes even if the instrument is
|
||
|
* set not to send any.
|
||
|
*/
|
||
|
void preparePlayback(bool forceProgramChanges = false);
|
||
|
|
||
|
/// Check and set sequencer status
|
||
|
void setTransportStatus(const TransportStatus &status);
|
||
|
TransportStatus getTransportStatus() const { return m_transportStatus; }
|
||
|
|
||
|
/**
|
||
|
* Suspend the sequencer to allow for a safe DCOP call() i.e. one
|
||
|
* when we don't hang both clients 'cos they're blocking on each
|
||
|
* other.
|
||
|
*/
|
||
|
void suspendSequencer(bool value);
|
||
|
|
||
|
/// Send the audio level to VU meters
|
||
|
void sendAudioLevel(MappedEvent *mE);
|
||
|
|
||
|
/// Find what has been initialised and what hasn't
|
||
|
unsigned int getSoundDriverStatus() { return m_soundDriverStatus; }
|
||
|
|
||
|
/// Reset MIDI controllers
|
||
|
void resetControllers();
|
||
|
|
||
|
/// Reset MIDI network
|
||
|
void resetMidiNetwork();
|
||
|
|
||
|
/// Reinitialise the studio
|
||
|
void reinitialiseSequencerStudio();
|
||
|
|
||
|
/// Send JACK and MMC transport control statuses
|
||
|
void sendTransportControlStatuses();
|
||
|
|
||
|
/// Send all note offs and resets to MIDI devices
|
||
|
void panic();
|
||
|
|
||
|
/// Send an MC to the view
|
||
|
void showVisuals(const MappedComposition &mC);
|
||
|
|
||
|
/// Apply in-situ filtering to a MappedComposition
|
||
|
MappedComposition
|
||
|
applyFiltering(const MappedComposition &mC,
|
||
|
MappedEvent::MappedEventType filter);
|
||
|
|
||
|
CountdownDialog* getCountdownDialog() { return m_countdownDialog; }
|
||
|
|
||
|
|
||
|
//
|
||
|
// CompositionObserver interface
|
||
|
//
|
||
|
virtual void segmentAdded (const Composition*, Segment*);
|
||
|
virtual void segmentRemoved (const Composition*, Segment*);
|
||
|
virtual void segmentRepeatChanged (const Composition*, Segment*, bool);
|
||
|
virtual void segmentRepeatEndChanged (const Composition*, Segment*, timeT);
|
||
|
virtual void segmentEventsTimingChanged(const Composition*, Segment *, timeT delay, RealTime rtDelay);
|
||
|
virtual void segmentTransposeChanged (const Composition*, Segment *, int transpose);
|
||
|
virtual void segmentTrackChanged (const Composition*, Segment *, TrackId id);
|
||
|
virtual void segmentEndMarkerChanged (const Composition*, Segment *, bool);
|
||
|
virtual void endMarkerTimeChanged (const Composition*, bool shorten);
|
||
|
virtual void trackChanged (const Composition*, Track*);
|
||
|
virtual void trackDeleted (const Composition*, TrackId);
|
||
|
virtual void timeSignatureChanged (const Composition*);
|
||
|
virtual void metronomeChanged (const Composition*);
|
||
|
virtual void soloChanged (const Composition*, bool solo, TrackId selectedTrack);
|
||
|
virtual void tempoChanged (const Composition*);
|
||
|
|
||
|
void processAddedSegment(Segment*);
|
||
|
void processRemovedSegment(Segment*);
|
||
|
void segmentModified(Segment*);
|
||
|
|
||
|
virtual bool event(QEvent *e);
|
||
|
|
||
|
/// for the gui to call to indicate that the metronome needs to be remapped
|
||
|
void metronomeChanged(InstrumentId id, bool regenerateTicks);
|
||
|
|
||
|
/// for the gui to call to indicate that a MIDI filter needs to be remapped
|
||
|
void filtersChanged(MidiFilter thruFilter,
|
||
|
MidiFilter recordFilter);
|
||
|
|
||
|
/// Return the current sequencer memory mapped file
|
||
|
SequencerMapper* getSequencerMapper() { return m_sequencerMapper; }
|
||
|
|
||
|
/// Ensure that the sequencer file is mapped
|
||
|
void mapSequencer();
|
||
|
|
||
|
void setTransport(TransportDialog* t) { m_transport = t; }
|
||
|
|
||
|
void enableMIDIThruRouting(bool state);
|
||
|
|
||
|
int getSampleRate(); // may return 0 if sequencer uncontactable
|
||
|
|
||
|
public slots:
|
||
|
|
||
|
void update();
|
||
|
|
||
|
signals:
|
||
|
void setProgress(int);
|
||
|
void incrementProgress(int);
|
||
|
|
||
|
void insertableNoteOnReceived(int pitch, int velocity);
|
||
|
void insertableNoteOffReceived(int pitch, int velocity);
|
||
|
void controllerDeviceEventReceived(MappedEvent *ev);
|
||
|
|
||
|
protected slots:
|
||
|
void slotCountdownTimerTimeout();
|
||
|
|
||
|
// Activated by timer to allow a message to be reported to
|
||
|
// the user - we use this mechanism so that the user isn't
|
||
|
// bombarded with dialogs in the event of lots of failures.
|
||
|
//
|
||
|
void slotAllowReport() { m_canReport = true; }
|
||
|
|
||
|
void slotFoundMountPoint(const QString&,
|
||
|
unsigned long kBSize,
|
||
|
unsigned long kBUsed,
|
||
|
unsigned long kBAvail);
|
||
|
|
||
|
void slotScheduledCompositionMmapperReset() { resetCompositionMmapper(); }
|
||
|
|
||
|
protected:
|
||
|
|
||
|
void resetCompositionMmapper();
|
||
|
void resetControlBlockMmapper();
|
||
|
void resetMetronomeMmapper();
|
||
|
void resetTempoSegmentMmapper();
|
||
|
void resetTimeSigSegmentMmapper();
|
||
|
void checkRefreshStatus();
|
||
|
void sendMIDIRecordingDevice(const QString recordDeviceStr);
|
||
|
void restoreRecordSubscriptions();
|
||
|
bool shouldWarnForImpreciseTimer();
|
||
|
|
||
|
//--------------- Data members ---------------------------------
|
||
|
|
||
|
MappedComposition m_mC;
|
||
|
RosegardenGUIDoc *m_doc;
|
||
|
CompositionMmapper *m_compositionMmapper;
|
||
|
ControlBlockMmapper *m_controlBlockMmapper;
|
||
|
MetronomeMmapper *m_metronomeMmapper;
|
||
|
TempoSegmentMmapper *m_tempoSegmentMmapper;
|
||
|
TimeSigSegmentMmapper *m_timeSigSegmentMmapper;
|
||
|
|
||
|
std::vector<Segment*> m_addedSegments;
|
||
|
std::vector<Segment*> m_removedSegments;
|
||
|
bool m_metronomeNeedsRefresh;
|
||
|
|
||
|
// statuses
|
||
|
TransportStatus m_transportStatus;
|
||
|
unsigned int m_soundDriverStatus;
|
||
|
|
||
|
// pointer to the transport dialog
|
||
|
TransportDialog *m_transport;
|
||
|
|
||
|
clock_t m_lastRewoundAt;
|
||
|
|
||
|
CountdownDialog *m_countdownDialog;
|
||
|
QTimer *m_countdownTimer;
|
||
|
|
||
|
bool m_shownOverrunWarning;
|
||
|
|
||
|
// Keep a track of elapsed record time with this object
|
||
|
//
|
||
|
QTime *m_recordTime;
|
||
|
|
||
|
typedef std::map<Segment *, int> SegmentRefreshMap;
|
||
|
SegmentRefreshMap m_segments; // map to refresh status id
|
||
|
SegmentRefreshMap m_triggerSegments;
|
||
|
unsigned int m_compositionRefreshStatusId;
|
||
|
bool m_updateRequested;
|
||
|
|
||
|
// used to schedule a composition mmapper reset when the composition end time marker changes
|
||
|
// this can be caused by a window resize, and since the reset is potentially expensive we want to collapse
|
||
|
// several following requests into one.
|
||
|
QTimer *m_compositionMmapperResetTimer;
|
||
|
|
||
|
// Information that the sequencer is providing to us - for the moment
|
||
|
// it's only the position pointer.
|
||
|
//
|
||
|
SequencerMapper *m_sequencerMapper;
|
||
|
|
||
|
// Just to make sure we don't bother the user too often
|
||
|
//
|
||
|
QTimer *m_reportTimer;
|
||
|
bool m_canReport;
|
||
|
|
||
|
bool m_gotDiskSpaceResult;
|
||
|
unsigned long m_diskSpaceKBAvail;
|
||
|
|
||
|
bool m_lastLowLatencySwitchSent;
|
||
|
|
||
|
timeT m_lastTransportStartPosition;
|
||
|
|
||
|
int m_sampleRate;
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
#endif
|