Chris@45: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@45: Chris@45: /* Chris@45: Sonic Visualiser Chris@45: An audio file viewer and annotation editor. Chris@45: Centre for Digital Music, Queen Mary, University of London. Chris@45: This file copyright 2006-2007 Chris Cannam and QMUL. Chris@45: Chris@45: This program is free software; you can redistribute it and/or Chris@45: modify it under the terms of the GNU General Public License as Chris@45: published by the Free Software Foundation; either version 2 of the Chris@45: License, or (at your option) any later version. See the file Chris@45: COPYING included with this distribution for more information. Chris@45: */ Chris@45: Chris@571: #ifndef SV_MAIN_WINDOW_BASE_H Chris@571: #define SV_MAIN_WINDOW_BASE_H Chris@45: Chris@45: #include Chris@45: #include Chris@45: #include Chris@45: #include Chris@45: #include Chris@113: #include Chris@45: Chris@45: #include "base/Command.h" Chris@45: #include "view/ViewManager.h" Chris@45: #include "base/PropertyContainer.h" Chris@45: #include "base/RecentFiles.h" Chris@161: #include "base/FrameTimer.h" Chris@45: #include "layer/LayerFactory.h" Chris@106: #include "transform/Transform.h" Chris@46: #include "SVFileReader.h" Chris@170: #include "data/fileio/FileFinder.h" Chris@45: #include "data/fileio/FileSource.h" Chris@113: #include "data/osc/OSCQueue.h" Chris@45: #include Chris@45: Chris@45: class Document; Chris@45: class PaneStack; Chris@45: class Pane; Chris@45: class View; Chris@45: class Fader; Chris@45: class Overview; Chris@45: class Layer; Chris@45: class WaveformLayer; Chris@45: class WaveFileModel; Chris@45: class AudioCallbackPlaySource; Chris@574: class AudioCallbackRecordTarget; Chris@45: class CommandHistory; Chris@45: class QMenu; Chris@45: class AudioDial; Chris@541: class LevelPanWidget; Chris@565: class LevelPanToolButton; Chris@45: class QLabel; Chris@45: class QCheckBox; Chris@45: class PreferencesDialog; Chris@45: class QTreeView; Chris@45: class QPushButton; Chris@45: class OSCMessage; Chris@157: class MIDIInput; Chris@45: class KeyReference; Chris@45: class Labeller; Chris@123: class ModelDataTableDialog; Chris@391: class QSignalMapper; Chris@391: class QShortcut; Chris@429: class AlignmentModel; Chris@45: Chris@468: namespace breakfastquay { Chris@551: class SystemPlaybackTarget; Chris@551: class SystemAudioIO; Chris@551: class ResamplerWrapper; Chris@468: } Chris@468: Chris@45: /** Chris@45: * The base class for the SV main window. This includes everything to Chris@45: * do with general document and pane stack management, but nothing Chris@45: * that involves user interaction -- this doesn't create the widget or Chris@45: * menu structures or editing tools, and if a function needs to open a Chris@45: * dialog, it shouldn't be in here. This permits "variations on SV" Chris@45: * to use different subclasses retaining the same general structure. Chris@45: */ Chris@45: Chris@161: class MainWindowBase : public QMainWindow, public FrameTimer Chris@45: { Chris@45: Q_OBJECT Chris@45: Chris@45: public: Chris@475: enum SoundOption { Chris@475: WithAudioOutput = 0x01, Chris@475: WithAudioInput = 0x02, Chris@475: WithMIDIInput = 0x04, Chris@515: WithEverything = 0xff, Chris@515: WithNothing = 0x00 Chris@475: }; Chris@475: typedef int SoundOptions; Chris@475: Chris@475: MainWindowBase(SoundOptions options = WithEverything); Chris@45: virtual ~MainWindowBase(); Chris@45: Chris@45: enum AudioFileOpenMode { Chris@221: ReplaceSession, Chris@45: ReplaceMainModel, Chris@45: CreateAdditionalModel, Chris@45: ReplaceCurrentPane, Chris@45: AskUser Chris@45: }; Chris@45: Chris@45: enum FileOpenStatus { Chris@45: FileOpenSucceeded, Chris@45: FileOpenFailed, Chris@45: FileOpenCancelled, Chris@45: FileOpenWrongMode // attempted to open layer when no main model present Chris@45: }; Chris@45: Chris@483: enum AudioRecordMode { Chris@483: RecordReplaceSession, Chris@483: RecordCreateAdditionalModel Chris@483: }; Chris@483: Chris@45: virtual FileOpenStatus open(FileSource source, AudioFileOpenMode = AskUser); Chris@373: virtual FileOpenStatus openPath(QString fileOrUrl, AudioFileOpenMode = AskUser); dan@210: virtual FileOpenStatus openAudio(FileSource source, AudioFileOpenMode = AskUser, QString templateName = ""); Chris@45: virtual FileOpenStatus openPlaylist(FileSource source, AudioFileOpenMode = AskUser); Chris@45: virtual FileOpenStatus openLayer(FileSource source); Chris@45: virtual FileOpenStatus openImage(FileSource source); Chris@45: Chris@427: virtual FileOpenStatus openDirOfAudio(QString dirPath); Chris@427: Chris@45: virtual FileOpenStatus openSession(FileSource source); Chris@373: virtual FileOpenStatus openSessionPath(QString fileOrUrl); Chris@230: virtual FileOpenStatus openSessionTemplate(QString templateName); Chris@227: virtual FileOpenStatus openSessionTemplate(FileSource source); Chris@45: Chris@45: virtual bool saveSessionFile(QString path); Chris@224: virtual bool saveSessionTemplate(QString path); Chris@45: Chris@161: /// Implementation of FrameTimer interface method Chris@435: virtual sv_frame_t getFrame() const; Chris@161: Chris@357: void setDefaultFfwdRwdStep(RealTime step) { Chris@357: m_defaultFfwdRwdStep = step; Chris@357: } Chris@357: Chris@483: void setAudioRecordMode(AudioRecordMode mode) { Chris@483: m_audioRecordMode = mode; Chris@483: } Chris@483: Chris@45: signals: Chris@45: // Used to toggle the availability of menu actions Chris@45: void canAddPane(bool); Chris@45: void canDeleteCurrentPane(bool); Chris@45: void canAddLayer(bool); Chris@45: void canImportMoreAudio(bool); Chris@259: void canReplaceMainAudio(bool); Chris@45: void canImportLayer(bool); Chris@289: void canChangeSessionTemplate(bool); Chris@45: void canExportAudio(bool); Chris@45: void canExportLayer(bool); Chris@45: void canExportImage(bool); Chris@45: void canRenameLayer(bool); Chris@45: void canEditLayer(bool); Chris@146: void canEditLayerTabular(bool); Chris@45: void canMeasureLayer(bool); Chris@45: void canSelect(bool); Chris@45: void canClearSelection(bool); Chris@45: void canEditSelection(bool); Chris@45: void canDeleteSelection(bool); Chris@45: void canPaste(bool); Chris@45: void canInsertInstant(bool); Chris@45: void canInsertInstantsAtBoundaries(bool); Chris@184: void canInsertItemAtSelection(bool); Chris@45: void canRenumberInstants(bool); Chris@537: void canSubdivideInstants(bool); Chris@538: void canWinnowInstants(bool); Chris@45: void canDeleteCurrentLayer(bool); Chris@45: void canZoom(bool); Chris@45: void canScroll(bool); Chris@45: void canPlay(bool); Chris@475: void canRecord(bool); Chris@45: void canFfwd(bool); Chris@45: void canRewind(bool); Chris@45: void canPlaySelection(bool); Chris@45: void canSpeedUpPlayback(bool); Chris@45: void canSlowDownPlayback(bool); Chris@45: void canChangePlaybackSpeed(bool); Chris@73: void canSelectPreviousPane(bool); Chris@73: void canSelectNextPane(bool); Chris@73: void canSelectPreviousLayer(bool); Chris@73: void canSelectNextLayer(bool); Chris@45: void canSave(bool); Chris@359: void canSaveAs(bool); Chris@104: void hideSplash(); Chris@452: void hideSplash(QWidget *); Chris@342: void sessionLoaded(); Chris@342: void audioFileLoaded(); Chris@160: void replacedDocument(); Chris@164: void activity(QString); Chris@45: Chris@45: public slots: Chris@45: virtual void preferenceChanged(PropertyContainer::PropertyName); Chris@168: virtual void resizeConstrained(QSize); Chris@556: virtual void recreateAudioIO(); Chris@45: Chris@45: protected slots: Chris@45: virtual void zoomIn(); Chris@45: virtual void zoomOut(); Chris@45: virtual void zoomToFit(); Chris@45: virtual void zoomDefault(); Chris@45: virtual void scrollLeft(); Chris@45: virtual void scrollRight(); Chris@45: virtual void jumpLeft(); Chris@45: virtual void jumpRight(); Chris@162: virtual void peekLeft(); Chris@162: virtual void peekRight(); Chris@45: Chris@45: virtual void showNoOverlays(); Chris@45: virtual void showMinimalOverlays(); Chris@45: virtual void showAllOverlays(); Chris@45: Chris@211: virtual void toggleTimeRulers(); Chris@45: virtual void toggleZoomWheels(); Chris@45: virtual void togglePropertyBoxes(); Chris@45: virtual void toggleStatusBar(); Chris@256: virtual void toggleCentreLine(); Chris@45: Chris@45: virtual void play(); Chris@45: virtual void ffwd(); Chris@45: virtual void ffwdEnd(); Chris@45: virtual void rewind(); Chris@45: virtual void rewindStart(); Chris@477: virtual void record(); Chris@45: virtual void stop(); Chris@45: Chris@166: virtual void ffwdSimilar(); Chris@166: virtual void rewindSimilar(); Chris@166: Chris@45: virtual void deleteCurrentPane(); Chris@45: virtual void deleteCurrentLayer(); Chris@123: virtual void editCurrentLayer(); Chris@45: Chris@73: virtual void previousPane(); Chris@73: virtual void nextPane(); Chris@73: virtual void previousLayer(); Chris@73: virtual void nextLayer(); Chris@73: Chris@45: virtual void playLoopToggled(); Chris@45: virtual void playSelectionToggled(); Chris@45: virtual void playSoloToggled(); Chris@45: Chris@570: virtual void audioChannelCountIncreased(int count); Chris@570: Chris@436: virtual void sampleRateMismatch(sv_samplerate_t, sv_samplerate_t, bool) = 0; Chris@45: virtual void audioOverloadPluginDisabled() = 0; Chris@130: virtual void audioTimeStretchMultiChannelDisabled() = 0; Chris@45: Chris@435: virtual void playbackFrameChanged(sv_frame_t); Chris@435: virtual void globalCentreFrameChanged(sv_frame_t); Chris@435: virtual void viewCentreFrameChanged(View *, sv_frame_t); Chris@366: virtual void viewZoomLevelChanged(View *, int, bool); Chris@574: virtual void monitoringLevelsChanged(float, float) = 0; Chris@485: virtual void recordDurationChanged(sv_frame_t, sv_samplerate_t); Chris@45: Chris@45: virtual void currentPaneChanged(Pane *); Chris@45: virtual void currentLayerChanged(Pane *, Layer *); Chris@45: Chris@45: virtual void selectAll(); Chris@45: virtual void selectToStart(); Chris@45: virtual void selectToEnd(); Chris@45: virtual void selectVisible(); Chris@45: virtual void clearSelection(); Chris@45: Chris@45: virtual void cut(); Chris@45: virtual void copy(); Chris@45: virtual void paste(); Chris@215: virtual void pasteAtPlaybackPosition(); Chris@435: virtual void pasteRelative(sv_frame_t offset); Chris@45: virtual void deleteSelected(); Chris@45: Chris@45: virtual void insertInstant(); Chris@435: virtual void insertInstantAt(sv_frame_t); Chris@45: virtual void insertInstantsAtBoundaries(); Chris@184: virtual void insertItemAtSelection(); Chris@435: virtual void insertItemAt(sv_frame_t, sv_frame_t); Chris@45: virtual void renumberInstants(); Chris@537: virtual void subdivideInstantsBy(int); Chris@538: virtual void winnowInstantsBy(int); Chris@45: Chris@45: virtual void documentModified(); Chris@45: virtual void documentRestored(); Chris@45: Chris@45: virtual void layerAdded(Layer *); Chris@45: virtual void layerRemoved(Layer *); Chris@45: virtual void layerAboutToBeDeleted(Layer *); Chris@45: virtual void layerInAView(Layer *, bool); Chris@45: Chris@45: virtual void mainModelChanged(WaveFileModel *); Chris@45: virtual void modelAdded(Model *); Chris@45: virtual void modelAboutToBeDeleted(Model *); Chris@45: Chris@45: virtual void updateMenuStates(); Chris@45: virtual void updateDescriptionLabel() = 0; Chris@45: Chris@78: virtual void modelGenerationFailed(QString, QString) = 0; Chris@78: virtual void modelGenerationWarning(QString, QString) = 0; Chris@78: virtual void modelRegenerationFailed(QString, QString, QString) = 0; Chris@78: virtual void modelRegenerationWarning(QString, QString, QString) = 0; Chris@429: Chris@429: virtual void alignmentComplete(AlignmentModel *); Chris@420: virtual void alignmentFailed(QString) = 0; Chris@45: Chris@45: virtual void rightButtonMenuRequested(Pane *, QPoint point) = 0; Chris@45: Chris@45: virtual void paneAdded(Pane *) = 0; Chris@45: virtual void paneHidden(Pane *) = 0; Chris@45: virtual void paneAboutToBeDeleted(Pane *) = 0; Chris@45: virtual void paneDropAccepted(Pane *, QStringList) = 0; Chris@45: virtual void paneDropAccepted(Pane *, QString) = 0; Chris@55: virtual void paneDeleteButtonClicked(Pane *); Chris@45: Chris@113: virtual void oscReady(); Chris@45: virtual void pollOSC(); Chris@45: virtual void handleOSCMessage(const OSCMessage &) = 0; Chris@45: Chris@45: virtual void contextHelpChanged(const QString &); Chris@45: virtual void inProgressSelectionChanged(); Chris@45: Chris@141: virtual FileOpenStatus openSessionFromRDF(FileSource source); Chris@145: virtual FileOpenStatus openLayersFromRDF(FileSource source); Chris@141: Chris@45: virtual void closeSession() = 0; Chris@45: Chris@452: virtual void emitHideSplash(); Chris@452: Chris@180: virtual void newerVersionAvailable(QString) { } Chris@180: Chris@354: virtual void menuActionMapperInvoked(QObject *); Chris@354: Chris@45: protected: Chris@45: QString m_sessionFile; Chris@45: QString m_audioFile; Chris@45: Document *m_document; Chris@45: Chris@45: PaneStack *m_paneStack; Chris@45: ViewManager *m_viewManager; Chris@45: Layer *m_timeRulerLayer; Chris@45: Chris@475: SoundOptions m_soundOptions; Chris@475: Chris@45: AudioCallbackPlaySource *m_playSource; Chris@574: AudioCallbackRecordTarget *m_recordTarget; Chris@551: breakfastquay::ResamplerWrapper *m_resamplerWrapper; Chris@475: breakfastquay::SystemPlaybackTarget *m_playTarget; // only one of this... Chris@475: breakfastquay::SystemAudioIO *m_audioIO; // ... and this exists Chris@45: Chris@113: class OSCQueueStarter : public QThread Chris@113: { Chris@113: public: Chris@113: OSCQueueStarter(MainWindowBase *mwb) : QThread(mwb), m_mwb(mwb) { } Chris@113: virtual void run() { Chris@113: OSCQueue *queue = new OSCQueue(); // can take a long time Chris@113: m_mwb->m_oscQueue = queue; Chris@113: } Chris@113: private: Chris@113: MainWindowBase *m_mwb; Chris@113: }; Chris@113: Chris@45: OSCQueue *m_oscQueue; Chris@113: OSCQueueStarter *m_oscQueueStarter; Chris@304: void startOSCQueue(); Chris@45: Chris@157: MIDIInput *m_midiInput; Chris@157: Chris@45: RecentFiles m_recentFiles; Chris@54: RecentFiles m_recentTransforms; Chris@45: Chris@45: bool m_documentModified; Chris@45: bool m_openingAudioFile; Chris@45: bool m_abandoning; Chris@45: Chris@45: Labeller *m_labeller; Chris@45: Chris@45: int m_lastPlayStatusSec; Chris@45: mutable QString m_myStatusMessage; Chris@45: Chris@45: bool m_initialDarkBackground; Chris@45: Chris@357: RealTime m_defaultFfwdRwdStep; Chris@357: Chris@483: AudioRecordMode m_audioRecordMode; Chris@571: Chris@378: mutable QLabel *m_statusLabel; Chris@378: QLabel *getStatusLabel() const; Chris@378: Chris@45: WaveFileModel *getMainModel(); Chris@45: const WaveFileModel *getMainModel() const; Chris@45: void createDocument(); Chris@45: Chris@45: Pane *addPaneToStack(); Chris@45: Layer *getSnapLayer() const; Chris@45: Chris@126: typedef std::map > LayerDataDialogMap; Chris@126: typedef std::set > DataDialogSet; Chris@123: typedef std::map ViewDataDialogMap; Chris@123: Chris@123: LayerDataDialogMap m_layerDataDialogMap; Chris@123: ViewDataDialogMap m_viewDataDialogMap; Chris@123: Chris@128: void removeLayerEditDialog(Layer *); Chris@128: Chris@45: class PaneCallback : public SVFileReaderPaneCallback Chris@45: { Chris@45: public: Chris@45: PaneCallback(MainWindowBase *mw) : m_mw(mw) { } Chris@45: virtual Pane *addPane() { return m_mw->addPaneToStack(); } Chris@45: virtual void setWindowSize(int width, int height) { Chris@168: m_mw->resizeConstrained(QSize(width, height)); Chris@45: } Chris@435: virtual void addSelection(sv_frame_t start, sv_frame_t end) { Chris@344: m_mw->m_viewManager->addSelectionQuietly(Selection(start, end)); Chris@45: } Chris@45: protected: Chris@45: MainWindowBase *m_mw; Chris@45: }; Chris@45: Chris@45: class AddPaneCommand : public Command Chris@45: { Chris@45: public: Chris@45: AddPaneCommand(MainWindowBase *mw); Chris@45: virtual ~AddPaneCommand(); Chris@45: Chris@45: virtual void execute(); Chris@45: virtual void unexecute(); Chris@45: virtual QString getName() const; Chris@45: Chris@45: Pane *getPane() { return m_pane; } Chris@45: Chris@45: protected: Chris@45: MainWindowBase *m_mw; Chris@45: Pane *m_pane; // Main window owns this, but I determine its lifespan Chris@45: Pane *m_prevCurrentPane; // I don't own this Chris@45: bool m_added; Chris@45: }; Chris@45: Chris@45: class RemovePaneCommand : public Command Chris@45: { Chris@45: public: Chris@45: RemovePaneCommand(MainWindowBase *mw, Pane *pane); Chris@45: virtual ~RemovePaneCommand(); Chris@45: Chris@45: virtual void execute(); Chris@45: virtual void unexecute(); Chris@45: virtual QString getName() const; Chris@45: Chris@45: protected: Chris@45: MainWindowBase *m_mw; Chris@45: Pane *m_pane; // Main window owns this, but I determine its lifespan Chris@45: Pane *m_prevCurrentPane; // I don't own this Chris@45: bool m_added; Chris@45: }; Chris@45: Chris@45: virtual bool checkSaveModified() = 0; Chris@45: Chris@45: virtual QString getOpenFileName(FileFinder::FileType type); Chris@45: virtual QString getSaveFileName(FileFinder::FileType type); Chris@45: virtual void registerLastOpenedFilePath(FileFinder::FileType type, QString path); Chris@45: Chris@222: virtual QString getDefaultSessionTemplate() const; Chris@251: virtual void setDefaultSessionTemplate(QString); Chris@222: Chris@577: virtual void findTimeRulerLayer(); Chris@577: Chris@475: virtual void createAudioIO(); Chris@556: virtual void deleteAudioIO(); Chris@556: Chris@45: virtual void openHelpUrl(QString url); Chris@483: virtual void openLocalFolder(QString path); Chris@45: Chris@45: virtual void setupMenus() = 0; Chris@45: virtual void updateVisibleRangeDisplay(Pane *p) const = 0; Chris@187: virtual void updatePositionStatusDisplays() const = 0; Chris@45: Chris@354: // Call this after setting up the menu bar, to fix up single-key Chris@426: // shortcuts on OS/X and do any other platform-specific tidying Chris@354: virtual void finaliseMenus(); Chris@354: virtual void finaliseMenu(QMenu *); Chris@394: Chris@426: // Call before finaliseMenus if you wish to have a say in this question Chris@426: void setIconsVisibleInMenus(bool visible) { m_iconsVisibleInMenus = visible; } Chris@426: bool m_iconsVisibleInMenus; Chris@426: Chris@394: // Only used on OS/X to work around a Qt/Cocoa bug, see finaliseMenus Chris@391: QSignalMapper *m_menuShortcutMapper; Chris@391: QList m_appShortcuts; Chris@354: Chris@147: virtual bool shouldCreateNewSessionForRDFAudio(bool *) { return true; } Chris@145: Chris@128: virtual void connectLayerEditDialog(ModelDataTableDialog *dialog); Chris@128: Chris@226: virtual void toXml(QTextStream &stream, bool asTemplate); Chris@45: }; Chris@45: Chris@45: Chris@45: #endif