summaryrefslogtreecommitdiffstats
path: root/src/gui/application/RosegardenGUIApp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/application/RosegardenGUIApp.cpp')
-rw-r--r--src/gui/application/RosegardenGUIApp.cpp8073
1 files changed, 8073 insertions, 0 deletions
diff --git a/src/gui/application/RosegardenGUIApp.cpp b/src/gui/application/RosegardenGUIApp.cpp
new file mode 100644
index 0000000..608ad58
--- /dev/null
+++ b/src/gui/application/RosegardenGUIApp.cpp
@@ -0,0 +1,8073 @@
+/* -*- 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 <[email protected]>,
+ Chris Cannam <[email protected]>,
+ Richard Bown <[email protected]>
+
+ 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 "RosegardenGUIApp.h"
+#include <kapplication.h>
+
+#include "gui/editors/segment/TrackEditor.h"
+#include "gui/editors/segment/TrackButtons.h"
+#include "misc/Debug.h"
+#include "misc/Strings.h"
+#include "gui/application/RosegardenDCOP.h"
+#include "base/AnalysisTypes.h"
+#include "base/AudioPluginInstance.h"
+#include "base/Clipboard.h"
+#include "base/Composition.h"
+#include "base/CompositionTimeSliceAdapter.h"
+#include "base/Configuration.h"
+#include "base/Device.h"
+#include "base/Exception.h"
+#include "base/Instrument.h"
+#include "base/MidiDevice.h"
+#include "base/MidiProgram.h"
+#include "base/NotationTypes.h"
+#include "base/Profiler.h"
+#include "base/RealTime.h"
+#include "base/Segment.h"
+#include "base/SegmentNotationHelper.h"
+#include "base/Selection.h"
+#include "base/Studio.h"
+#include "base/Track.h"
+#include "commands/edit/CopyCommand.h"
+#include "commands/edit/CutCommand.h"
+#include "commands/edit/EventQuantizeCommand.h"
+#include "commands/edit/PasteSegmentsCommand.h"
+#include "commands/edit/TransposeCommand.h"
+#include "commands/edit/AddMarkerCommand.h"
+#include "commands/edit/ModifyMarkerCommand.h"
+#include "commands/edit/RemoveMarkerCommand.h"
+#include "commands/notation/KeyInsertionCommand.h"
+#include "commands/segment/AddTempoChangeCommand.h"
+#include "commands/segment/AddTimeSignatureAndNormalizeCommand.h"
+#include "commands/segment/AddTimeSignatureCommand.h"
+#include "commands/segment/AudioSegmentAutoSplitCommand.h"
+#include "commands/segment/AudioSegmentRescaleCommand.h"
+#include "commands/segment/AudioSegmentSplitCommand.h"
+#include "commands/segment/ChangeCompositionLengthCommand.h"
+#include "commands/segment/CreateTempoMapFromSegmentCommand.h"
+#include "commands/segment/CutRangeCommand.h"
+#include "commands/segment/DeleteRangeCommand.h"
+#include "commands/segment/InsertRangeCommand.h"
+#include "commands/segment/ModifyDefaultTempoCommand.h"
+#include "commands/segment/MoveTracksCommand.h"
+#include "commands/segment/PasteRangeCommand.h"
+#include "commands/segment/RemoveTempoChangeCommand.h"
+#include "commands/segment/SegmentAutoSplitCommand.h"
+#include "commands/segment/SegmentChangeTransposeCommand.h"
+#include "commands/segment/SegmentJoinCommand.h"
+#include "commands/segment/SegmentLabelCommand.h"
+#include "commands/segment/SegmentReconfigureCommand.h"
+#include "commands/segment/SegmentRescaleCommand.h"
+#include "commands/segment/SegmentSplitByPitchCommand.h"
+#include "commands/segment/SegmentSplitByRecordingSrcCommand.h"
+#include "commands/segment/SegmentSplitCommand.h"
+#include "commands/segment/SegmentTransposeCommand.h"
+#include "commands/studio/CreateOrDeleteDeviceCommand.h"
+#include "commands/studio/ModifyDeviceCommand.h"
+#include "document/io/CsoundExporter.h"
+#include "document/io/HydrogenLoader.h"
+#include "document/io/LilyPondExporter.h"
+#include "document/MultiViewCommandHistory.h"
+#include "document/io/RG21Loader.h"
+#include "document/io/MupExporter.h"
+#include "document/io/MusicXmlExporter.h"
+#include "document/RosegardenGUIDoc.h"
+#include "document/ConfigGroups.h"
+#include "gui/application/RosegardenApplication.h"
+#include "gui/dialogs/AddTracksDialog.h"
+#include "gui/dialogs/AudioManagerDialog.h"
+#include "gui/dialogs/AudioPluginDialog.h"
+#include "gui/dialogs/AudioSplitDialog.h"
+#include "gui/dialogs/BeatsBarsDialog.h"
+#include "gui/dialogs/CompositionLengthDialog.h"
+#include "gui/dialogs/ConfigureDialog.h"
+#include "gui/dialogs/CountdownDialog.h"
+#include "gui/dialogs/DocumentConfigureDialog.h"
+#include "gui/dialogs/FileMergeDialog.h"
+#include "gui/dialogs/IdentifyTextCodecDialog.h"
+#include "gui/dialogs/IntervalDialog.h"
+#include "gui/dialogs/LilyPondOptionsDialog.h"
+#include "gui/dialogs/ManageMetronomeDialog.h"
+#include "gui/dialogs/QuantizeDialog.h"
+#include "gui/dialogs/RescaleDialog.h"
+#include "gui/dialogs/SplitByPitchDialog.h"
+#include "gui/dialogs/SplitByRecordingSrcDialog.h"
+#include "gui/dialogs/TempoDialog.h"
+#include "gui/dialogs/TimeDialog.h"
+#include "gui/dialogs/TimeSignatureDialog.h"
+#include "gui/dialogs/TransportDialog.h"
+#include "gui/editors/parameters/InstrumentParameterBox.h"
+#include "gui/editors/parameters/RosegardenParameterArea.h"
+#include "gui/editors/parameters/SegmentParameterBox.h"
+#include "gui/editors/parameters/TrackParameterBox.h"
+#include "gui/editors/segment/segmentcanvas/CompositionView.h"
+#include "gui/editors/segment/ControlEditorDialog.h"
+#include "gui/editors/segment/MarkerEditor.h"
+#include "gui/editors/segment/PlayListDialog.h"
+#include "gui/editors/segment/PlayList.h"
+#include "gui/editors/segment/segmentcanvas/SegmentEraser.h"
+#include "gui/editors/segment/segmentcanvas/SegmentJoiner.h"
+#include "gui/editors/segment/segmentcanvas/SegmentMover.h"
+#include "gui/editors/segment/segmentcanvas/SegmentPencil.h"
+#include "gui/editors/segment/segmentcanvas/SegmentResizer.h"
+#include "gui/editors/segment/segmentcanvas/SegmentSelector.h"
+#include "gui/editors/segment/segmentcanvas/SegmentSplitter.h"
+#include "gui/editors/segment/segmentcanvas/SegmentToolBox.h"
+#include "gui/editors/segment/TrackLabel.h"
+#include "gui/editors/segment/TriggerSegmentManager.h"
+#include "gui/editors/tempo/TempoView.h"
+#include "gui/general/EditViewBase.h"
+#include "gui/kdeext/KStartupLogo.h"
+#include "gui/kdeext/KTmpStatusMsg.h"
+#include "gui/seqmanager/MidiFilterDialog.h"
+#include "gui/seqmanager/SequenceManager.h"
+#include "gui/seqmanager/SequencerMapper.h"
+#include "gui/studio/AudioMixerWindow.h"
+#include "gui/studio/AudioPlugin.h"
+#include "gui/studio/AudioPluginManager.h"
+#include "gui/studio/AudioPluginOSCGUIManager.h"
+#include "gui/studio/BankEditorDialog.h"
+#include "gui/studio/DeviceManagerDialog.h"
+#include "gui/studio/MidiMixerWindow.h"
+#include "gui/studio/RemapInstrumentDialog.h"
+#include "gui/studio/StudioControl.h"
+#include "gui/studio/SynthPluginManagerDialog.h"
+#include "gui/widgets/CurrentProgressDialog.h"
+#include "gui/widgets/ProgressBar.h"
+#include "gui/widgets/ProgressDialog.h"
+#include "LircClient.h"
+#include "LircCommander.h"
+#include "RosegardenGUIView.h"
+#include "RosegardenIface.h"
+#include "SetWaitCursor.h"
+#include "sound/AudioFile.h"
+#include "sound/AudioFileManager.h"
+#include "sound/MappedCommon.h"
+#include "sound/MappedComposition.h"
+#include "sound/MappedEvent.h"
+#include "sound/MappedStudio.h"
+#include "sound/MidiFile.h"
+#include "sound/PluginIdentifier.h"
+#include "sound/SoundDriver.h"
+#include "StartupTester.h"
+#include <dcopclient.h>
+#include <dcopobject.h>
+#include <dcopref.h>
+#include <kaction.h>
+#include <kconfig.h>
+#include <kdcopactionproxy.h>
+#include <kdockwidget.h>
+#include <kedittoolbar.h>
+#include <kfiledialog.h>
+#include <kglobal.h>
+#include <kinputdialog.h>
+#include <kio/netaccess.h>
+#include <kkeydialog.h>
+#include <klocale.h>
+#include <kmainwindow.h>
+#include <kmessagebox.h>
+#include <kmimetype.h>
+#include <kprocess.h>
+#include <kstatusbar.h>
+#include <kstdaccel.h>
+#include <kstdaction.h>
+#include <kstddirs.h>
+#include <ktempfile.h>
+#include <ktip.h>
+#include <ktoolbar.h>
+#include <kurl.h>
+#include <kxmlguiclient.h>
+#include <qaccel.h>
+#include <qcanvas.h>
+#include <qcstring.h>
+#include <qcursor.h>
+#include <qdatastream.h>
+#include <qdialog.h>
+#include <qdir.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qiconset.h>
+#include <qinputdialog.h>
+#include <qlabel.h>
+#include <qobject.h>
+#include <qobjectlist.h>
+#include <qpixmap.h>
+#include <qpopupmenu.h>
+#include <qpushbutton.h>
+#include <qregexp.h>
+#include <qslider.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qtextcodec.h>
+#include <qtimer.h>
+#include <qvaluevector.h>
+#include <qwidget.h>
+
+#ifdef HAVE_LIBJACK
+#include <jack/jack.h>
+#endif
+
+
+namespace Rosegarden
+{
+
+RosegardenGUIApp::RosegardenGUIApp(bool useSequencer,
+ bool useExistingSequencer,
+ QObject *startupStatusMessageReceiver)
+ : DCOPObject("RosegardenIface"), RosegardenIface(this), KDockMainWindow(0),
+ m_actionsSetup(false),
+ m_fileRecent(0),
+ m_view(0),
+ m_swapView(0),
+ m_mainDockWidget(0),
+ m_dockLeft(0),
+ m_doc(0),
+ m_sequencerProcess(0),
+ m_sequencerCheckedIn(false),
+#ifdef HAVE_LIBJACK
+ m_jackProcess(0),
+#endif
+ m_zoomSlider(0),
+ m_seqManager(0),
+ m_transport(0),
+ m_audioManagerDialog(0),
+ m_originatingJump(false),
+ m_storedLoopStart(0),
+ m_storedLoopEnd(0),
+ m_useSequencer(useSequencer),
+ m_dockVisible(true),
+ m_autoSaveTimer(new QTimer(this)),
+ m_clipboard(new Clipboard),
+ m_playList(0),
+ m_deviceManager(0),
+ m_synthManager(0),
+ m_audioMixer(0),
+ m_midiMixer(0),
+ m_bankEditor(0),
+ m_markerEditor(0),
+ m_tempoView(0),
+ m_triggerSegmentManager(0),
+#ifdef HAVE_LIBLO
+ m_pluginGUIManager(new AudioPluginOSCGUIManager(this)),
+#endif
+ m_playTimer(new QTimer(this)),
+ m_stopTimer(new QTimer(this)),
+ m_startupTester(0),
+#ifdef HAVE_LIRC
+ m_lircClient(0),
+ m_lircCommander(0),
+#endif
+ m_haveAudioImporter(false),
+ m_firstRun(false),
+ m_parameterArea(0)
+{
+ m_myself = this;
+
+
+ if (startupStatusMessageReceiver) {
+ QObject::connect(this, SIGNAL(startupStatusMessage(QString)),
+ startupStatusMessageReceiver,
+ SLOT(slotShowStatusMessage(QString)));
+ }
+
+ // Try to start the sequencer
+ //
+ if (m_useSequencer) {
+
+#ifdef HAVE_LIBJACK
+#define OFFER_JACK_START_OPTION 1
+#ifdef OFFER_JACK_START_OPTION
+ // First we check if jackd is running allready
+
+ std::string jackClientName = "rosegarden";
+
+ // attempt connection to JACK server
+ //
+ jack_client_t* testJackClient;
+ testJackClient = jack_client_new(jackClientName.c_str());
+ if (testJackClient == 0 ) {
+
+ // If no connection to JACK
+ // try to launch JACK - if the configuration wants us to.
+ if (!launchJack()) {
+ KStartupLogo::hideIfStillThere();
+ KMessageBox::error(this, i18n("Attempted to launch JACK audio daemon failed. Audio will be disabled.\nPlease check configuration (Settings -> Configure Rosegarden -> Audio -> Startup)\n and restart."));
+ }
+ } else {
+ //this client was just for testing
+ jack_client_close(testJackClient);
+ }
+#endif // OFFER_JACK_START_OPTION
+#endif // HAVE_LIBJACK
+
+ emit startupStatusMessage(i18n("Starting sequencer..."));
+ launchSequencer(useExistingSequencer);
+
+ } else
+ RG_DEBUG << "RosegardenGUIApp : don't use sequencer\n";
+
+ // Plugin manager
+ //
+ emit startupStatusMessage(i18n("Initializing plugin manager..."));
+ m_pluginManager = new AudioPluginManager();
+
+ // call inits to invoke all other construction parts
+ //
+ emit startupStatusMessage(i18n("Initializing view..."));
+ initStatusBar();
+ setupActions();
+ iFaceDelayedInit(this);
+ initZoomToolbar();
+
+ QPixmap dummyPixmap; // any icon will do
+ m_mainDockWidget = createDockWidget("Rosegarden MainDockWidget", dummyPixmap, 0L, "main_dock_widget");
+ // allow others to dock to the left and right sides only
+ m_mainDockWidget->setDockSite(KDockWidget::DockLeft | KDockWidget::DockRight);
+ // forbit docking abilities of m_mainDockWidget itself
+ m_mainDockWidget->setEnableDocking(KDockWidget::DockNone);
+ setView(m_mainDockWidget); // central widget in a KDE mainwindow
+ setMainDockWidget(m_mainDockWidget); // master dockwidget
+
+ m_dockLeft = createDockWidget("params dock", dummyPixmap, 0L,
+ i18n("Special Parameters"));
+ m_dockLeft->manualDock(m_mainDockWidget, // dock target
+ KDockWidget::DockLeft, // dock site
+ 20); // relation target/this (in percent)
+
+ connect(m_dockLeft, SIGNAL(iMBeingClosed()),
+ this, SLOT(slotParametersClosed()));
+ connect(m_dockLeft, SIGNAL(hasUndocked()),
+ this, SLOT(slotParametersClosed()));
+ // Apparently, hasUndocked() is emitted when the dock widget's
+ // 'close' button on the dock handle is clicked.
+ connect(m_mainDockWidget, SIGNAL(docking(KDockWidget*, KDockWidget::DockPosition)),
+ this, SLOT(slotParametersDockedBack(KDockWidget*, KDockWidget::DockPosition)));
+
+ stateChanged("parametersbox_closed", KXMLGUIClient::StateReverse);
+
+ RosegardenGUIDoc* doc = new RosegardenGUIDoc(this, m_pluginManager);
+
+ m_parameterArea = new RosegardenParameterArea(m_dockLeft);
+ m_dockLeft->setWidget(m_parameterArea);
+
+ // Populate the parameter-box area with the respective
+ // parameter box widgets.
+
+ m_segmentParameterBox = new SegmentParameterBox(doc, m_parameterArea);
+ m_parameterArea->addRosegardenParameterBox(m_segmentParameterBox);
+ m_trackParameterBox = new TrackParameterBox(doc, m_parameterArea);
+ m_parameterArea->addRosegardenParameterBox(m_trackParameterBox);
+ m_instrumentParameterBox = new InstrumentParameterBox(doc, m_parameterArea);
+ m_parameterArea->addRosegardenParameterBox(m_instrumentParameterBox);
+
+ // Lookup the configuration parameter that specifies the default
+ // arrangement, and instantiate it.
+
+ kapp->config()->setGroup(GeneralOptionsConfigGroup);
+ m_parameterArea->setArrangement((RosegardenParameterArea::Arrangement)
+ kapp->config()->readUnsignedNumEntry("sidebarstyle",
+ RosegardenParameterArea::CLASSIC_STYLE));
+
+ m_dockLeft->update();
+
+ connect(m_instrumentParameterBox,
+ SIGNAL(selectPlugin(QWidget *, InstrumentId, int)),
+ this,
+ SLOT(slotShowPluginDialog(QWidget *, InstrumentId, int)));
+
+ connect(m_instrumentParameterBox,
+ SIGNAL(showPluginGUI(InstrumentId, int)),
+ this,
+ SLOT(slotShowPluginGUI(InstrumentId, int)));
+
+ // relay this through our own signal so that others can use it too
+ connect(m_instrumentParameterBox,
+ SIGNAL(instrumentParametersChanged(InstrumentId)),
+ this,
+ SIGNAL(instrumentParametersChanged(InstrumentId)));
+
+ connect(this,
+ SIGNAL(instrumentParametersChanged(InstrumentId)),
+ m_instrumentParameterBox,
+ SLOT(slotInstrumentParametersChanged(InstrumentId)));
+
+ connect(this,
+ SIGNAL(pluginSelected(InstrumentId, int, int)),
+ m_instrumentParameterBox,
+ SLOT(slotPluginSelected(InstrumentId, int, int)));
+
+ connect(this,
+ SIGNAL(pluginBypassed(InstrumentId, int, bool)),
+ m_instrumentParameterBox,
+ SLOT(slotPluginBypassed(InstrumentId, int, bool)));
+
+ // Load the initial document (this includes doc's own autoload)
+ //
+ setDocument(doc);
+
+ emit startupStatusMessage(i18n("Starting sequence manager..."));
+
+ // transport is created by setupActions()
+ m_seqManager = new SequenceManager(m_doc, getTransport());
+
+ if (m_useSequencer) {
+ // Check the sound driver status and warn the user of any
+ // problems. This warning has to happen early, in case it
+ // affects the ability to load plugins etc from a file on the
+ // command line.
+ m_seqManager->checkSoundDriverStatus(true);
+ }
+
+ if (m_view) {
+ connect(m_seqManager, SIGNAL(controllerDeviceEventReceived(MappedEvent *)),
+ m_view, SLOT(slotControllerDeviceEventReceived(MappedEvent *)));
+ }
+
+ if (m_seqManager->getSoundDriverStatus() & AUDIO_OK) {
+ slotStateChanged("got_audio", true);
+ } else {
+ slotStateChanged("got_audio", false);
+ }
+
+ // If we're restarting the gui then make sure any transient
+ // studio objects are cleared away.
+ emit startupStatusMessage(i18n("Clearing studio data..."));
+ m_seqManager->reinitialiseSequencerStudio();
+
+ // Send the transport control statuses for MMC and JACK
+ //
+ m_seqManager->sendTransportControlStatuses();
+
+ // Now autoload
+ //
+ stateChanged("new_file");
+ stateChanged("have_segments", KXMLGUIClient::StateReverse);
+ stateChanged("have_selection", KXMLGUIClient::StateReverse);
+ slotTestClipboard();
+
+ // Check for lack of MIDI devices and disable Studio options accordingly
+ //
+ if (!m_doc->getStudio().haveMidiDevices())
+ stateChanged("got_midi_devices", KXMLGUIClient::StateReverse);
+
+ emit startupStatusMessage(i18n("Starting..."));
+
+ setupFileDialogSpeedbar();
+ readOptions();
+
+ // All toolbars should be created before this is called
+ setAutoSaveSettings(MainWindowConfigGroup, true);
+
+#ifdef HAVE_LIRC
+
+ try {
+ m_lircClient = new LircClient();
+ } catch (Exception e) {
+ RG_DEBUG << e.getMessage().c_str() << endl;
+ // continue without
+ m_lircClient = 0;
+ }
+ if (m_lircClient) {
+ m_lircCommander = new LircCommander(m_lircClient, this);
+ }
+#endif
+
+ stateChanged("have_project_packager", KXMLGUIClient::StateReverse);
+ stateChanged("have_lilypondview", KXMLGUIClient::StateReverse);
+ QTimer::singleShot(1000, this, SLOT(slotTestStartupTester()));
+}
+
+RosegardenGUIApp::~RosegardenGUIApp()
+{
+ RG_DEBUG << "~RosegardenGUIApp()\n";
+
+ if (getView() &&
+ getView()->getTrackEditor() &&
+ getView()->getTrackEditor()->getSegmentCanvas()) {
+ getView()->getTrackEditor()->getSegmentCanvas()->endAudioPreviewGeneration();
+ }
+
+#ifdef HAVE_LIBLO
+ delete m_pluginGUIManager;
+#endif
+
+ if (isSequencerRunning() && !isSequencerExternal()) {
+ m_sequencerProcess->blockSignals(true);
+ rgapp->sequencerSend("quit()");
+ usleep(300000);
+ delete m_sequencerProcess;
+ }
+
+ delete m_jumpToQuickMarkerAction;
+ delete m_setQuickMarkerAction;
+
+ delete m_transport;
+
+ delete m_seqManager;
+
+#ifdef HAVE_LIRC
+
+ delete m_lircCommander;
+ delete m_lircClient;
+#endif
+
+ delete m_doc;
+ Profiles::getInstance()->dump();
+}
+
+void RosegardenGUIApp::setupActions()
+{
+ // setup File menu
+ // New Window ?
+ KStdAction::openNew (this, SLOT(slotFileNew()), actionCollection());
+ KStdAction::open (this, SLOT(slotFileOpen()), actionCollection());
+ m_fileRecent = KStdAction::openRecent(this,
+ SLOT(slotFileOpenRecent(const KURL&)),
+ actionCollection());
+ KStdAction::save (this, SLOT(slotFileSave()), actionCollection());
+ KStdAction::saveAs(this, SLOT(slotFileSaveAs()), actionCollection());
+ KStdAction::revert(this, SLOT(slotRevertToSaved()), actionCollection());
+ KStdAction::close (this, SLOT(slotFileClose()), actionCollection());
+ KStdAction::print (this, SLOT(slotFilePrint()), actionCollection());
+ KStdAction::printPreview (this, SLOT(slotFilePrintPreview()), actionCollection());
+
+ new KAction(i18n("Import Rosegarden &Project file..."), 0, 0, this,
+ SLOT(slotImportProject()), actionCollection(),
+ "file_import_project");
+
+ new KAction(i18n("Import &MIDI file..."), 0, 0, this,
+ SLOT(slotImportMIDI()), actionCollection(),
+ "file_import_midi");
+
+ new KAction(i18n("Import &Rosegarden 2.1 file..."), 0, 0, this,
+ SLOT(slotImportRG21()), actionCollection(),
+ "file_import_rg21");
+
+ new KAction(i18n("Import &Hydrogen file..."), 0, 0, this,
+ SLOT(slotImportHydrogen()), actionCollection(),
+ "file_import_hydrogen");
+
+ new KAction(i18n("Merge &File..."), 0, 0, this,
+ SLOT(slotMerge()), actionCollection(),
+ "file_merge");
+
+ new KAction(i18n("Merge &MIDI file..."), 0, 0, this,
+ SLOT(slotMergeMIDI()), actionCollection(),
+ "file_merge_midi");
+
+ new KAction(i18n("Merge &Rosegarden 2.1 file..."), 0, 0, this,
+ SLOT(slotMergeRG21()), actionCollection(),
+ "file_merge_rg21");
+
+ new KAction(i18n("Merge &Hydrogen file..."), 0, 0, this,
+ SLOT(slotMergeHydrogen()), actionCollection(),
+ "file_merge_hydrogen");
+
+ new KAction(i18n("Export Rosegarden &Project file..."), 0, 0, this,
+ SLOT(slotExportProject()), actionCollection(),
+ "file_export_project");
+
+ new KAction(i18n("Export &MIDI file..."), 0, 0, this,
+ SLOT(slotExportMIDI()), actionCollection(),
+ "file_export_midi");
+
+ new KAction(i18n("Export &LilyPond file..."), 0, 0, this,
+ SLOT(slotExportLilyPond()), actionCollection(),
+ "file_export_lilypond");
+
+ new KAction(i18n("Export Music&XML file..."), 0, 0, this,
+ SLOT(slotExportMusicXml()), actionCollection(),
+ "file_export_musicxml");
+
+ new KAction(i18n("Export &Csound score file..."), 0, 0, this,
+ SLOT(slotExportCsound()), actionCollection(),
+ "file_export_csound");
+
+ new KAction(i18n("Export M&up file..."), 0, 0, this,
+ SLOT(slotExportMup()), actionCollection(),
+ "file_export_mup");
+
+ new KAction(i18n("Print &with LilyPond..."), 0, 0, this,
+ SLOT(slotPrintLilyPond()), actionCollection(),
+ "file_print_lilypond");
+
+ new KAction(i18n("Preview with Lil&yPond..."), 0, 0, this,
+ SLOT(slotPreviewLilyPond()), actionCollection(),
+ "file_preview_lilypond");
+
+ new KAction(i18n("Play&list"), 0, 0, this,
+ SLOT(slotPlayList()), actionCollection(),
+ "file_show_playlist");
+
+ KStdAction::quit (this, SLOT(slotQuit()), actionCollection());
+
+ // help menu
+ new KAction(i18n("Rosegarden &Tutorial"), 0, 0, this,
+ SLOT(slotTutorial()), actionCollection(),
+ "tutorial");
+
+ new KAction(i18n("&Bug Reporting Guidelines"), 0, 0, this,
+ SLOT(slotBugGuidelines()), actionCollection(),
+ "guidelines");
+
+ // setup edit menu
+ KStdAction::cut (this, SLOT(slotEditCut()), actionCollection());
+ KStdAction::copy (this, SLOT(slotEditCopy()), actionCollection());
+ KStdAction::paste (this, SLOT(slotEditPaste()), actionCollection());
+
+ //
+ // undo/redo actions are special in that they are connected to
+ // slots later on, when the current document is set up - see
+ // MultiViewCommandHistory::attachView
+ //
+ new KToolBarPopupAction(i18n("Und&o"),
+ "undo",
+ KStdAccel::shortcut(KStdAccel::Undo),
+ actionCollection(),
+ KStdAction::stdName(KStdAction::Undo));
+
+ new KToolBarPopupAction(i18n("Re&do"),
+ "redo",
+ KStdAccel::shortcut(KStdAccel::Redo),
+ actionCollection(),
+ KStdAction::stdName(KStdAction::Redo));
+ /////
+
+
+
+ // setup Settings menu
+ //
+ m_viewToolBar = KStdAction::showToolbar (this, SLOT(slotToggleToolBar()), actionCollection(),
+ "show_stock_toolbar");
+
+ m_viewToolsToolBar = new KToggleAction(i18n("Show T&ools Toolbar"), 0, this,
+ SLOT(slotToggleToolsToolBar()), actionCollection(),
+ "show_tools_toolbar");
+
+ m_viewTracksToolBar = new KToggleAction(i18n("Show Trac&ks Toolbar"), 0, this,
+ SLOT(slotToggleTracksToolBar()), actionCollection(),
+ "show_tracks_toolbar");
+
+ m_viewEditorsToolBar = new KToggleAction(i18n("Show &Editors Toolbar"), 0, this,
+ SLOT(slotToggleEditorsToolBar()), actionCollection(),
+ "show_editors_toolbar");
+
+ m_viewTransportToolBar = new KToggleAction(i18n("Show Trans&port Toolbar"), 0, this,
+ SLOT(slotToggleTransportToolBar()), actionCollection(),
+ "show_transport_toolbar");
+
+ m_viewZoomToolBar = new KToggleAction(i18n("Show &Zoom Toolbar"), 0, this,
+ SLOT(slotToggleZoomToolBar()), actionCollection(),
+ "show_zoom_toolbar");
+
+ m_viewStatusBar = KStdAction::showStatusbar(this, SLOT(slotToggleStatusBar()),
+ actionCollection(), "show_status_bar");
+
+ m_viewTransport = new KToggleAction(i18n("Show Tra&nsport"), Key_T, this,
+ SLOT(slotToggleTransport()),
+ actionCollection(),
+ "show_transport");
+
+ m_viewTrackLabels = new KToggleAction(i18n("Show Track &Labels"), 0, this,
+ SLOT(slotToggleTrackLabels()),
+ actionCollection(),
+ "show_tracklabels");
+
+ m_viewRulers = new KToggleAction(i18n("Show Playback Position R&uler"), 0, this,
+ SLOT(slotToggleRulers()),
+ actionCollection(),
+ "show_rulers");
+
+ m_viewTempoRuler = new KToggleAction(i18n("Show Te&mpo Ruler"), 0, this,
+ SLOT(slotToggleTempoRuler()),
+ actionCollection(),
+ "show_tempo_ruler");
+
+ m_viewChordNameRuler = new KToggleAction(i18n("Show Cho&rd Name Ruler"), 0, this,
+ SLOT(slotToggleChordNameRuler()),
+ actionCollection(),
+ "show_chord_name_ruler");
+
+
+ m_viewPreviews = new KToggleAction(i18n("Show Segment Pre&views"), 0, this,
+ SLOT(slotTogglePreviews()),
+ actionCollection(),
+ "show_previews");
+
+ new KAction(i18n("Show Special &Parameters"), Key_P, this,
+ SLOT(slotDockParametersBack()),
+ actionCollection(),
+ "show_inst_segment_parameters");
+
+ KStdAction::tipOfDay( this, SLOT( slotShowTip() ), actionCollection() );
+
+ // Standard Actions
+ //
+ KStdAction::saveOptions(this,
+ SLOT(slotSaveOptions()),
+ actionCollection());
+
+ KStdAction::preferences(this,
+ SLOT(slotConfigure()),
+ actionCollection());
+
+ KStdAction::keyBindings(this,
+ SLOT(slotEditKeys()),
+ actionCollection());
+
+ KStdAction::configureToolbars(this,
+ SLOT(slotEditToolbars()),
+ actionCollection());
+
+ KRadioAction *action = 0;
+
+ // Create the select icon
+ //
+ QString pixmapDir = KGlobal::dirs()->findResource("appdata", "pixmaps/");
+ QCanvasPixmap pixmap(pixmapDir + "/toolbar/select.xpm");
+ QIconSet icon = QIconSet(pixmap);
+
+ // TODO : add some shortcuts here
+ action = new KRadioAction(i18n("&Select and Edit"), icon, Key_F2,
+ this, SLOT(slotPointerSelected()),
+ actionCollection(), "select");
+ action->setExclusiveGroup("segmenttools");
+
+ action = new KRadioAction(i18n("&Draw"), "pencil", Key_F3,
+ this, SLOT(slotDrawSelected()),
+ actionCollection(), "draw");
+ action->setExclusiveGroup("segmenttools");
+
+ action = new KRadioAction(i18n("&Erase"), "eraser", Key_F4,
+ this, SLOT(slotEraseSelected()),
+ actionCollection(), "erase");
+ action->setExclusiveGroup("segmenttools");
+
+ action = new KRadioAction(i18n("&Move"), "move", Key_F5,
+ this, SLOT(slotMoveSelected()),
+ actionCollection(), "move");
+ action->setExclusiveGroup("segmenttools");
+
+ pixmap.load(pixmapDir + "/toolbar/resize.xpm");
+ icon = QIconSet(pixmap);
+ action = new KRadioAction(i18n("&Resize"), icon, Key_F6,
+ this, SLOT(slotResizeSelected()),
+ actionCollection(), "resize");
+ action->setExclusiveGroup("segmenttools");
+
+ pixmap.load(pixmapDir + "/toolbar/split.xpm");
+ icon = QIconSet(pixmap);
+ action = new KRadioAction(i18n("&Split"), icon, Key_F7,
+ this, SLOT(slotSplitSelected()),
+ actionCollection(), "split");
+ action->setExclusiveGroup("segmenttools");
+
+ pixmap.load(pixmapDir + "/toolbar/join.xpm");
+ icon = QIconSet(pixmap);
+ action = new KRadioAction(i18n("&Join"), icon, 0,
+ this, SLOT(slotJoinSelected()),
+ actionCollection(), "join");
+ action->setExclusiveGroup("segmenttools");
+
+
+ new KAction(i18n("&Harmonize"), 0, this,
+ SLOT(slotHarmonizeSelection()), actionCollection(),
+ "harmonize_selection");
+
+ pixmap.load(pixmapDir + "/toolbar/event-insert-timesig.png");
+ icon = QIconSet(pixmap);
+ new KAction(AddTimeSignatureCommand::getGlobalName(),
+ icon, 0,
+ this, SLOT(slotEditTimeSignature()),
+ actionCollection(), "add_time_signature");
+
+ new KAction(i18n("Open Tempo and Time Signature Editor"), 0, this,
+ SLOT(slotEditTempos()), actionCollection(), "edit_tempos");
+
+ //
+ // Edit menu
+ //
+ new KAction(i18n("Cut Range"), Key_X + CTRL + SHIFT, this,
+ SLOT(slotCutRange()), actionCollection(),
+ "cut_range");
+
+ new KAction(i18n("Copy Range"), Key_C + CTRL + SHIFT, this,
+ SLOT(slotCopyRange()), actionCollection(),
+ "copy_range");
+
+ new KAction(i18n("Paste Range"), Key_V + CTRL + SHIFT, this,
+ SLOT(slotPasteRange()), actionCollection(),
+ "paste_range");
+/*
+ new KAction(i18n("Delete Range"), Key_Delete + SHIFT, this,
+ SLOT(slotDeleteRange()), actionCollection(),
+ "delete_range");
+*/
+ new KAction(i18n("Insert Range..."), Key_Insert + SHIFT, this,
+ SLOT(slotInsertRange()), actionCollection(),
+ "insert_range");
+
+ new KAction(i18n("De&lete"), Key_Delete, this,
+ SLOT(slotDeleteSelectedSegments()), actionCollection(),
+ "delete");
+
+ new KAction(i18n("Select &All Segments"), Key_A + CTRL, this,
+ SLOT(slotSelectAll()), actionCollection(),
+ "select_all");
+
+ pixmap.load(pixmapDir + "/toolbar/event-insert-tempo.png");
+ icon = QIconSet(pixmap);
+ new KAction(AddTempoChangeCommand::getGlobalName(),
+ icon, 0,
+ this, SLOT(slotEditTempo()),
+ actionCollection(), "add_tempo");
+
+ new KAction(ChangeCompositionLengthCommand::getGlobalName(),
+ 0,
+ this, SLOT(slotChangeCompositionLength()),
+ actionCollection(), "change_composition_length");
+
+ new KAction(i18n("Edit Mar&kers..."), Key_K + CTRL, this,
+ SLOT(slotEditMarkers()),
+ actionCollection(), "edit_markers");
+
+ new KAction(i18n("Edit Document P&roperties..."), 0, this,
+ SLOT(slotEditDocumentProperties()),
+ actionCollection(), "edit_doc_properties");
+
+
+ //
+ // Segments menu
+ //
+ new KAction(i18n("Open in &Default Editor"), Key_Return, this,
+ SLOT(slotEdit()), actionCollection(),
+ "edit_default");
+
+ pixmap.load(pixmapDir + "/toolbar/matrix.png");
+ icon = QIconSet(pixmap);
+ new KAction(i18n("Open in Matri&x Editor"), icon, Key_M, this,
+ SLOT(slotEditInMatrix()), actionCollection(),
+ "edit_matrix");
+
+ pixmap.load(pixmapDir + "/toolbar/matrix-percussion.png");
+ icon = QIconSet(pixmap);
+ new KAction(i18n("Open in &Percussion Matrix Editor"), icon, Key_D, this,
+ SLOT(slotEditInPercussionMatrix()), actionCollection(),
+ "edit_percussion_matrix");
+
+ pixmap.load(pixmapDir + "/toolbar/notation.png");
+ icon = QIconSet(pixmap);
+ new KAction(i18n("Open in &Notation Editor"), icon, Key_N, this,
+ SLOT(slotEditAsNotation()), actionCollection(),
+ "edit_notation");
+
+ pixmap.load(pixmapDir + "/toolbar/eventlist.png");
+ icon = QIconSet(pixmap);
+ new KAction(i18n("Open in &Event List Editor"), icon, Key_E, this,
+ SLOT(slotEditInEventList()), actionCollection(),
+ "edit_event_list");
+
+ pixmap.load(pixmapDir + "/toolbar/quantize.png");
+ icon = QIconSet(pixmap);
+ new KAction(i18n("&Quantize..."), icon, Key_Equal, this,
+ SLOT(slotQuantizeSelection()), actionCollection(),
+ "quantize_selection");
+
+ new KAction(SegmentLabelCommand::getGlobalName(),
+ 0,
+ this, SLOT(slotRelabelSegments()),
+ actionCollection(), "relabel_segment");
+
+ new KAction(SegmentTransposeCommand::getGlobalName(),
+ 0,
+ this, SLOT(slotTransposeSegments()),
+ actionCollection(), "transpose");
+
+ new KAction(i18n("Repeat Last Quantize"), Key_Plus, this,
+ SLOT(slotRepeatQuantizeSelection()), actionCollection(),
+ "repeat_quantize");
+
+ new KAction(SegmentRescaleCommand::getGlobalName(), 0, this,
+ SLOT(slotRescaleSelection()), actionCollection(),
+ "rescale");
+
+ new KAction(SegmentAutoSplitCommand::getGlobalName(), 0, this,
+ SLOT(slotAutoSplitSelection()), actionCollection(),
+ "auto_split");
+
+ new KAction(SegmentSplitByPitchCommand::getGlobalName(), 0, this,
+ SLOT(slotSplitSelectionByPitch()), actionCollection(),
+ "split_by_pitch");
+
+ new KAction(SegmentSplitByRecordingSrcCommand::getGlobalName(), 0, this,
+ SLOT(slotSplitSelectionByRecordedSrc()), actionCollection(),
+ "split_by_recording");
+
+ new KAction(i18n("Split at Time..."), 0, this,
+ SLOT(slotSplitSelectionAtTime()), actionCollection(),
+ "split_at_time");
+
+ new KAction(i18n("Jog &Left"), Key_Left + ALT, this,
+ SLOT(slotJogLeft()), actionCollection(),
+ "jog_left");
+
+ new KAction(i18n("Jog &Right"), Key_Right + ALT, this,
+ SLOT(slotJogRight()), actionCollection(),
+ "jog_right");
+
+ new KAction(i18n("Set Start Time..."), 0, this,
+ SLOT(slotSetSegmentStartTimes()), actionCollection(),
+ "set_segment_start");
+
+ new KAction(i18n("Set Duration..."), 0, this,
+ SLOT(slotSetSegmentDurations()), actionCollection(),
+ "set_segment_duration");
+
+ new KAction(SegmentJoinCommand::getGlobalName(),
+ Key_J + CTRL,
+ this, SLOT(slotJoinSegments()),
+ actionCollection(), "join_segments");
+
+ new KAction(i18n("Turn Re&peats into Copies"),
+ 0,
+ this, SLOT(slotRepeatingSegments()),
+ actionCollection(), "repeats_to_real_copies");
+
+ new KAction(i18n("Manage Tri&ggered Segments"), 0,
+ this, SLOT(slotManageTriggerSegments()),
+ actionCollection(), "manage_trigger_segments");
+
+ new KAction(i18n("Set Tempos from &Beat Segment"), 0, this,
+ SLOT(slotGrooveQuantize()), actionCollection(),
+ "groove_quantize");
+
+ new KAction(i18n("Set &Tempo to Audio Segment Duration"), 0, this,
+ SLOT(slotTempoToSegmentLength()), actionCollection(),
+ "set_tempo_to_segment_length");
+
+ pixmap.load(pixmapDir + "/toolbar/manage-audio-segments.xpm");
+ icon = QIconSet(pixmap);
+ new KAction(i18n("Manage A&udio Files"), icon,
+ Key_U + CTRL,
+ this, SLOT(slotAudioManager()),
+ actionCollection(), "audio_manager");
+
+ m_viewSegmentLabels = new KToggleAction(i18n("Show Segment Labels"), 0, this,
+ SLOT(slotToggleSegmentLabels()), actionCollection(),
+ "show_segment_labels");
+
+ //
+ // Tracks menu
+ //
+ pixmap.load(pixmapDir + "/toolbar/add_tracks.png");
+ icon = QIconSet(pixmap);
+ new KAction(i18n("Add &Track"), icon, CTRL + Key_T,
+ this, SLOT(slotAddTrack()),
+ actionCollection(), "add_track");
+
+ new KAction(i18n("&Add Tracks..."), 0,
+ this, SLOT(slotAddTracks()),
+ actionCollection(), "add_tracks");
+
+ pixmap.load(pixmapDir + "/toolbar/delete_track.png");
+ icon = QIconSet(pixmap);
+ new KAction(i18n("D&elete Track"), icon, CTRL + Key_D,
+ this, SLOT(slotDeleteTrack()),
+ actionCollection(), "delete_track");
+
+ pixmap.load(pixmapDir + "/toolbar/move_track_down.png");
+ icon = QIconSet(pixmap);
+ new KAction(i18n("Move Track &Down"), icon, SHIFT + Key_Down,
+ this, SLOT(slotMoveTrackDown()),
+ actionCollection(), "move_track_down");
+
+ pixmap.load(pixmapDir + "/toolbar/move_track_up.png");
+ icon = QIconSet(pixmap);
+ new KAction(i18n("Move Track &Up"), icon, SHIFT + Key_Up,
+ this, SLOT(slotMoveTrackUp()),
+ actionCollection(), "move_track_up");
+
+ new KAction(i18n("Select &Next Track"),
+ Key_Down,
+ this, SLOT(slotTrackDown()),
+ actionCollection(), "select_next_track");
+
+ new KAction(i18n("Select &Previous Track"),
+ Key_Up,
+ this, SLOT(slotTrackUp()),
+ actionCollection(), "select_previous_track");
+
+ new KAction(i18n("Mute or Unmute Track"),
+ Key_U,
+ this, SLOT(slotToggleMutedCurrentTrack()),
+ actionCollection(), "toggle_mute_track");
+
+ new KAction(i18n("Arm or Un-arm Track for Record"),
+ Key_R,
+ this, SLOT(slotToggleRecordCurrentTrack()),
+ actionCollection(), "toggle_arm_track");
+
+ pixmap.load(pixmapDir + "/toolbar/mute-all.png");
+ icon = QIconSet(pixmap);
+ new KAction(i18n("&Mute all Tracks"), icon, 0,
+ this, SLOT(slotMuteAllTracks()),
+ actionCollection(), "mute_all_tracks");
+
+ pixmap.load(pixmapDir + "/toolbar/un-mute-all.png");
+ icon = QIconSet(pixmap);
+ new KAction(i18n("&Unmute all Tracks"), icon, 0,
+ this, SLOT(slotUnmuteAllTracks()),
+ actionCollection(), "unmute_all_tracks");
+
+ new KAction(i18n("&Remap Instruments..."), 0, this,
+ SLOT(slotRemapInstruments()),
+ actionCollection(), "remap_instruments");
+
+ //
+ // Studio menu
+ //
+ pixmap.load(pixmapDir + "/toolbar/mixer.png");
+ icon = QIconSet(pixmap);
+ new KAction(i18n("&Audio Mixer"), icon, 0, this,
+ SLOT(slotOpenAudioMixer()),
+ actionCollection(), "audio_mixer");
+
+ pixmap.load(pixmapDir + "/toolbar/midimixer.png");
+ icon = QIconSet(pixmap);
+ new KAction(i18n("Midi Mi&xer"), icon, 0, this,
+ SLOT(slotOpenMidiMixer()),
+ actionCollection(), "midi_mixer");
+
+ pixmap.load(pixmapDir + "/toolbar/manage-midi-devices.xpm");
+ icon = QIconSet(pixmap);
+ new KAction(i18n("Manage MIDI &Devices"), icon, 0, this,
+ SLOT(slotManageMIDIDevices()),
+ actionCollection(), "manage_devices");
+
+ pixmap.load(pixmapDir + "/toolbar/manage-synth-plugins.png");
+ icon = QIconSet(pixmap);
+ new KAction(i18n("Manage S&ynth Plugins"), icon, 0, this,
+ SLOT(slotManageSynths()),
+ actionCollection(), "manage_synths");
+
+ new KAction(i18n("Modify MIDI &Filters"), "filter", 0, this,
+ SLOT(slotModifyMIDIFilters()),
+ actionCollection(), "modify_midi_filters");
+
+ m_enableMIDIrouting = new KToggleAction(i18n("MIDI Thru Routing"), 0, this,
+ SLOT(slotEnableMIDIThruRouting()),
+ actionCollection(), "enable_midi_routing");
+
+ pixmap.load(pixmapDir + "/toolbar/time-musical.png");
+ icon = QIconSet(pixmap);
+ new KAction(i18n("Manage &Metronome"), 0, this,
+ SLOT(slotManageMetronome()),
+ actionCollection(), "manage_metronome");
+
+ new KAction(i18n("&Save Current Document as Default Studio"), 0, this,
+ SLOT(slotSaveDefaultStudio()),
+ actionCollection(), "save_default_studio");
+
+ new KAction(i18n("&Import Default Studio"), 0, this,
+ SLOT(slotImportDefaultStudio()),
+ actionCollection(), "load_default_studio");
+
+ new KAction(i18n("Im&port Studio from File..."), 0, this,
+ SLOT(slotImportStudio()),
+ actionCollection(), "load_studio");
+
+ new KAction(i18n("&Reset MIDI Network"), 0, this,
+ SLOT(slotResetMidiNetwork()),
+ actionCollection(), "reset_midi_network");
+
+ m_setQuickMarkerAction = new KAction(i18n("Set Quick Marker at Playback Position"), 0, CTRL + Key_1, this,
+ SLOT(slotSetQuickMarker()), actionCollection(),
+ "set_quick_marker");
+
+ m_jumpToQuickMarkerAction = new KAction(i18n("Jump to Quick Marker"), 0, Key_1, this,
+ SLOT(slotJumpToQuickMarker()), actionCollection(),
+ "jump_to_quick_marker");
+
+ //
+ // Marker Ruler popup menu
+ //
+// new KAction(i18n("Insert Marker"), 0, 0, this,
+// SLOT(slotInsertMarkerHere()), actionCollection(),
+// "insert_marker_here");
+//
+// new KAction(i18n("Insert Marker at Playback Position"), 0, 0, this,
+// SLOT(slotInsertMarkerAtPointer()), actionCollection(),
+// "insert_marker_at_pointer");
+//
+// new KAction(i18n("Delete Marker"), 0, 0, this,
+// SLOT(slotDeleteMarker()), actionCollection(),
+// "delete_marker");
+
+
+
+ //
+ // Transport menu
+ //
+
+ // Transport controls [rwb]
+ //
+ // We set some default key bindings - with numlock off
+ // use 1 (End) and 3 (Page Down) for Rwd and Ffwd and
+ // 0 (insert) and keypad Enter for Play and Stop
+ //
+ pixmap.load(pixmapDir + "/toolbar/transport-play.png");
+ icon = QIconSet(pixmap);
+ m_playTransport = new KAction(i18n("&Play"), icon, Key_Enter, this,
+ SLOT(slotPlay()), actionCollection(),
+ "play");
+ // Alternative shortcut for Play
+ KShortcut playShortcut = m_playTransport->shortcut();
+ playShortcut.append( KKey(Key_Return + CTRL) );
+ m_playTransport->setShortcut(playShortcut);
+ m_playTransport->setGroup(TransportDialogConfigGroup);
+
+ pixmap.load(pixmapDir + "/toolbar/transport-stop.png");
+ icon = QIconSet(pixmap);
+ m_stopTransport = new KAction(i18n("&Stop"), icon, Key_Insert, this,
+ SLOT(slotStop()), actionCollection(),
+ "stop");
+ m_stopTransport->setGroup(TransportDialogConfigGroup);
+
+ pixmap.load(pixmapDir + "/toolbar/transport-ffwd.png");
+ icon = QIconSet(pixmap);
+ m_ffwdTransport = new KAction(i18n("&Fast Forward"), icon, Key_PageDown,
+ this,
+ SLOT(slotFastforward()), actionCollection(),
+ "fast_forward");
+ m_ffwdTransport->setGroup(TransportDialogConfigGroup);
+
+ pixmap.load(pixmapDir + "/toolbar/transport-rewind.png");
+ icon = QIconSet(pixmap);
+ m_rewindTransport = new KAction(i18n("Re&wind"), icon, Key_End, this,
+ SLOT(slotRewind()), actionCollection(),
+ "rewind");
+ m_rewindTransport->setGroup(TransportDialogConfigGroup);
+
+ pixmap.load(pixmapDir + "/toolbar/transport-record.png");
+ icon = QIconSet(pixmap);
+ m_recordTransport = new KAction(i18n("P&unch in Record"), icon, Key_Space, this,
+ SLOT(slotToggleRecord()), actionCollection(),
+ "recordtoggle");
+ m_recordTransport->setGroup(TransportDialogConfigGroup);
+
+ pixmap.load(pixmapDir + "/toolbar/transport-record.png");
+ icon = QIconSet(pixmap);
+ m_recordTransport = new KAction(i18n("&Record"), icon, 0, this,
+ SLOT(slotRecord()), actionCollection(),
+ "record");
+ m_recordTransport->setGroup(TransportDialogConfigGroup);
+
+ pixmap.load(pixmapDir + "/toolbar/transport-rewind-end.png");
+ icon = QIconSet(pixmap);
+ m_rewindEndTransport = new KAction(i18n("Rewind to &Beginning"), icon, 0, this,
+ SLOT(slotRewindToBeginning()), actionCollection(),
+ "rewindtobeginning");
+ m_rewindEndTransport->setGroup(TransportDialogConfigGroup);
+
+ pixmap.load(pixmapDir + "/toolbar/transport-ffwd-end.png");
+ icon = QIconSet(pixmap);
+ m_ffwdEndTransport = new KAction(i18n("Fast Forward to &End"), icon, 0, this,
+ SLOT(slotFastForwardToEnd()), actionCollection(),
+ "fastforwardtoend");
+ m_ffwdEndTransport->setGroup(TransportDialogConfigGroup);
+
+ pixmap.load(pixmapDir + "/toolbar/transport-tracking.png");
+ icon = QIconSet(pixmap);
+ (new KToggleAction(i18n("Scro&ll to Follow Playback"), icon, Key_Pause, this,
+ SLOT(slotToggleTracking()), actionCollection(),
+ "toggle_tracking"))->setChecked(true);
+
+ pixmap.load(pixmapDir + "/toolbar/transport-panic.png");
+ icon = QIconSet(pixmap);
+ new KAction( i18n("Panic"), icon, Key_P + CTRL + ALT, this, SLOT(slotPanic()),
+ actionCollection(), "panic");
+
+ // DEBUG FACILITY
+ new KAction(i18n("Segment Debug Dump "), 0, this,
+ SLOT(slotDebugDump()), actionCollection(),
+ "debug_dump_segments");
+
+ // create main gui
+ //
+ createGUI("rosegardenui.rc", false);
+
+ createAndSetupTransport();
+
+ // transport toolbar is hidden by default - TODO : this should be in options
+ //
+ //toolBar("Transport Toolbar")->hide();
+
+ QPopupMenu* setTrackInstrumentMenu = dynamic_cast<QPopupMenu*>(factory()->container("set_track_instrument", this));
+
+ if (setTrackInstrumentMenu) {
+ connect(setTrackInstrumentMenu, SIGNAL(aboutToShow()),
+ this, SLOT(slotPopulateTrackInstrumentPopup()));
+ } else {
+ RG_DEBUG << "RosegardenGUIApp::setupActions() : couldn't find set_track_instrument menu - check rosegardenui.rcn\n";
+ }
+
+ setRewFFwdToAutoRepeat();
+}
+
+void RosegardenGUIApp::setRewFFwdToAutoRepeat()
+{
+ QWidget* transportToolbar = factory()->container("Transport Toolbar", this);
+
+ if (transportToolbar) {
+ QObjectList *l = transportToolbar->queryList();
+ QObjectListIt it(*l); // iterate over the buttons
+ QObject *obj;
+
+ while ( (obj = it.current()) != 0 ) {
+ // for each found object...
+ ++it;
+ // RG_DEBUG << "obj name : " << obj->name() << endl;
+ QString objName = obj->name();
+
+ if (objName.endsWith("rewind") || objName.endsWith("fast_forward")) {
+ QButton* btn = dynamic_cast<QButton*>(obj);
+ if (!btn) {
+ RG_DEBUG << "Very strange - found widgets in transport_toolbar which aren't buttons\n";
+
+ continue;
+ }
+ btn->setAutoRepeat(true);
+ }
+
+
+ }
+ delete l;
+
+ } else {
+ RG_DEBUG << "transportToolbar == 0\n";
+ }
+
+}
+
+void RosegardenGUIApp::initZoomToolbar()
+{
+ KToolBar *zoomToolbar = toolBar("Zoom Toolbar");
+ if (!zoomToolbar) {
+ RG_DEBUG << "RosegardenGUIApp::initZoomToolbar() : "
+ << "zoom toolbar not found" << endl;
+ return ;
+ }
+
+ new QLabel(i18n(" Zoom: "), zoomToolbar, "kde toolbar widget");
+
+ std::vector<double> zoomSizes; // in units-per-pixel
+ double defaultBarWidth44 = 100.0;
+ double duration44 = TimeSignature(4, 4).getBarDuration();
+ static double factors[] = { 0.025, 0.05, 0.1, 0.2, 0.5,
+ 1.0, 1.5, 2.5, 5.0, 10.0 , 20.0 };
+
+ for (unsigned int i = 0; i < sizeof(factors) / sizeof(factors[0]); ++i) {
+ zoomSizes.push_back(duration44 / (defaultBarWidth44 * factors[i]));
+ }
+
+ // zoom labels
+ QString minZoom = QString("%1%").arg(factors[0] * 100.0);
+ QString maxZoom = QString("%1%").arg(factors[(sizeof(factors) / sizeof(factors[0])) - 1] * 100.0);
+
+ m_zoomSlider = new ZoomSlider<double>
+ (zoomSizes, -1, QSlider::Horizontal, zoomToolbar, "kde toolbar widget");
+ m_zoomSlider->setTracking(true);
+ m_zoomSlider->setFocusPolicy(QWidget::NoFocus);
+ m_zoomLabel = new QLabel(minZoom, zoomToolbar, "kde toolbar widget");
+ m_zoomLabel->setIndent(10);
+
+ connect(m_zoomSlider, SIGNAL(valueChanged(int)),
+ this, SLOT(slotChangeZoom(int)));
+
+ // set initial zoom - we might want to make this a config option
+ // m_zoomSlider->setToDefault();
+
+}
+
+void RosegardenGUIApp::initStatusBar()
+{
+ KTmpStatusMsg::setDefaultMsg("");
+ statusBar()->insertItem(KTmpStatusMsg::getDefaultMsg(),
+ KTmpStatusMsg::getDefaultId(), 1);
+ statusBar()->setItemAlignment(KTmpStatusMsg::getDefaultId(),
+ AlignLeft | AlignVCenter);
+
+ m_progressBar = new ProgressBar(100, true, statusBar());
+ // m_progressBar->setMinimumWidth(100);
+ m_progressBar->setFixedWidth(60);
+ m_progressBar->setFixedHeight(18);
+ m_progressBar->setTextEnabled(false);
+ statusBar()->addWidget(m_progressBar);
+}
+
+void RosegardenGUIApp::initView()
+{
+ ////////////////////////////////////////////////////////////////////
+ // create the main widget here that is managed by KTMainWindow's view-region and
+ // connect the widget to your document to display document contents.
+
+ RG_DEBUG << "RosegardenGUIApp::initView()" << endl;
+
+ Composition &comp = m_doc->getComposition();
+
+ // Ensure that the start and end markers for the piece are set
+ // to something reasonable
+ //
+ if (comp.getStartMarker() == 0 &&
+ comp.getEndMarker() == 0) {
+ int endMarker = comp.getBarRange(100 + comp.getNbBars()).second;
+ comp.setEndMarker(endMarker);
+ }
+
+ m_swapView = new RosegardenGUIView(m_viewTrackLabels->isChecked(),
+ m_segmentParameterBox,
+ m_instrumentParameterBox,
+ m_trackParameterBox, this);
+
+ // Connect up this signal so that we can force tool mode
+ // changes from the view
+ connect(m_swapView, SIGNAL(activateTool(QString)),
+ this, SLOT(slotActivateTool(QString)));
+
+ connect(m_swapView,
+ SIGNAL(segmentsSelected(const SegmentSelection &)),
+ SIGNAL(segmentsSelected(const SegmentSelection &)));
+
+ connect(m_swapView,
+ SIGNAL(addAudioFile(AudioFileId)),
+ SLOT(slotAddAudioFile(AudioFileId)));
+
+ connect(m_swapView, SIGNAL(toggleSolo(bool)), SLOT(slotToggleSolo(bool)));
+
+ m_doc->attachView(m_swapView);
+
+ m_mainDockWidget->setWidget(m_swapView);
+
+ // setCentralWidget(m_swapView);
+ setCaption(m_doc->getTitle());
+
+
+ // Transport setup
+ //
+ std::string transportMode = m_doc->getConfiguration().
+ get
+ <String>
+ (DocumentConfiguration::TransportMode);
+
+
+ slotEnableTransport(true);
+
+ // and the time signature
+ //
+ getTransport()->setTimeSignature(comp.getTimeSignatureAt(comp.getPosition()));
+
+ // set the tempo in the transport
+ //
+ getTransport()->setTempo(comp.getCurrentTempo());
+
+ // bring the transport to the front
+ //
+ getTransport()->raise();
+
+ // set the play metronome button
+ getTransport()->MetronomeButton()->setOn(comp.usePlayMetronome());
+
+ // Set the solo button
+ getTransport()->SoloButton()->setOn(comp.isSolo());
+
+ // set the transport mode found in the configuration
+ getTransport()->setNewMode(transportMode);
+
+ // set the pointer position
+ //
+ slotSetPointerPosition(m_doc->getComposition().getPosition());
+
+ // make sure we show
+ //
+ RosegardenGUIView *oldView = m_view;
+ m_view = m_swapView;
+
+ connect(m_view, SIGNAL(stateChange(QString, bool)),
+ this, SLOT (slotStateChanged(QString, bool)));
+
+ connect(m_view, SIGNAL(instrumentParametersChanged(InstrumentId)),
+ this, SIGNAL(instrumentParametersChanged(InstrumentId)));
+
+ // We only check for the SequenceManager to make sure
+ // we're not on the first pass though - we don't want
+ // to send these toggles twice on initialisation.
+ //
+ // Clunky but we just about get away with it for the
+ // moment.
+ //
+ if (m_seqManager != 0) {
+ slotToggleChordNameRuler();
+ slotToggleRulers();
+ slotToggleTempoRuler();
+ slotTogglePreviews();
+ slotToggleSegmentLabels();
+
+ // Reset any loop on the sequencer
+ //
+ try {
+ if (isUsingSequencer())
+ m_seqManager->setLoop(0, 0);
+ stateChanged("have_range", KXMLGUIClient::StateReverse);
+ } catch (QString s) {
+ KStartupLogo::hideIfStillThere();
+ CurrentProgressDialog::freeze();
+ KMessageBox::error(this, s);
+ CurrentProgressDialog::thaw();
+ }
+
+ connect(m_seqManager, SIGNAL(controllerDeviceEventReceived(MappedEvent *)),
+ m_view, SLOT(slotControllerDeviceEventReceived(MappedEvent *)));
+ }
+
+ // delete m_playList;
+ // m_playList = 0;
+
+ delete m_deviceManager;
+ m_deviceManager = 0;
+
+ delete m_synthManager;
+ m_synthManager = 0;
+
+ delete m_audioMixer;
+ m_audioMixer = 0;
+
+ delete m_bankEditor;
+ m_bankEditor = 0;
+
+ delete m_markerEditor;
+ m_markerEditor = 0;
+
+ delete m_tempoView;
+ m_tempoView = 0;
+
+ delete m_triggerSegmentManager;
+ m_triggerSegmentManager = 0;
+
+ delete oldView;
+
+ // set the highlighted track
+ m_view->slotSelectTrackSegments(comp.getSelectedTrack());
+
+ // play tracking on in the editor by default: turn off if need be
+ KToggleAction *trackingAction = dynamic_cast<KToggleAction *>
+ (actionCollection()->action("toggle_tracking"));
+ if (trackingAction && !trackingAction->isChecked()) {
+ m_view->getTrackEditor()->slotToggleTracking();
+ }
+
+ m_view->show();
+
+ connect(m_view->getTrackEditor()->getSegmentCanvas(),
+ SIGNAL(showContextHelp(const QString &)),
+ this,
+ SLOT(slotShowToolHelp(const QString &)));
+
+ // We have to do this to make sure that the 2nd call ("select")
+ // actually has any effect. Activating the same radio action
+ // doesn't work the 2nd time (like pressing down the same radio
+ // button twice - it doesn't have any effect), so if you load two
+ // files in a row, on the 2nd file a new SegmentCanvas will be
+ // created but its tool won't be set, even though it will appear
+ // to be selected.
+ //
+ actionCollection()->action("move")->activate();
+ if (m_doc->getComposition().getNbSegments() > 0)
+ actionCollection()->action("select")->activate();
+ else
+ actionCollection()->action("draw")->activate();
+
+ int zoomLevel = m_doc->getConfiguration().
+ get
+ <Int>
+ (DocumentConfiguration::ZoomLevel);
+
+ m_zoomSlider->setSize(double(zoomLevel) / 1000.0);
+ slotChangeZoom(zoomLevel);
+
+ //slotChangeZoom(int(m_zoomSlider->getCurrentSize()));
+
+ stateChanged("new_file");
+
+ ProgressDialog::processEvents();
+
+ if (m_viewChordNameRuler->isChecked()) {
+ SetWaitCursor swc;
+ m_view->initChordNameRuler();
+ } else {
+ m_view->initChordNameRuler();
+ }
+}
+
+void RosegardenGUIApp::setDocument(RosegardenGUIDoc* newDocument)
+{
+ if (m_doc == newDocument)
+ return ;
+
+ emit documentAboutToChange();
+ kapp->processEvents(); // to make sure all opened dialogs (mixer, midi devices...) are closed
+
+ // Take care of all subparts which depend on the document
+
+ // Caption
+ //
+ QString caption = kapp->caption();
+ setCaption(caption + ": " + newDocument->getTitle());
+
+ // // reset AudioManagerDialog
+ // //
+ // delete m_audioManagerDialog; // TODO : replace this with a connection to documentAboutToChange() sig.
+ // m_audioManagerDialog = 0;
+
+ RosegardenGUIDoc* oldDoc = m_doc;
+
+ m_doc = newDocument;
+
+ if (m_seqManager) // when we're called at startup, the seq. man. isn't created yet
+ m_seqManager->setDocument(m_doc);
+
+ if (m_markerEditor)
+ m_markerEditor->setDocument(m_doc);
+ if (m_tempoView) {
+ delete m_tempoView;
+ m_tempoView = 0;
+ }
+ if (m_triggerSegmentManager)
+ m_triggerSegmentManager->setDocument(m_doc);
+
+ m_trackParameterBox->setDocument(m_doc);
+ m_segmentParameterBox->setDocument(m_doc);
+ m_instrumentParameterBox->setDocument(m_doc);
+
+#ifdef HAVE_LIBLO
+
+ if (m_pluginGUIManager) {
+ m_pluginGUIManager->stopAllGUIs();
+ m_pluginGUIManager->setStudio(&m_doc->getStudio());
+ }
+#endif
+
+ if (getView() &&
+ getView()->getTrackEditor() &&
+ getView()->getTrackEditor()->getSegmentCanvas()) {
+ getView()->getTrackEditor()->getSegmentCanvas()->endAudioPreviewGeneration();
+ }
+
+ // this will delete all edit views
+ //
+ delete oldDoc;
+
+ // connect needed signals
+ //
+ connect(m_segmentParameterBox, SIGNAL(documentModified()),
+ m_doc, SLOT(slotDocumentModified()));
+
+ connect(m_doc, SIGNAL(pointerPositionChanged(timeT)),
+ this, SLOT(slotSetPointerPosition(timeT)));
+
+ connect(m_doc, SIGNAL(documentModified(bool)),
+ this, SLOT(slotDocumentModified(bool)));
+
+ connect(m_doc, SIGNAL(loopChanged(timeT, timeT)),
+ this, SLOT(slotSetLoop(timeT, timeT)));
+
+ m_doc->getCommandHistory()->attachView(actionCollection());
+
+ connect(m_doc->getCommandHistory(), SIGNAL(commandExecuted()),
+ SLOT(update()));
+ connect(m_doc->getCommandHistory(), SIGNAL(commandExecuted()),
+ SLOT(slotTestClipboard()));
+
+ // connect and start the autosave timer
+ connect(m_autoSaveTimer, SIGNAL(timeout()), this, SLOT(slotAutoSave()));
+ m_autoSaveTimer->start(m_doc->getAutoSavePeriod() * 1000);
+
+ // Connect the playback timer
+ //
+ connect(m_playTimer, SIGNAL(timeout()), this, SLOT(slotUpdatePlaybackPosition()));
+ connect(m_stopTimer, SIGNAL(timeout()), this, SLOT(slotUpdateMonitoring()));
+
+ // finally recreate the main view
+ //
+ initView();
+
+ if (getView() && getView()->getTrackEditor()) {
+ connect(m_doc, SIGNAL(makeTrackVisible(int)),
+ getView()->getTrackEditor(), SLOT(slotScrollToTrack(int)));
+ }
+
+ connect(m_doc, SIGNAL(devicesResyncd()),
+ this, SLOT(slotDocumentDevicesResyncd()));
+
+ m_doc->syncDevices();
+ m_doc->clearModifiedStatus();
+
+ if (newDocument->getStudio().haveMidiDevices()) {
+ stateChanged("got_midi_devices");
+ } else {
+ stateChanged("got_midi_devices", KXMLGUIClient::StateReverse);
+ }
+
+ // Ensure the sequencer knows about any audio files
+ // we've loaded as part of the new Composition
+ //
+ m_doc->prepareAudio();
+
+ // Do not reset instrument prog. changes after all.
+ // if (m_seqManager)
+ // m_seqManager->preparePlayback(true);
+
+ Composition &comp = m_doc->getComposition();
+
+ // Set any loaded loop at the Composition and
+ // on the marker on SegmentCanvas and clients
+ //
+ if (m_seqManager)
+ m_doc->setLoop(comp.getLoopStart(), comp.getLoopEnd());
+
+ emit documentChanged(m_doc);
+
+ m_doc->clearModifiedStatus(); // because it's set as modified by the various
+ // init operations
+ // TODO: this sucks, have to sort it out somehow.
+
+ // Readjust canvas size
+ //
+ m_view->getTrackEditor()->slotReadjustCanvasSize();
+
+ m_stopTimer->start(100);
+}
+
+void
+RosegardenGUIApp::openFile(QString filePath, ImportType type)
+{
+ RG_DEBUG << "RosegardenGUIApp::openFile " << filePath << endl;
+
+ if (type == ImportCheckType && filePath.endsWith(".rgp")) {
+ importProject(filePath);
+ return ;
+ }
+
+ RosegardenGUIDoc *doc = createDocument(filePath, type);
+ if (doc) {
+ setDocument(doc);
+
+ // fix # 1235755, "SPB combo not updating after document swap"
+ RG_DEBUG << "RosegardenGUIApp::openFile(): calling slotDocColoursChanged() in doc" << endl;
+ doc->slotDocColoursChanged();
+
+ kapp->config()->setGroup(GeneralOptionsConfigGroup);
+ if (kapp->config()->readBoolEntry("alwaysusedefaultstudio", false)) {
+
+ QString autoloadFile =
+ KGlobal::dirs()->findResource("appdata", "autoload.rg");
+
+ QFileInfo autoloadFileInfo(autoloadFile);
+ if (autoloadFileInfo.isReadable()) {
+
+ RG_DEBUG << "Importing default studio from " << autoloadFile << endl;
+
+ slotImportStudioFromFile(autoloadFile);
+ }
+ }
+
+ QFileInfo fInfo(filePath);
+ m_fileRecent->addURL(fInfo.absFilePath());
+ }
+}
+
+RosegardenGUIDoc*
+RosegardenGUIApp::createDocument(QString filePath, ImportType importType)
+{
+ QFileInfo info(filePath);
+ RosegardenGUIDoc *doc = 0;
+
+ if (!info.exists()) {
+ // can happen with command-line arg, so...
+ KStartupLogo::hideIfStillThere();
+ KMessageBox::sorry(this, i18n("File \"%1\" does not exist").arg(filePath));
+ return 0;
+ }
+
+ if (info.isDir()) {
+ KStartupLogo::hideIfStillThere();
+ KMessageBox::sorry(this, i18n("File \"%1\" is actually a directory"));
+ return 0;
+ }
+
+ QFile file(filePath);
+
+ if (!file.open(IO_ReadOnly)) {
+ KStartupLogo::hideIfStillThere();
+ QString errStr =
+ i18n("You do not have read permission for \"%1\"").arg(filePath);
+
+ KMessageBox::sorry(this, errStr);
+ return 0;
+ }
+
+ // Stop if playing
+ //
+ if (m_seqManager && m_seqManager->getTransportStatus() == PLAYING)
+ slotStop();
+
+ slotEnableTransport(false);
+
+ if (importType == ImportCheckType) {
+ KMimeType::Ptr fileMimeType = KMimeType::findByPath(filePath);
+ if (fileMimeType->name() == "audio/x-midi")
+ importType = ImportMIDI;
+ else if (fileMimeType->name() == "audio/x-rosegarden")
+ importType = ImportRG4;
+ else if (filePath.endsWith(".rose"))
+ importType = ImportRG21;
+ else if (filePath.endsWith(".h2song"))
+ importType = ImportHydrogen;
+ }
+
+
+ switch (importType) {
+ case ImportMIDI:
+ doc = createDocumentFromMIDIFile(filePath);
+ break;
+ case ImportRG21:
+ doc = createDocumentFromRG21File(filePath);
+ break;
+ case ImportHydrogen:
+ doc = createDocumentFromHydrogenFile(filePath);
+ break;
+ default:
+ doc = createDocumentFromRGFile(filePath);
+ }
+
+ slotEnableTransport(true);
+
+ return doc;
+}
+
+RosegardenGUIDoc*
+RosegardenGUIApp::createDocumentFromRGFile(QString filePath)
+{
+ // Check for an autosaved file to recover
+ QString effectiveFilePath = filePath;
+ bool canRecover = false;
+ QString autoSaveFileName = kapp->checkRecoverFile(filePath, canRecover);
+
+ if (canRecover) {
+ // First check if the auto-save file is more recent than the doc
+ QFileInfo docFileInfo(filePath), autoSaveFileInfo(autoSaveFileName);
+
+ if (docFileInfo.lastModified() < autoSaveFileInfo.lastModified()) {
+
+ RG_DEBUG << "RosegardenGUIApp::openFile : "
+ << "found a more recent autosave file\n";
+
+ // At this point the splash screen may still be there, hide it if
+ // it's the case
+ KStartupLogo::hideIfStillThere();
+
+ // It is, so ask the user if he wants to use the autosave file
+ int reply = KMessageBox::questionYesNo(this,
+ i18n("An auto-save file for this document has been found\nDo you want to open it instead ?"));
+
+ if (reply == KMessageBox::Yes)
+ // open the autosave file instead
+ effectiveFilePath = autoSaveFileName;
+ else {
+ // user doesn't want the autosave, so delete it
+ // so it won't bother us again if we reload
+ canRecover = false;
+ QFile::remove
+ (autoSaveFileName);
+ }
+
+ } else
+ canRecover = false;
+ }
+
+ // Create a new blank document
+ //
+ RosegardenGUIDoc *newDoc = new RosegardenGUIDoc(this, m_pluginManager,
+ true); // skipAutoload
+
+ // ignore return thingy
+ //
+ if (newDoc->openDocument(effectiveFilePath)) {
+ if (canRecover) {
+ // Mark the document as modified,
+ // set the "regular" filepath and name (not those of
+ // the autosaved doc)
+ //
+ newDoc->slotDocumentModified();
+ QFileInfo info(filePath);
+ newDoc->setAbsFilePath(info.absFilePath());
+ newDoc->setTitle(info.fileName());
+ } else {
+ newDoc->clearModifiedStatus();
+ }
+ } else {
+ delete newDoc;
+ return 0;
+ }
+
+ return newDoc;
+}
+
+void RosegardenGUIApp::slotSaveOptions()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotSaveOptions()\n";
+
+#ifdef SETTING_LOG_DEBUG
+
+ _settingLog(QString("SETTING 2 : transport flap extended = %1").arg(getTransport()->isExpanded()));
+ _settingLog(QString("SETTING 2 : show track labels = %1").arg(m_viewTrackLabels->isChecked()));
+#endif
+
+ kapp->config()->setGroup(GeneralOptionsConfigGroup);
+ kapp->config()->writeEntry("Show Transport", m_viewTransport->isChecked());
+ kapp->config()->writeEntry("Expanded Transport", m_transport ? getTransport()->isExpanded() : true);
+ kapp->config()->writeEntry("Show Track labels", m_viewTrackLabels->isChecked());
+ kapp->config()->writeEntry("Show Rulers", m_viewRulers->isChecked());
+ kapp->config()->writeEntry("Show Tempo Ruler", m_viewTempoRuler->isChecked());
+ kapp->config()->writeEntry("Show Chord Name Ruler", m_viewChordNameRuler->isChecked());
+ kapp->config()->writeEntry("Show Previews", m_viewPreviews->isChecked());
+ kapp->config()->writeEntry("Show Segment Labels", m_viewSegmentLabels->isChecked());
+ kapp->config()->writeEntry("Show Parameters", m_dockVisible);
+ kapp->config()->writeEntry("MIDI Thru Routing", m_enableMIDIrouting->isChecked());
+
+#ifdef SETTING_LOG_DEBUG
+
+ RG_DEBUG << "SHOW PARAMETERS = " << m_dockVisible << endl;
+#endif
+
+ m_fileRecent->saveEntries(kapp->config());
+
+ // saveMainWindowSettings(kapp->config(), RosegardenGUIApp::MainWindowConfigGroup); - no need to, done by KMainWindow
+ kapp->config()->sync();
+}
+
+void RosegardenGUIApp::setupFileDialogSpeedbar()
+{
+ KConfig *config = kapp->config();
+
+ config->setGroup("KFileDialog Speedbar");
+
+ RG_DEBUG << "RosegardenGUIApp::setupFileDialogSpeedbar" << endl;
+
+ bool hasSetExamplesItem = config->readBoolEntry("Examples Set", false);
+
+ RG_DEBUG << "RosegardenGUIApp::setupFileDialogSpeedbar: examples set " << hasSetExamplesItem << endl;
+
+ if (!hasSetExamplesItem) {
+
+ unsigned int n = config->readUnsignedNumEntry("Number of Entries", 0);
+
+ config->writeEntry(QString("Description_%1").arg(n), i18n("Example Files"));
+ config->writeEntry(QString("IconGroup_%1").arg(n), 4);
+ config->writeEntry(QString("Icon_%1").arg(n), "folder");
+ config->writeEntry(QString("URL_%1").arg(n),
+ KGlobal::dirs()->findResource("appdata", "examples/"));
+
+ RG_DEBUG << "wrote url " << config->readEntry(QString("URL_%1").arg(n)) << endl;
+
+ config->writeEntry("Examples Set", true);
+ config->writeEntry("Number of Entries", n + 1);
+ config->sync();
+ }
+
+}
+
+void RosegardenGUIApp::readOptions()
+{
+ applyMainWindowSettings(kapp->config(), MainWindowConfigGroup);
+
+ kapp->config()->reparseConfiguration();
+
+ // Statusbar and toolbars toggling action status
+ //
+ m_viewStatusBar ->setChecked(!statusBar() ->isHidden());
+ m_viewToolBar ->setChecked(!toolBar() ->isHidden());
+ m_viewToolsToolBar ->setChecked(!toolBar("Tools Toolbar") ->isHidden());
+ m_viewTracksToolBar ->setChecked(!toolBar("Tracks Toolbar") ->isHidden());
+ m_viewEditorsToolBar ->setChecked(!toolBar("Editors Toolbar") ->isHidden());
+ m_viewTransportToolBar->setChecked(!toolBar("Transport Toolbar")->isHidden());
+ m_viewZoomToolBar ->setChecked(!toolBar("Zoom Toolbar") ->isHidden());
+
+ bool opt;
+
+ kapp->config()->setGroup(GeneralOptionsConfigGroup);
+
+ opt = kapp->config()->readBoolEntry("Show Transport", true);
+ m_viewTransport->setChecked(opt);
+ slotToggleTransport();
+
+ opt = kapp->config()->readBoolEntry("Expanded Transport", true);
+
+#ifdef SETTING_LOG_DEBUG
+
+ _settingLog(QString("SETTING 3 : transport flap extended = %1").arg(opt));
+#endif
+
+ if (opt)
+ getTransport()->slotPanelOpenButtonClicked();
+ else
+ getTransport()->slotPanelCloseButtonClicked();
+
+ opt = kapp->config()->readBoolEntry("Show Track labels", true);
+
+#ifdef SETTING_LOG_DEBUG
+
+ _settingLog(QString("SETTING 3 : show track labels = %1").arg(opt));
+#endif
+
+ m_viewTrackLabels->setChecked(opt);
+ slotToggleTrackLabels();
+
+ opt = kapp->config()->readBoolEntry("Show Rulers", true);
+ m_viewRulers->setChecked(opt);
+ slotToggleRulers();
+
+ opt = kapp->config()->readBoolEntry("Show Tempo Ruler", true);
+ m_viewTempoRuler->setChecked(opt);
+ slotToggleTempoRuler();
+
+ opt = kapp->config()->readBoolEntry("Show Chord Name Ruler", false);
+ m_viewChordNameRuler->setChecked(opt);
+ slotToggleChordNameRuler();
+
+ opt = kapp->config()->readBoolEntry("Show Previews", true);
+ m_viewPreviews->setChecked(opt);
+ slotTogglePreviews();
+
+ opt = kapp->config()->readBoolEntry("Show Segment Labels", true);
+ m_viewSegmentLabels->setChecked(opt);
+ slotToggleSegmentLabels();
+
+ opt = kapp->config()->readBoolEntry("Show Parameters", true);
+ if (!opt) {
+ m_dockLeft->undock();
+ m_dockLeft->hide();
+ stateChanged("parametersbox_closed", KXMLGUIClient::StateNoReverse);
+ m_dockVisible = false;
+ }
+
+ // MIDI Thru routing
+ opt = kapp->config()->readBoolEntry("MIDI Thru Routing", true);
+ m_enableMIDIrouting->setChecked(opt);
+ slotEnableMIDIThruRouting();
+
+ // initialise the recent file list
+ //
+ m_fileRecent->loadEntries(kapp->config());
+
+ m_actionsSetup = true;
+
+}
+
+void RosegardenGUIApp::saveGlobalProperties(KConfig *cfg)
+{
+ if (m_doc->getTitle() != i18n("Untitled") && !m_doc->isModified()) {
+ // saving to tempfile not necessary
+ } else {
+ QString filename = m_doc->getAbsFilePath();
+ cfg->writeEntry("filename", filename);
+ cfg->writeEntry("modified", m_doc->isModified());
+
+ QString tempname = kapp->tempSaveName(filename);
+ QString errMsg;
+ bool res = m_doc->saveDocument(tempname, errMsg);
+ if (!res) {
+ if (errMsg)
+ KMessageBox::error(this, i18n(QString("Could not save document at %1\nError was : %2")
+ .arg(tempname).arg(errMsg)));
+ else
+ KMessageBox::error(this, i18n(QString("Could not save document at %1")
+ .arg(tempname)));
+ }
+ }
+}
+
+void RosegardenGUIApp::readGlobalProperties(KConfig* _cfg)
+{
+ QString filename = _cfg->readEntry("filename", "");
+ bool modified = _cfg->readBoolEntry("modified", false);
+
+ if (modified) {
+ bool canRecover;
+ QString tempname = kapp->checkRecoverFile(filename, canRecover);
+
+ if (canRecover) {
+ slotEnableTransport(false);
+ m_doc->openDocument(tempname);
+ slotEnableTransport(true);
+ m_doc->slotDocumentModified();
+ QFileInfo info(filename);
+ m_doc->setAbsFilePath(info.absFilePath());
+ m_doc->setTitle(info.fileName());
+ }
+ } else {
+ if (!filename.isEmpty()) {
+ slotEnableTransport(false);
+ m_doc->openDocument(filename);
+ slotEnableTransport(true);
+ }
+ }
+
+ QString caption = kapp->caption();
+ setCaption(caption + ": " + m_doc->getTitle());
+}
+
+void RosegardenGUIApp::showEvent(QShowEvent* e)
+{
+ RG_DEBUG << "RosegardenGUIApp::showEvent()\n";
+
+ getTransport()->raise();
+ KMainWindow::showEvent(e);
+}
+
+bool RosegardenGUIApp::queryClose()
+{
+ RG_DEBUG << "RosegardenGUIApp::queryClose" << endl;
+#ifdef SETTING_LOG_DEBUG
+
+ _settingLog(QString("SETTING 1 : transport flap extended = %1").arg(getTransport()->isExpanded()));
+ _settingLog(QString("SETTING 1 : show track labels = %1").arg(m_viewTrackLabels->isChecked()));
+#endif
+
+ QString errMsg;
+
+ bool canClose = m_doc->saveIfModified();
+
+ /*
+ if (canClose && m_transport) {
+
+ // or else the closing of the transport will toggle off the
+ // 'view transport' action, and its state will be saved as
+ // 'off'
+ //
+
+ disconnect(m_transport, SIGNAL(closed()),
+ this, SLOT(slotCloseTransport()));
+ }
+ */
+
+ return canClose;
+
+}
+
+bool RosegardenGUIApp::queryExit()
+{
+ RG_DEBUG << "RosegardenGUIApp::queryExit" << endl;
+ if (m_actionsSetup)
+ slotSaveOptions();
+
+ return true;
+}
+
+void RosegardenGUIApp::slotFileNewWindow()
+{
+ KTmpStatusMsg msg(i18n("Opening a new application window..."), this);
+
+ RosegardenGUIApp *new_window = new RosegardenGUIApp();
+ new_window->show();
+}
+
+void RosegardenGUIApp::slotFileNew()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotFileNew()\n";
+
+ KTmpStatusMsg msg(i18n("Creating new document..."), this);
+
+ bool makeNew = false;
+
+ if (!m_doc->isModified()) {
+ makeNew = true;
+ // m_doc->closeDocument();
+ } else if (m_doc->saveIfModified()) {
+ makeNew = true;
+ }
+
+ if (makeNew) {
+
+ setDocument(new RosegardenGUIDoc(this, m_pluginManager));
+ }
+}
+
+void RosegardenGUIApp::slotOpenDroppedURL(QString url)
+{
+ ProgressDialog::processEvents(); // or else we get a crash because the
+ // track editor is erased too soon - it is the originator of the signal
+ // this slot is connected to.
+
+ if (!m_doc->saveIfModified())
+ return ;
+
+ openURL(KURL(url));
+}
+
+void RosegardenGUIApp::openURL(QString url)
+{
+ RG_DEBUG << "RosegardenGUIApp::openURL: QString " << url << endl;
+ openURL(KURL(url));
+}
+
+void RosegardenGUIApp::openURL(const KURL& url)
+{
+ SetWaitCursor waitCursor;
+
+ QString netFile = url.prettyURL();
+ RG_DEBUG << "RosegardenGUIApp::openURL: KURL " << netFile << endl;
+
+ if (!url.isValid()) {
+ QString string;
+ string = i18n( "Malformed URL\n%1").arg(netFile);
+
+ KMessageBox::sorry(this, string);
+ return ;
+ }
+
+ QString target, caption(url.path());
+
+ if (KIO::NetAccess::download(url, target, this) == false) {
+ KMessageBox::error(this, i18n("Cannot download file %1").arg(url.prettyURL()));
+ return ;
+ }
+
+ RG_DEBUG << "RosegardenGUIApp::openURL: target : " << target << endl;
+
+ if (!m_doc->saveIfModified())
+ return ;
+
+ openFile(target);
+
+ setCaption(caption);
+}
+
+void RosegardenGUIApp::slotFileOpen()
+{
+ slotStatusHelpMsg(i18n("Opening file..."));
+
+ kapp->config()->setGroup(GeneralOptionsConfigGroup);
+
+ QString lastOpenedVersion =
+ kapp->config()->readEntry("Last File Opened Version", "none");
+
+ if (lastOpenedVersion != VERSION) {
+
+ // We haven't opened any files with this version of the
+ // program before. Default to the examples directory.
+
+ QString examplesDir = KGlobal::dirs()->findResource("appdata", "examples/");
+ kapp->config()->setGroup("Recent Dirs");
+ QString recentString = kapp->config()->readEntry("ROSEGARDEN", "");
+ kapp->config()->writeEntry
+ ("ROSEGARDEN", QString("file:%1,%2").arg(examplesDir).arg(recentString));
+ }
+
+ KURL url = KFileDialog::getOpenURL
+ (":ROSEGARDEN",
+ "audio/x-rosegarden audio/x-midi audio/x-rosegarden21", this,
+ i18n("Open File"));
+ if ( url.isEmpty() ) {
+ return ;
+ }
+
+ if (m_doc && !m_doc->saveIfModified())
+ return ;
+
+ kapp->config()->setGroup(GeneralOptionsConfigGroup);
+ kapp->config()->writeEntry("Last File Opened Version", VERSION);
+
+ openURL(url);
+}
+
+void RosegardenGUIApp::slotMerge()
+{
+ KURL url = KFileDialog::getOpenURL
+ (":ROSEGARDEN",
+ "audio/x-rosegarden audio/x-midi audio/x-rosegarden21", this,
+ i18n("Open File"));
+ if ( url.isEmpty() ) {
+ return ;
+ }
+
+
+ QString target;
+
+ if (KIO::NetAccess::download(url, target, this) == false) {
+ KMessageBox::error(this, i18n("Cannot download file %1").arg(url.prettyURL()));
+ return ;
+ }
+
+ mergeFile(target);
+
+ KIO::NetAccess::removeTempFile( target );
+}
+
+void RosegardenGUIApp::slotFileOpenRecent(const KURL &url)
+{
+ KTmpStatusMsg msg(i18n("Opening file..."), this);
+
+ if (m_doc) {
+
+ if (!m_doc->saveIfModified()) {
+ return ;
+
+ }
+ }
+
+ openURL(url);
+}
+
+void RosegardenGUIApp::slotFileSave()
+{
+ if (!m_doc /*|| !m_doc->isModified()*/)
+ return ; // ALWAYS save, even if doc is not modified.
+
+ KTmpStatusMsg msg(i18n("Saving file..."), this);
+
+ // if it's a new file (no file path), or an imported file
+ // (file path doesn't end with .rg), call saveAs
+ //
+ if (!m_doc->isRegularDotRGFile()) {
+
+ slotFileSaveAs();
+
+ } else {
+
+ SetWaitCursor waitCursor;
+ QString errMsg, docFilePath = m_doc->getAbsFilePath();
+
+ bool res = m_doc->saveDocument(docFilePath, errMsg);
+ if (!res) {
+ if (errMsg)
+ KMessageBox::error(this, i18n(QString("Could not save document at %1\nError was : %2")
+ .arg(docFilePath).arg(errMsg)));
+ else
+ KMessageBox::error(this, i18n(QString("Could not save document at %1")
+ .arg(docFilePath)));
+ }
+ }
+}
+
+QString
+RosegardenGUIApp::getValidWriteFile(QString descriptiveExtension,
+ QString label)
+{
+ // extract first extension listed in descriptiveExtension, for instance,
+ // ".rg" from "*.rg|Rosegarden files", or ".mid" from "*.mid *.midi|MIDI Files"
+ //
+ QString extension = descriptiveExtension.left(descriptiveExtension.find('|')).mid(1).section(' ', 0, 0);
+
+ RG_DEBUG << "RosegardenGUIApp::getValidWriteFile() : extension = " << extension << endl;
+
+ // It's too bad there isn't this functionality within
+ // KFileDialog::getSaveFileName
+ KFileDialog saveFileDialog(":ROSEGARDEN", descriptiveExtension, this, label, true);
+ saveFileDialog.setOperationMode(KFileDialog::Saving);
+ if (m_doc) {
+ QString saveFileName = m_doc->getAbsFilePath();
+ // Show filename without the old extension
+ int dotLoc = saveFileName.findRev('.');
+ if (dotLoc >= int(saveFileName.length() - 4)) {
+ saveFileName = saveFileName.left(dotLoc);
+ }
+ saveFileDialog.setSelection(saveFileName);
+ }
+ saveFileDialog.exec();
+ QString name = saveFileDialog.selectedFile();
+
+ // RG_DEBUG << "RosegardenGUIApp::getValidWriteFile() : KFileDialog::getSaveFileName returned "
+ // << name << endl;
+
+
+ if (name.isEmpty())
+ return name;
+
+ // Append extension if we don't have one
+ //
+ if (!extension.isEmpty()) {
+ static QRegExp rgFile("\\..{1,4}$");
+ if (rgFile.match(name) == -1) {
+ name += extension;
+ }
+ }
+
+ KURL *u = new KURL(name);
+
+ if (!u->isValid()) {
+ KMessageBox::sorry(this, i18n("This is not a valid filename.\n"));
+ return "";
+ }
+
+ if (!u->isLocalFile()) {
+ KMessageBox::sorry(this, i18n("This is not a local file.\n"));
+ return "";
+ }
+
+ QFileInfo info(name);
+
+ if (info.isDir()) {
+ KMessageBox::sorry(this, i18n("You have specified a directory"));
+ return "";
+ }
+
+ if (info.exists()) {
+ int overwrite = KMessageBox::questionYesNo
+ (this, i18n("The specified file exists. Overwrite?"));
+
+ if (overwrite != KMessageBox::Yes)
+ return "";
+ }
+
+ return name;
+}
+
+bool RosegardenGUIApp::slotFileSaveAs()
+{
+ if (!m_doc)
+ return false;
+
+ KTmpStatusMsg msg(i18n("Saving file with a new filename..."), this);
+
+ QString newName = getValidWriteFile("*.rg|" + i18n("Rosegarden files") +
+ "\n*|" + i18n("All files"),
+ i18n("Save as..."));
+ if (newName.isEmpty())
+ return false;
+
+ SetWaitCursor waitCursor;
+ QFileInfo saveAsInfo(newName);
+ m_doc->setTitle(saveAsInfo.fileName());
+ m_doc->setAbsFilePath(saveAsInfo.absFilePath());
+ QString errMsg;
+ bool res = m_doc->saveDocument(newName, errMsg);
+ if (!res) {
+ if (errMsg)
+ KMessageBox::error(this, i18n(QString("Could not save document at %1\nError was : %2")
+ .arg(newName).arg(errMsg)));
+ else
+ KMessageBox::error(this, i18n(QString("Could not save document at %1")
+ .arg(newName)));
+
+ } else {
+
+ m_fileRecent->addURL(newName);
+
+ QString caption = kapp->caption();
+ setCaption(caption + ": " + m_doc->getTitle());
+ // update the edit view's captions too
+ emit compositionStateUpdate();
+ }
+
+ return res;
+}
+
+void RosegardenGUIApp::slotFileClose()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotFileClose()" << endl;
+
+ if (!m_doc)
+ return ;
+
+ KTmpStatusMsg msg(i18n("Closing file..."), this);
+
+ if (m_doc->saveIfModified()) {
+ setDocument(new RosegardenGUIDoc(this, m_pluginManager));
+ }
+
+ // Don't close the whole view (i.e. Quit), just close the doc.
+ // close();
+}
+
+void RosegardenGUIApp::slotFilePrint()
+{
+ if (m_doc->getComposition().getNbSegments() == 0) {
+ KMessageBox::sorry(0, "Please create some tracks first (until we implement menu state management)");
+ return ;
+ }
+
+ KTmpStatusMsg msg(i18n("Printing..."), this);
+
+ m_view->print(&m_doc->getComposition());
+}
+
+void RosegardenGUIApp::slotFilePrintPreview()
+{
+ if (m_doc->getComposition().getNbSegments() == 0) {
+ KMessageBox::sorry(0, "Please create some tracks first (until we implement menu state management)");
+ return ;
+ }
+
+ KTmpStatusMsg msg(i18n("Previewing..."), this);
+
+ m_view->print(&m_doc->getComposition(), true);
+}
+
+void RosegardenGUIApp::slotQuit()
+{
+ slotStatusMsg(i18n("Exiting..."));
+
+ Profiles::getInstance()->dump();
+
+ // close the first window, the list makes the next one the first again.
+ // This ensures that queryClose() is called on each window to ask for closing
+ KMainWindow* w;
+ if (memberList) {
+
+ for (w = memberList->first(); w != 0; w = memberList->next()) {
+ // only close the window if the closeEvent is accepted. If
+ // the user presses Cancel on the saveIfModified() dialog,
+ // the window and the application stay open.
+ if (!w->close())
+ break;
+ }
+ }
+}
+
+void RosegardenGUIApp::slotEditCut()
+{
+ if (!m_view->haveSelection())
+ return ;
+ KTmpStatusMsg msg(i18n("Cutting selection..."), this);
+
+ SegmentSelection selection(m_view->getSelection());
+ m_doc->getCommandHistory()->addCommand
+ (new CutCommand(selection, m_clipboard));
+}
+
+void RosegardenGUIApp::slotEditCopy()
+{
+ if (!m_view->haveSelection())
+ return ;
+ KTmpStatusMsg msg(i18n("Copying selection to clipboard..."), this);
+
+ SegmentSelection selection(m_view->getSelection());
+ m_doc->getCommandHistory()->addCommand
+ (new CopyCommand(selection, m_clipboard));
+}
+
+void RosegardenGUIApp::slotEditPaste()
+{
+ if (m_clipboard->isEmpty()) {
+ KTmpStatusMsg msg(i18n("Clipboard is empty"), this);
+ return ;
+ }
+ KTmpStatusMsg msg(i18n("Inserting clipboard contents..."), this);
+
+ // for now, but we could paste at the time of the first copied
+ // segment and then do ghosting drag or something
+ timeT insertionTime = m_doc->getComposition().getPosition();
+ m_doc->getCommandHistory()->addCommand
+ (new PasteSegmentsCommand(&m_doc->getComposition(),
+ m_clipboard, insertionTime,
+ m_doc->getComposition().getSelectedTrack(),
+ false));
+
+ // User preference? Update song pointer position on paste
+ m_doc->slotSetPointerPosition(m_doc->getComposition().getPosition());
+}
+
+void RosegardenGUIApp::slotCutRange()
+{
+ timeT t0 = m_doc->getComposition().getLoopStart();
+ timeT t1 = m_doc->getComposition().getLoopEnd();
+
+ if (t0 == t1)
+ return ;
+
+ m_doc->getCommandHistory()->addCommand
+ (new CutRangeCommand(&m_doc->getComposition(), t0, t1, m_clipboard));
+}
+
+void RosegardenGUIApp::slotCopyRange()
+{
+ timeT t0 = m_doc->getComposition().getLoopStart();
+ timeT t1 = m_doc->getComposition().getLoopEnd();
+
+ if (t0 == t1)
+ return ;
+
+ m_doc->getCommandHistory()->addCommand
+ (new CopyCommand(&m_doc->getComposition(), t0, t1, m_clipboard));
+}
+
+void RosegardenGUIApp::slotPasteRange()
+{
+ if (m_clipboard->isEmpty())
+ return ;
+
+ m_doc->getCommandHistory()->addCommand
+ (new PasteRangeCommand(&m_doc->getComposition(), m_clipboard,
+ m_doc->getComposition().getPosition()));
+
+ m_doc->setLoop(0, 0);
+}
+
+void RosegardenGUIApp::slotDeleteRange()
+{
+ timeT t0 = m_doc->getComposition().getLoopStart();
+ timeT t1 = m_doc->getComposition().getLoopEnd();
+
+ if (t0 == t1)
+ return ;
+
+ m_doc->getCommandHistory()->addCommand
+ (new DeleteRangeCommand(&m_doc->getComposition(), t0, t1));
+
+ m_doc->setLoop(0, 0);
+}
+
+void RosegardenGUIApp::slotInsertRange()
+{
+ timeT t0 = m_doc->getComposition().getPosition();
+ std::pair<timeT, timeT> r = m_doc->getComposition().getBarRangeForTime(t0);
+ TimeDialog dialog(m_view, i18n("Duration of empty range to insert"),
+ &m_doc->getComposition(), t0, r.second - r.first, false);
+ if (dialog.exec() == QDialog::Accepted) {
+ m_doc->getCommandHistory()->addCommand
+ (new InsertRangeCommand(&m_doc->getComposition(), t0, dialog.getTime()));
+ m_doc->setLoop(0, 0);
+ }
+}
+
+void RosegardenGUIApp::slotSelectAll()
+{
+ m_view->slotSelectAllSegments();
+}
+
+void RosegardenGUIApp::slotDeleteSelectedSegments()
+{
+ m_view->getTrackEditor()->slotDeleteSelectedSegments();
+}
+
+void RosegardenGUIApp::slotQuantizeSelection()
+{
+ if (!m_view->haveSelection())
+ return ;
+
+ //!!! this should all be in rosegardenguiview
+
+ QuantizeDialog dialog(m_view);
+ if (dialog.exec() != QDialog::Accepted)
+ return ;
+
+ SegmentSelection selection = m_view->getSelection();
+
+ KMacroCommand *command = new KMacroCommand
+ (EventQuantizeCommand::getGlobalName());
+
+ for (SegmentSelection::iterator i = selection.begin();
+ i != selection.end(); ++i) {
+ command->addCommand(new EventQuantizeCommand
+ (**i, (*i)->getStartTime(), (*i)->getEndTime(),
+ dialog.getQuantizer()));
+ }
+
+ m_view->slotAddCommandToHistory(command);
+}
+
+void RosegardenGUIApp::slotRepeatQuantizeSelection()
+{
+ if (!m_view->haveSelection())
+ return ;
+
+ //!!! this should all be in rosegardenguiview
+
+ SegmentSelection selection = m_view->getSelection();
+
+ KMacroCommand *command = new KMacroCommand
+ (EventQuantizeCommand::getGlobalName());
+
+ for (SegmentSelection::iterator i = selection.begin();
+ i != selection.end(); ++i) {
+ command->addCommand(new EventQuantizeCommand
+ (**i, (*i)->getStartTime(), (*i)->getEndTime(),
+ "Quantize Dialog Grid", false)); // no i18n (config group name)
+ }
+
+ m_view->slotAddCommandToHistory(command);
+}
+
+void RosegardenGUIApp::slotGrooveQuantize()
+{
+ if (!m_view->haveSelection())
+ return ;
+
+ SegmentSelection selection = m_view->getSelection();
+
+ if (selection.size() != 1) {
+ KMessageBox::sorry(this, i18n("This function needs no more than one segment to be selected."));
+ return ;
+ }
+
+ Segment *s = *selection.begin();
+ m_view->slotAddCommandToHistory(new CreateTempoMapFromSegmentCommand(s));
+}
+
+void RosegardenGUIApp::slotJoinSegments()
+{
+ if (!m_view->haveSelection())
+ return ;
+
+ //!!! this should all be in rosegardenguiview
+ //!!! should it?
+
+ SegmentSelection selection = m_view->getSelection();
+ if (selection.size() == 0)
+ return ;
+
+ for (SegmentSelection::iterator i = selection.begin();
+ i != selection.end(); ++i) {
+ if ((*i)->getType() != Segment::Internal) {
+ KMessageBox::sorry(this, i18n("Can't join Audio segments"));
+ return ;
+ }
+ }
+
+ m_view->slotAddCommandToHistory(new SegmentJoinCommand(selection));
+ m_view->updateSelectionContents();
+}
+
+void RosegardenGUIApp::slotRescaleSelection()
+{
+ if (!m_view->haveSelection())
+ return ;
+
+ //!!! this should all be in rosegardenguiview
+ //!!! should it?
+
+ SegmentSelection selection = m_view->getSelection();
+
+ timeT startTime = 0, endTime = 0;
+ for (SegmentSelection::iterator i = selection.begin();
+ i != selection.end(); ++i) {
+ if ((i == selection.begin()) || ((*i)->getStartTime() < startTime)) {
+ startTime = (*i)->getStartTime();
+ }
+ if ((i == selection.begin()) || ((*i)->getEndMarkerTime() > endTime)) {
+ endTime = (*i)->getEndMarkerTime();
+ }
+ }
+
+ RescaleDialog dialog(m_view, &m_doc->getComposition(),
+ startTime, endTime - startTime,
+ false, false);
+ if (dialog.exec() != QDialog::Accepted)
+ return ;
+
+ std::vector<AudioSegmentRescaleCommand *> asrcs;
+
+ int mult = dialog.getNewDuration();
+ int div = endTime - startTime;
+ float ratio = float(mult) / float(div);
+
+ std::cerr << "slotRescaleSelection: mult = " << mult << ", div = " << div << ", ratio = " << ratio << std::endl;
+
+ KMacroCommand *command = new KMacroCommand
+ (SegmentRescaleCommand::getGlobalName());
+
+ bool pathTested = false;
+
+ for (SegmentSelection::iterator i = selection.begin();
+ i != selection.end(); ++i) {
+ if ((*i)->getType() == Segment::Audio) {
+ if (!pathTested) {
+ testAudioPath(i18n("rescaling an audio file"));
+ pathTested = true;
+ }
+ AudioSegmentRescaleCommand *asrc = new AudioSegmentRescaleCommand
+ (m_doc, *i, ratio);
+ command->addCommand(asrc);
+ asrcs.push_back(asrc);
+ } else {
+ command->addCommand(new SegmentRescaleCommand(*i, mult, div));
+ }
+ }
+
+ ProgressDialog *progressDlg = 0;
+
+ if (!asrcs.empty()) {
+ progressDlg = new ProgressDialog
+ (i18n("Rescaling audio file..."), 100, this);
+ progressDlg->setAutoClose(false);
+ progressDlg->setAutoReset(false);
+ progressDlg->show();
+ for (size_t i = 0; i < asrcs.size(); ++i) {
+ asrcs[i]->connectProgressDialog(progressDlg);
+ }
+ }
+
+ m_view->slotAddCommandToHistory(command);
+
+ if (!asrcs.empty()) {
+
+ progressDlg->setLabel(i18n("Generating audio preview..."));
+
+ for (size_t i = 0; i < asrcs.size(); ++i) {
+ asrcs[i]->disconnectProgressDialog(progressDlg);
+ }
+
+ connect(&m_doc->getAudioFileManager(), SIGNAL(setProgress(int)),
+ progressDlg->progressBar(), SLOT(setValue(int)));
+ connect(progressDlg, SIGNAL(cancelClicked()),
+ &m_doc->getAudioFileManager(), SLOT(slotStopPreview()));
+
+ for (size_t i = 0; i < asrcs.size(); ++i) {
+ int fid = asrcs[i]->getNewAudioFileId();
+ if (fid >= 0) {
+ slotAddAudioFile(fid);
+ m_doc->getAudioFileManager().generatePreview(fid);
+ }
+ }
+ }
+
+ if (progressDlg) delete progressDlg;
+}
+
+bool
+RosegardenGUIApp::testAudioPath(QString op)
+{
+ try {
+ m_doc->getAudioFileManager().testAudioPath();
+ } catch (AudioFileManager::BadAudioPathException) {
+ if (KMessageBox::warningContinueCancel
+ (this,
+ i18n("The audio file path does not exist or is not writable.\nYou must set the audio file path to a valid directory in Document Properties before %1.\nWould you like to set it now?").arg(op),
+ i18n("Warning"),
+ i18n("Set audio file path")) == KMessageBox::Continue) {
+ slotOpenAudioPathSettings();
+ }
+ return false;
+ }
+ return true;
+}
+
+void RosegardenGUIApp::slotAutoSplitSelection()
+{
+ if (!m_view->haveSelection())
+ return ;
+
+ //!!! this should all be in rosegardenguiview
+ //!!! or should it?
+
+ SegmentSelection selection = m_view->getSelection();
+
+ KMacroCommand *command = new KMacroCommand
+ (SegmentAutoSplitCommand::getGlobalName());
+
+ for (SegmentSelection::iterator i = selection.begin();
+ i != selection.end(); ++i) {
+
+ if ((*i)->getType() == Segment::Audio) {
+ AudioSplitDialog aSD(this, (*i), m_doc);
+
+ if (aSD.exec() == QDialog::Accepted) {
+ // split to threshold
+ //
+ command->addCommand(
+ new AudioSegmentAutoSplitCommand(m_doc,
+ *i,
+ aSD.getThreshold()));
+ // dmm - verifying that widget->value() accessors *can* work without crashing
+ // std::cout << "SILVAN: getThreshold() = " << aSD.getThreshold() << std::endl;
+ }
+ } else {
+ command->addCommand(new SegmentAutoSplitCommand(*i));
+ }
+ }
+
+ m_view->slotAddCommandToHistory(command);
+}
+
+void RosegardenGUIApp::slotJogLeft()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotJogLeft" << endl;
+ jogSelection( -Note(Note::Demisemiquaver).getDuration());
+}
+
+void RosegardenGUIApp::slotJogRight()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotJogRight" << endl;
+ jogSelection(Note(Note::Demisemiquaver).getDuration());
+}
+
+void RosegardenGUIApp::jogSelection(timeT amount)
+{
+ if (!m_view->haveSelection())
+ return ;
+
+ SegmentSelection selection = m_view->getSelection();
+
+ SegmentReconfigureCommand *command = new SegmentReconfigureCommand(i18n("Jog Selection"));
+
+ for (SegmentSelection::iterator i = selection.begin();
+ i != selection.end(); ++i) {
+
+ command->addSegment((*i),
+ (*i)->getStartTime() + amount,
+ (*i)->getEndMarkerTime() + amount,
+ (*i)->getTrack());
+ }
+
+ m_view->slotAddCommandToHistory(command);
+}
+
+void RosegardenGUIApp::createAndSetupTransport()
+{
+ // create the Transport GUI and add the callbacks to the
+ // buttons and keyboard accelerators
+ //
+ m_transport =
+ new TransportDialog(this);
+ plugAccelerators(m_transport, m_transport->getAccelerators());
+
+ m_transport->getAccelerators()->connectItem
+ (m_transport->getAccelerators()->insertItem(Key_T),
+ this,
+ SLOT(slotHideTransport()));
+
+ // Ensure that the checkbox is unchecked if the dialog
+ // is closed
+ connect(m_transport, SIGNAL(closed()),
+ SLOT(slotCloseTransport()));
+
+ // Handle loop setting and unsetting from the transport loop button
+ //
+
+ connect(m_transport, SIGNAL(setLoop()), SLOT(slotSetLoop()));
+ connect(m_transport, SIGNAL(unsetLoop()), SLOT(slotUnsetLoop()));
+ connect(m_transport, SIGNAL(panic()), SLOT(slotPanic()));
+
+ connect(m_transport, SIGNAL(editTempo(QWidget*)),
+ SLOT(slotEditTempo(QWidget*)));
+
+ connect(m_transport, SIGNAL(editTimeSignature(QWidget*)),
+ SLOT(slotEditTimeSignature(QWidget*)));
+
+ connect(m_transport, SIGNAL(editTransportTime(QWidget*)),
+ SLOT(slotEditTransportTime(QWidget*)));
+
+ // Handle set loop start/stop time buttons.
+ //
+ connect(m_transport, SIGNAL(setLoopStartTime()), SLOT(slotSetLoopStart()));
+ connect(m_transport, SIGNAL(setLoopStopTime()), SLOT(slotSetLoopStop()));
+
+ if (m_seqManager != 0)
+ m_seqManager->setTransport(m_transport);
+
+}
+
+void RosegardenGUIApp::slotSplitSelectionByPitch()
+{
+ if (!m_view->haveSelection())
+ return ;
+
+ SplitByPitchDialog dialog(m_view);
+ if (dialog.exec() != QDialog::Accepted)
+ return ;
+
+ SegmentSelection selection = m_view->getSelection();
+
+ KMacroCommand *command = new KMacroCommand
+ (SegmentSplitByPitchCommand::getGlobalName());
+
+ bool haveSomething = false;
+
+ for (SegmentSelection::iterator i = selection.begin();
+ i != selection.end(); ++i) {
+
+ if ((*i)->getType() == Segment::Audio) {
+ // nothing
+ } else {
+ command->addCommand
+ (new SegmentSplitByPitchCommand
+ (*i,
+ dialog.getPitch(),
+ dialog.getShouldRange(),
+ dialog.getShouldDuplicateNonNoteEvents(),
+ (SegmentSplitByPitchCommand::ClefHandling)
+ dialog.getClefHandling()));
+ haveSomething = true;
+ }
+ }
+
+ if (haveSomething)
+ m_view->slotAddCommandToHistory(command);
+ //!!! else complain
+}
+
+void
+RosegardenGUIApp::slotSplitSelectionByRecordedSrc()
+{
+ if (!m_view->haveSelection())
+ return ;
+
+ SplitByRecordingSrcDialog dialog(m_view, m_doc);
+ if (dialog.exec() != QDialog::Accepted)
+ return ;
+
+ SegmentSelection selection = m_view->getSelection();
+
+ KMacroCommand *command = new KMacroCommand
+ (SegmentSplitByRecordingSrcCommand::getGlobalName());
+
+ bool haveSomething = false;
+
+ for (SegmentSelection::iterator i = selection.begin();
+ i != selection.end(); ++i) {
+
+ if ((*i)->getType() == Segment::Audio) {
+ // nothing
+ } else {
+ command->addCommand
+ (new SegmentSplitByRecordingSrcCommand(*i,
+ dialog.getChannel(),
+ dialog.getDevice()));
+ haveSomething = true;
+ }
+ }
+ if (haveSomething)
+ m_view->slotAddCommandToHistory(command);
+}
+
+void
+RosegardenGUIApp::slotSplitSelectionAtTime()
+{
+ if (!m_view->haveSelection())
+ return ;
+
+ SegmentSelection selection = m_view->getSelection();
+ if (selection.empty())
+ return ;
+
+ timeT now = m_doc->getComposition().getPosition();
+
+ QString title = i18n("Split Segment at Time",
+ "Split %n Segments at Time",
+ selection.size());
+
+ TimeDialog dialog(m_view, title,
+ &m_doc->getComposition(),
+ now, true);
+
+ KMacroCommand *command = new KMacroCommand( title );
+
+ if (dialog.exec() == QDialog::Accepted) {
+ for (SegmentSelection::iterator i = selection.begin();
+ i != selection.end(); ++i) {
+
+ if ((*i)->getType() == Segment::Audio) {
+ command->addCommand(new AudioSegmentSplitCommand(*i, dialog.getTime()));
+ } else {
+ command->addCommand(new SegmentSplitCommand(*i, dialog.getTime()));
+ }
+ }
+ m_view->slotAddCommandToHistory(command);
+ }
+}
+
+void
+RosegardenGUIApp::slotSetSegmentStartTimes()
+{
+ if (!m_view->haveSelection())
+ return ;
+
+ SegmentSelection selection = m_view->getSelection();
+ if (selection.empty())
+ return ;
+
+ timeT someTime = (*selection.begin())->getStartTime();
+
+ TimeDialog dialog(m_view, i18n("Segment Start Time"),
+ &m_doc->getComposition(),
+ someTime, false);
+
+ if (dialog.exec() == QDialog::Accepted) {
+
+ bool plural = (selection.size() > 1);
+
+ SegmentReconfigureCommand *command =
+ new SegmentReconfigureCommand(plural ?
+ i18n("Set Segment Start Times") :
+ i18n("Set Segment Start Time"));
+
+ for (SegmentSelection::iterator i = selection.begin();
+ i != selection.end(); ++i) {
+
+ command->addSegment
+ (*i, dialog.getTime(),
+ (*i)->getEndMarkerTime() - (*i)->getStartTime() + dialog.getTime(),
+ (*i)->getTrack());
+ }
+
+ m_view->slotAddCommandToHistory(command);
+ }
+}
+
+void
+RosegardenGUIApp::slotSetSegmentDurations()
+{
+ if (!m_view->haveSelection())
+ return ;
+
+ SegmentSelection selection = m_view->getSelection();
+ if (selection.empty())
+ return ;
+
+ timeT someTime =
+ (*selection.begin())->getStartTime();
+
+ timeT someDuration =
+ (*selection.begin())->getEndMarkerTime() -
+ (*selection.begin())->getStartTime();
+
+ TimeDialog dialog(m_view, i18n("Segment Duration"),
+ &m_doc->getComposition(),
+ someTime,
+ someDuration,
+ false);
+
+ if (dialog.exec() == QDialog::Accepted) {
+
+ bool plural = (selection.size() > 1);
+
+ SegmentReconfigureCommand *command =
+ new SegmentReconfigureCommand(plural ?
+ i18n("Set Segment Durations") :
+ i18n("Set Segment Duration"));
+
+ for (SegmentSelection::iterator i = selection.begin();
+ i != selection.end(); ++i) {
+
+ command->addSegment
+ (*i, (*i)->getStartTime(),
+ (*i)->getStartTime() + dialog.getTime(),
+ (*i)->getTrack());
+ }
+
+ m_view->slotAddCommandToHistory(command);
+ }
+}
+
+void RosegardenGUIApp::slotHarmonizeSelection()
+{
+ if (!m_view->haveSelection())
+ return ;
+
+ SegmentSelection selection = m_view->getSelection();
+ //!!! This should be somewhere else too
+
+ CompositionTimeSliceAdapter adapter(&m_doc->getComposition(),
+ &selection);
+
+ AnalysisHelper helper;
+ Segment *segment = new Segment;
+ helper.guessHarmonies(adapter, *segment);
+
+ //!!! do nothing with the results yet
+ delete segment;
+}
+
+void RosegardenGUIApp::slotTempoToSegmentLength()
+{
+ slotTempoToSegmentLength(this);
+}
+
+void RosegardenGUIApp::slotTempoToSegmentLength(QWidget* parent)
+{
+ RG_DEBUG << "RosegardenGUIApp::slotTempoToSegmentLength" << endl;
+
+ if (!m_view->haveSelection())
+ return ;
+
+ SegmentSelection selection = m_view->getSelection();
+
+ // Only set for a single selection
+ //
+ if (selection.size() == 1 &&
+ (*selection.begin())->getType() == Segment::Audio) {
+ Composition &comp = m_doc->getComposition();
+ Segment *seg = *selection.begin();
+
+ TimeSignature timeSig =
+ comp.getTimeSignatureAt( seg->getStartTime());
+
+ timeT endTime = seg->getEndTime();
+
+ if (seg->getRawEndMarkerTime())
+ endTime = seg->getEndMarkerTime();
+
+ RealTime segDuration =
+ seg->getAudioEndTime() - seg->getAudioStartTime();
+
+ int beats = 0;
+
+ // Get user to tell us how many beats or bars the segment contains
+ BeatsBarsDialog dialog(parent);
+ if (dialog.exec() == QDialog::Accepted) {
+ beats = dialog.getQuantity(); // beats (or bars)
+ if (dialog.getMode() == 1) // bars (multiply by time sig)
+ beats *= timeSig.getBeatsPerBar();
+#ifdef DEBUG_TEMPO_FROM_AUDIO
+
+ RG_DEBUG << "RosegardenGUIApp::slotTempoToSegmentLength - beats = " << beats
+ << " mode = " << ((dialog.getMode() == 0) ? "bars" : "beats") << endl
+ << " beats per bar = " << timeSig.getBeatsPerBar()
+ << " user quantity = " << dialog.getQuantity()
+ << " user mode = " << dialog.getMode() << endl;
+#endif
+
+ } else {
+ RG_DEBUG << "RosegardenGUIApp::slotTempoToSegmentLength - BeatsBarsDialog aborted"
+ << endl;
+ return ;
+ }
+
+ double beatLengthUsec =
+ double(segDuration.sec * 1000000 + segDuration.usec()) /
+ double(beats);
+
+ // New tempo is a minute divided by time of beat
+ // converted up (#1414252) to a sane value via getTempoFoQpm()
+ //
+ tempoT newTempo =
+ comp.getTempoForQpm(60.0 * 1000000.0 / beatLengthUsec);
+
+#ifdef DEBUG_TEMPO_FROM_AUDIO
+
+ RG_DEBUG << "RosegardenGUIApp::slotTempoToSegmentLength info: " << endl
+ << " beatLengthUsec = " << beatLengthUsec << endl
+ << " segDuration.usec = " << segDuration.usec() << endl
+ << " newTempo = " << newTempo << endl;
+#endif
+
+ KMacroCommand *macro = new KMacroCommand(i18n("Set Global Tempo"));
+
+ // Remove all tempo changes in reverse order so as the index numbers
+ // don't becoming meaningless as the command gets unwound.
+ //
+ for (int i = 0; i < comp.getTempoChangeCount(); i++)
+ macro->addCommand(new RemoveTempoChangeCommand(&comp,
+ (comp.getTempoChangeCount() - 1 - i)));
+
+ // add tempo change at time zero
+ //
+ macro->addCommand(new AddTempoChangeCommand(&comp, 0, newTempo));
+
+ // execute
+ m_doc->getCommandHistory()->addCommand(macro);
+ }
+}
+
+void RosegardenGUIApp::slotToggleSegmentLabels()
+{
+ KToggleAction* act = dynamic_cast<KToggleAction*>(actionCollection()->action("show_segment_labels"));
+ if (act) {
+ m_view->slotShowSegmentLabels(act->isChecked());
+ }
+}
+
+void RosegardenGUIApp::slotEdit()
+{
+ m_view->slotEditSegment(0);
+}
+
+void RosegardenGUIApp::slotEditAsNotation()
+{
+ m_view->slotEditSegmentNotation(0);
+}
+
+void RosegardenGUIApp::slotEditInMatrix()
+{
+ m_view->slotEditSegmentMatrix(0);
+}
+
+void RosegardenGUIApp::slotEditInPercussionMatrix()
+{
+ m_view->slotEditSegmentPercussionMatrix(0);
+}
+
+void RosegardenGUIApp::slotEditInEventList()
+{
+ m_view->slotEditSegmentEventList(0);
+}
+
+void RosegardenGUIApp::slotEditTempos()
+{
+ slotEditTempos(m_doc->getComposition().getPosition());
+}
+
+void RosegardenGUIApp::slotToggleToolBar()
+{
+ KTmpStatusMsg msg(i18n("Toggle the toolbar..."), this);
+
+ if (m_viewToolBar->isChecked())
+ toolBar("mainToolBar")->show();
+ else
+ toolBar("mainToolBar")->hide();
+}
+
+void RosegardenGUIApp::slotToggleToolsToolBar()
+{
+ KTmpStatusMsg msg(i18n("Toggle the tools toolbar..."), this);
+
+ if (m_viewToolsToolBar->isChecked())
+ toolBar("Tools Toolbar")->show();
+ else
+ toolBar("Tools Toolbar")->hide();
+}
+
+void RosegardenGUIApp::slotToggleTracksToolBar()
+{
+ KTmpStatusMsg msg(i18n("Toggle the tracks toolbar..."), this);
+
+ if (m_viewTracksToolBar->isChecked())
+ toolBar("Tracks Toolbar")->show();
+ else
+ toolBar("Tracks Toolbar")->hide();
+}
+
+void RosegardenGUIApp::slotToggleEditorsToolBar()
+{
+ KTmpStatusMsg msg(i18n("Toggle the editor toolbar..."), this);
+
+ if (m_viewEditorsToolBar->isChecked())
+ toolBar("Editors Toolbar")->show();
+ else
+ toolBar("Editors Toolbar")->hide();
+}
+
+void RosegardenGUIApp::slotToggleTransportToolBar()
+{
+ KTmpStatusMsg msg(i18n("Toggle the transport toolbar..."), this);
+
+ if (m_viewTransportToolBar->isChecked())
+ toolBar("Transport Toolbar")->show();
+ else
+ toolBar("Transport Toolbar")->hide();
+}
+
+void RosegardenGUIApp::slotToggleZoomToolBar()
+{
+ KTmpStatusMsg msg(i18n("Toggle the zoom toolbar..."), this);
+
+ if (m_viewZoomToolBar->isChecked())
+ toolBar("Zoom Toolbar")->show();
+ else
+ toolBar("Zoom Toolbar")->hide();
+}
+
+void RosegardenGUIApp::slotToggleTransport()
+{
+ KTmpStatusMsg msg(i18n("Toggle the Transport"), this);
+
+ if (m_viewTransport->isChecked()) {
+ getTransport()->show();
+ getTransport()->raise();
+ getTransport()->blockSignals(false);
+ } else {
+ getTransport()->hide();
+ getTransport()->blockSignals(true);
+ }
+}
+
+void RosegardenGUIApp::slotHideTransport()
+{
+ if (m_viewTransport->isChecked()) {
+ m_viewTransport->blockSignals(true);
+ m_viewTransport->setChecked(false);
+ m_viewTransport->blockSignals(false);
+ }
+ getTransport()->hide();
+ getTransport()->blockSignals(true);
+}
+
+void RosegardenGUIApp::slotToggleTrackLabels()
+{
+ if (m_viewTrackLabels->isChecked()) {
+#ifdef SETTING_LOG_DEBUG
+ _settingLog("toggle track labels on");
+#endif
+
+ m_view->getTrackEditor()->getTrackButtons()->
+ changeTrackInstrumentLabels(TrackLabel::ShowTrack);
+ } else {
+#ifdef SETTING_LOG_DEBUG
+ _settingLog("toggle track labels off");
+#endif
+
+ m_view->getTrackEditor()->getTrackButtons()->
+ changeTrackInstrumentLabels(TrackLabel::ShowInstrument);
+ }
+}
+
+void RosegardenGUIApp::slotToggleRulers()
+{
+ m_view->slotShowRulers(m_viewRulers->isChecked());
+}
+
+void RosegardenGUIApp::slotToggleTempoRuler()
+{
+ m_view->slotShowTempoRuler(m_viewTempoRuler->isChecked());
+}
+
+void RosegardenGUIApp::slotToggleChordNameRuler()
+{
+ m_view->slotShowChordNameRuler(m_viewChordNameRuler->isChecked());
+}
+
+void RosegardenGUIApp::slotTogglePreviews()
+{
+ m_view->slotShowPreviews(m_viewPreviews->isChecked());
+}
+
+void RosegardenGUIApp::slotDockParametersBack()
+{
+ m_dockLeft->dockBack();
+}
+
+void RosegardenGUIApp::slotParametersClosed()
+{
+ stateChanged("parametersbox_closed");
+ m_dockVisible = false;
+}
+
+void RosegardenGUIApp::slotParametersDockedBack(KDockWidget* dw, KDockWidget::DockPosition)
+{
+ if (dw == m_dockLeft) {
+ stateChanged("parametersbox_closed", KXMLGUIClient::StateReverse);
+ m_dockVisible = true;
+ }
+}
+
+void RosegardenGUIApp::slotToggleStatusBar()
+{
+ KTmpStatusMsg msg(i18n("Toggle the statusbar..."), this);
+
+ if (!m_viewStatusBar->isChecked())
+ statusBar()->hide();
+ else
+ statusBar()->show();
+}
+
+void RosegardenGUIApp::slotStatusMsg(QString text)
+{
+ ///////////////////////////////////////////////////////////////////
+ // change status message permanently
+ statusBar()->clear();
+ statusBar()->changeItem(text, EditViewBase::ID_STATUS_MSG);
+}
+
+void RosegardenGUIApp::slotStatusHelpMsg(QString text)
+{
+ ///////////////////////////////////////////////////////////////////
+ // change status message of whole statusbar temporary (text, msec)
+ statusBar()->message(text, 2000);
+}
+
+void RosegardenGUIApp::slotEnableTransport(bool enable)
+{
+ if (m_transport)
+ getTransport()->setEnabled(enable);
+}
+
+void RosegardenGUIApp::slotPointerSelected()
+{
+ m_view->selectTool(SegmentSelector::ToolName);
+}
+
+void RosegardenGUIApp::slotEraseSelected()
+{
+ m_view->selectTool(SegmentEraser::ToolName);
+}
+
+void RosegardenGUIApp::slotDrawSelected()
+{
+ m_view->selectTool(SegmentPencil::ToolName);
+}
+
+void RosegardenGUIApp::slotMoveSelected()
+{
+ m_view->selectTool(SegmentMover::ToolName);
+}
+
+void RosegardenGUIApp::slotResizeSelected()
+{
+ m_view->selectTool(SegmentResizer::ToolName);
+}
+
+void RosegardenGUIApp::slotJoinSelected()
+{
+ KMessageBox::information(this,
+ i18n("The join tool isn't implemented yet. Instead please highlight "
+ "the segments you want to join and then use the menu option:\n\n"
+ " Segments->Collapse Segments.\n"),
+ i18n("Join tool not yet implemented"));
+
+ m_view->selectTool(SegmentJoiner::ToolName);
+}
+
+void RosegardenGUIApp::slotSplitSelected()
+{
+ m_view->selectTool(SegmentSplitter::ToolName);
+}
+
+void RosegardenGUIApp::slotAddTrack()
+{
+ if (!m_view)
+ return ;
+
+ // default to the base number - might not actually exist though
+ //
+ InstrumentId id = MidiInstrumentBase;
+
+ // Get the first Internal/MIDI instrument
+ //
+ DeviceList *devices = m_doc->getStudio().getDevices();
+ bool have = false;
+
+ for (DeviceList::iterator it = devices->begin();
+ it != devices->end() && !have; it++) {
+
+ if ((*it)->getType() != Device::Midi)
+ continue;
+
+ InstrumentList instruments = (*it)->getAllInstruments();
+ for (InstrumentList::iterator iit = instruments.begin();
+ iit != instruments.end(); iit++) {
+
+ if ((*iit)->getId() >= MidiInstrumentBase) {
+ id = (*iit)->getId();
+ have = true;
+ break;
+ }
+ }
+ }
+
+ Composition &comp = m_doc->getComposition();
+ TrackId trackId = comp.getSelectedTrack();
+ Track *track = comp.getTrackById(trackId);
+
+ int pos = -1;
+ if (track) pos = track->getPosition() + 1;
+
+ m_view->slotAddTracks(1, id, pos);
+}
+
+void RosegardenGUIApp::slotAddTracks()
+{
+ if (!m_view)
+ return ;
+
+ // default to the base number - might not actually exist though
+ //
+ InstrumentId id = MidiInstrumentBase;
+
+ // Get the first Internal/MIDI instrument
+ //
+ DeviceList *devices = m_doc->getStudio().getDevices();
+ bool have = false;
+
+ for (DeviceList::iterator it = devices->begin();
+ it != devices->end() && !have; it++) {
+
+ if ((*it)->getType() != Device::Midi)
+ continue;
+
+ InstrumentList instruments = (*it)->getAllInstruments();
+ for (InstrumentList::iterator iit = instruments.begin();
+ iit != instruments.end(); iit++) {
+
+ if ((*iit)->getId() >= MidiInstrumentBase) {
+ id = (*iit)->getId();
+ have = true;
+ break;
+ }
+ }
+ }
+
+ Composition &comp = m_doc->getComposition();
+ TrackId trackId = comp.getSelectedTrack();
+ Track *track = comp.getTrackById(trackId);
+
+ int pos = 0;
+ if (track) pos = track->getPosition();
+
+ bool ok = false;
+
+ AddTracksDialog dialog(this, pos);
+
+ if (dialog.exec() == QDialog::Accepted) {
+ m_view->slotAddTracks(dialog.getTracks(), id,
+ dialog.getInsertPosition());
+ }
+}
+
+void RosegardenGUIApp::slotDeleteTrack()
+{
+ if (!m_view)
+ return ;
+
+ Composition &comp = m_doc->getComposition();
+ TrackId trackId = comp.getSelectedTrack();
+ Track *track = comp.getTrackById(trackId);
+
+ RG_DEBUG << "RosegardenGUIApp::slotDeleteTrack() : about to delete track id "
+ << trackId << endl;
+
+ if (track == 0)
+ return ;
+
+ // Always have at least one track in a composition
+ //
+ if (comp.getNbTracks() == 1)
+ return ;
+
+ // VLADA
+ if (m_view->haveSelection()) {
+
+ SegmentSelection selection = m_view->getSelection();
+ m_view->slotSelectTrackSegments(trackId);
+ m_view->getTrackEditor()->slotDeleteSelectedSegments();
+ m_view->slotPropagateSegmentSelection(selection);
+
+ } else {
+
+ m_view->slotSelectTrackSegments(trackId);
+ m_view->getTrackEditor()->slotDeleteSelectedSegments();
+ }
+ //VLADA
+
+ int position = track->getPosition();
+
+ // Delete the track
+ //
+ std::vector<TrackId> tracks;
+ tracks.push_back(trackId);
+
+ m_view->slotDeleteTracks(tracks);
+
+ // Select a new valid track
+ //
+ if (comp.getTrackByPosition(position))
+ trackId = comp.getTrackByPosition(position)->getId();
+ else if (comp.getTrackByPosition(position - 1))
+ trackId = comp.getTrackByPosition(position - 1)->getId();
+ else {
+ RG_DEBUG << "RosegardenGUIApp::slotDeleteTrack - "
+ << "can't select a highlighted track after delete"
+ << endl;
+ }
+
+ comp.setSelectedTrack(trackId);
+
+ Instrument *inst = m_doc->getStudio().
+ getInstrumentById(comp.getTrackById(trackId)->getInstrument());
+
+ //VLADA
+ // m_view->slotSelectTrackSegments(trackId);
+ //VLADA
+}
+
+void RosegardenGUIApp::slotMoveTrackDown()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotMoveTrackDown" << endl;
+
+ Composition &comp = m_doc->getComposition();
+ Track *srcTrack = comp.getTrackById(comp.getSelectedTrack());
+
+ // Check for track object
+ //
+ if (srcTrack == 0)
+ return ;
+
+ // Check destination track exists
+ //
+ Track *destTrack =
+ comp.getTrackByPosition(srcTrack->getPosition() + 1);
+
+ if (destTrack == 0)
+ return ;
+
+ MoveTracksCommand *command =
+ new MoveTracksCommand(&comp, srcTrack->getId(), destTrack->getId());
+
+ m_doc->getCommandHistory()->addCommand(command);
+
+ // make sure we're showing the right selection
+ m_view->slotSelectTrackSegments(comp.getSelectedTrack());
+
+}
+
+void RosegardenGUIApp::slotMoveTrackUp()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotMoveTrackUp" << endl;
+
+ Composition &comp = m_doc->getComposition();
+ Track *srcTrack = comp.getTrackById(comp.getSelectedTrack());
+
+ // Check for track object
+ //
+ if (srcTrack == 0)
+ return ;
+
+ // Check we're not at the top already
+ //
+ if (srcTrack->getPosition() == 0)
+ return ;
+
+ // Check destination track exists
+ //
+ Track *destTrack =
+ comp.getTrackByPosition(srcTrack->getPosition() - 1);
+
+ if (destTrack == 0)
+ return ;
+
+ MoveTracksCommand *command =
+ new MoveTracksCommand(&comp, srcTrack->getId(), destTrack->getId());
+
+ m_doc->getCommandHistory()->addCommand(command);
+
+ // make sure we're showing the right selection
+ m_view->slotSelectTrackSegments(comp.getSelectedTrack());
+}
+
+void RosegardenGUIApp::slotRevertToSaved()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotRevertToSaved" << endl;
+
+ if (m_doc->isModified()) {
+ int revert =
+ KMessageBox::questionYesNo(this,
+ i18n("Revert modified document to previous saved version?"));
+
+ if (revert == KMessageBox::No)
+ return ;
+
+ openFile(m_doc->getAbsFilePath());
+ }
+}
+
+void RosegardenGUIApp::slotImportProject()
+{
+ if (m_doc && !m_doc->saveIfModified())
+ return ;
+
+ KURL url = KFileDialog::getOpenURL
+ (":RGPROJECT",
+ i18n("*.rgp|Rosegarden Project files\n*|All files"), this,
+ i18n("Import Rosegarden Project File"));
+ if (url.isEmpty()) {
+ return ;
+ }
+
+ QString tmpfile;
+ KIO::NetAccess::download(url, tmpfile, this);
+
+ importProject(tmpfile);
+
+ KIO::NetAccess::removeTempFile(tmpfile);
+}
+
+void RosegardenGUIApp::importProject(QString filePath)
+{
+ KProcess *proc = new KProcess;
+ *proc << "rosegarden-project-package";
+ *proc << "--unpack";
+ *proc << filePath;
+
+ KStartupLogo::hideIfStillThere();
+ proc->start(KProcess::Block, KProcess::All);
+
+ if (!proc->normalExit() || proc->exitStatus()) {
+ CurrentProgressDialog::freeze();
+ KMessageBox::sorry(this, i18n("Failed to import project file \"%1\"").arg(filePath));
+ CurrentProgressDialog::thaw();
+ delete proc;
+ return ;
+ }
+
+ delete proc;
+
+ QString rgFile = filePath;
+ rgFile.replace(QRegExp(".rg.rgp$"), ".rg");
+ rgFile.replace(QRegExp(".rgp$"), ".rg");
+ openURL(rgFile);
+}
+
+void RosegardenGUIApp::slotImportMIDI()
+{
+ if (m_doc && !m_doc->saveIfModified())
+ return ;
+
+ KURL url = KFileDialog::getOpenURL
+ (":MIDI",
+ "audio/x-midi", this,
+ i18n("Open MIDI File"));
+ if (url.isEmpty()) {
+ return ;
+ }
+
+ QString tmpfile;
+ KIO::NetAccess::download(url, tmpfile, this);
+ openFile(tmpfile, ImportMIDI); // does everything including setting the document
+
+ KIO::NetAccess::removeTempFile( tmpfile );
+}
+
+void RosegardenGUIApp::slotMergeMIDI()
+{
+ KURL url = KFileDialog::getOpenURL
+ (":MIDI",
+ "audio/x-midi", this,
+ i18n("Merge MIDI File"));
+ if (url.isEmpty()) {
+ return ;
+ }
+
+ QString tmpfile;
+ KIO::NetAccess::download(url, tmpfile, this);
+ mergeFile(tmpfile, ImportMIDI);
+
+ KIO::NetAccess::removeTempFile( tmpfile );
+}
+
+QTextCodec *
+RosegardenGUIApp::guessTextCodec(std::string text)
+{
+ QTextCodec *codec = 0;
+
+ for (int c = 0; c < text.length(); ++c) {
+ if (text[c] & 0x80) {
+
+ CurrentProgressDialog::freeze();
+ KStartupLogo::hideIfStillThere();
+
+ IdentifyTextCodecDialog dialog(0, text);
+ dialog.exec();
+
+ std::string codecName = dialog.getCodec();
+
+ CurrentProgressDialog::thaw();
+
+ if (codecName != "") {
+ codec = QTextCodec::codecForName(codecName.c_str());
+ }
+ break;
+ }
+ }
+
+ return codec;
+}
+
+void
+RosegardenGUIApp::fixTextEncodings(Composition *c)
+
+{
+ QTextCodec *codec = 0;
+
+ for (Composition::iterator i = c->begin();
+ i != c->end(); ++i) {
+
+ for (Segment::iterator j = (*i)->begin();
+ j != (*i)->end(); ++j) {
+
+ if ((*j)->isa(Text::EventType)) {
+
+ std::string text;
+
+ if ((*j)->get
+ <String>
+ (Text::TextPropertyName, text)) {
+
+ if (!codec)
+ codec = guessTextCodec(text);
+
+ if (codec) {
+ (*j)->set
+ <String>
+ (Text::TextPropertyName,
+ convertFromCodec(text, codec));
+ }
+ }
+ }
+ }
+ }
+
+ if (!codec)
+ codec = guessTextCodec(c->getCopyrightNote());
+ if (codec)
+ c->setCopyrightNote(convertFromCodec(c->getCopyrightNote(), codec));
+
+ for (Composition::trackcontainer::iterator i =
+ c->getTracks().begin(); i != c->getTracks().end(); ++i) {
+ if (!codec)
+ codec = guessTextCodec(i->second->getLabel());
+ if (codec)
+ i->second->setLabel(convertFromCodec(i->second->getLabel(), codec));
+ }
+
+ for (Composition::iterator i = c->begin(); i != c->end(); ++i) {
+ if (!codec)
+ codec = guessTextCodec((*i)->getLabel());
+ if (codec)
+ (*i)->setLabel(convertFromCodec((*i)->getLabel(), codec));
+ }
+}
+
+RosegardenGUIDoc*
+RosegardenGUIApp::createDocumentFromMIDIFile(QString file)
+{
+ //if (!merge && !m_doc->saveIfModified()) return;
+
+ // Create new document (autoload is inherent)
+ //
+ RosegardenGUIDoc *newDoc = new RosegardenGUIDoc(this, m_pluginManager);
+
+ std::string fname(QFile::encodeName(file));
+
+ MidiFile midiFile(fname,
+ &newDoc->getStudio());
+
+ KStartupLogo::hideIfStillThere();
+ ProgressDialog progressDlg(i18n("Importing MIDI file..."),
+ 200,
+ this);
+
+ CurrentProgressDialog::set
+ (&progressDlg);
+
+ connect(&midiFile, SIGNAL(setProgress(int)),
+ progressDlg.progressBar(), SLOT(setValue(int)));
+
+ connect(&midiFile, SIGNAL(incrementProgress(int)),
+ progressDlg.progressBar(), SLOT(advance(int)));
+
+ if (!midiFile.open()) {
+ CurrentProgressDialog::freeze();
+ KMessageBox::error(this, strtoqstr(midiFile.getError())); //!!! i18n
+ delete newDoc;
+ return 0;
+ }
+
+ midiFile.convertToRosegarden(newDoc->getComposition(),
+ MidiFile::CONVERT_REPLACE);
+
+ fixTextEncodings(&newDoc->getComposition());
+
+ // Set modification flag
+ //
+ newDoc->slotDocumentModified();
+
+ // Set the caption
+ //
+ newDoc->setTitle(QFileInfo(file).fileName());
+ newDoc->setAbsFilePath(QFileInfo(file).absFilePath());
+
+ // Clean up for notation purposes (after reinitialise, because that
+ // sets the composition's end marker time which is needed here)
+
+ progressDlg.slotSetOperationName(i18n("Calculating notation..."));
+ ProgressDialog::processEvents();
+
+ Composition *comp = &newDoc->getComposition();
+
+ for (Composition::iterator i = comp->begin();
+ i != comp->end(); ++i) {
+
+ Segment &segment = **i;
+ SegmentNotationHelper helper(segment);
+ segment.insert(helper.guessClef(segment.begin(),
+ segment.getEndMarker()).getAsEvent
+ (segment.getStartTime()));
+ }
+
+ progressDlg.progressBar()->setProgress(100);
+
+ for (Composition::iterator i = comp->begin();
+ i != comp->end(); ++i) {
+
+ // find first key event in each segment (we'd have done the
+ // same for clefs, except there is no MIDI clef event)
+
+ Segment &segment = **i;
+ timeT firstKeyTime = segment.getEndMarkerTime();
+
+ for (Segment::iterator si = segment.begin();
+ segment.isBeforeEndMarker(si); ++si) {
+ if ((*si)->isa(Rosegarden::Key::EventType)) {
+ firstKeyTime = (*si)->getAbsoluteTime();
+ break;
+ }
+ }
+
+ if (firstKeyTime > segment.getStartTime()) {
+ CompositionTimeSliceAdapter adapter
+ (comp, timeT(0), firstKeyTime);
+ AnalysisHelper helper;
+ segment.insert(helper.guessKey(adapter).getAsEvent
+ (segment.getStartTime()));
+ }
+ }
+
+ int progressPer = 100;
+ if (comp->getNbSegments() > 0)
+ progressPer = (int)(100.0 / double(comp->getNbSegments()));
+
+ KMacroCommand *command = new KMacroCommand(i18n("Calculate Notation"));
+
+ for (Composition::iterator i = comp->begin();
+ i != comp->end(); ++i) {
+
+ Segment &segment = **i;
+ timeT startTime(segment.getStartTime());
+ timeT endTime(segment.getEndMarkerTime());
+
+// std::cerr << "segment: start time " << segment.getStartTime() << ", end time " << segment.getEndTime() << ", end marker time " << segment.getEndMarkerTime() << ", events " << segment.size() << std::endl;
+
+ EventQuantizeCommand *subCommand = new EventQuantizeCommand
+ (segment, startTime, endTime, "Notation Options", true);
+
+ subCommand->setProgressTotal(progressPer + 1);
+ QObject::connect(subCommand, SIGNAL(incrementProgress(int)),
+ progressDlg.progressBar(), SLOT(advance(int)));
+
+ command->addCommand(subCommand);
+ }
+
+ newDoc->getCommandHistory()->addCommand(command);
+
+ if (comp->getTimeSignatureCount() == 0) {
+ CompositionTimeSliceAdapter adapter(comp);
+ AnalysisHelper analysisHelper;
+ TimeSignature timeSig =
+ analysisHelper.guessTimeSignature(adapter);
+ comp->addTimeSignature(0, timeSig);
+ }
+
+ return newDoc;
+}
+
+void RosegardenGUIApp::slotImportRG21()
+{
+ if (m_doc && !m_doc->saveIfModified())
+ return ;
+
+ KURL url = KFileDialog::getOpenURL
+ (":ROSEGARDEN21",
+ i18n("*.rose|Rosegarden-2 files\n*|All files"), this,
+ i18n("Open Rosegarden 2.1 File"));
+ if (url.isEmpty()) {
+ return ;
+ }
+
+ QString tmpfile;
+ KIO::NetAccess::download(url, tmpfile, this);
+ openFile(tmpfile, ImportRG21);
+
+ KIO::NetAccess::removeTempFile(tmpfile);
+}
+
+void RosegardenGUIApp::slotMergeRG21()
+{
+ KURL url = KFileDialog::getOpenURL
+ (":ROSEGARDEN21",
+ i18n("*.rose|Rosegarden-2 files\n*|All files"), this,
+ i18n("Open Rosegarden 2.1 File"));
+ if (url.isEmpty()) {
+ return ;
+ }
+
+ QString tmpfile;
+ KIO::NetAccess::download(url, tmpfile, this);
+ mergeFile(tmpfile, ImportRG21);
+
+ KIO::NetAccess::removeTempFile( tmpfile );
+}
+
+RosegardenGUIDoc*
+RosegardenGUIApp::createDocumentFromRG21File(QString file)
+{
+ KStartupLogo::hideIfStillThere();
+ ProgressDialog progressDlg(
+ i18n("Importing Rosegarden 2.1 file..."), 100, this);
+
+ CurrentProgressDialog::set
+ (&progressDlg);
+
+ // Inherent autoload
+ //
+ RosegardenGUIDoc *newDoc = new RosegardenGUIDoc(this, m_pluginManager);
+
+ RG21Loader rg21Loader(&newDoc->getStudio());
+
+ // TODO: make RG21Loader to actually emit these signals
+ //
+ connect(&rg21Loader, SIGNAL(setProgress(int)),
+ progressDlg.progressBar(), SLOT(setValue(int)));
+
+ connect(&rg21Loader, SIGNAL(incrementProgress(int)),
+ progressDlg.progressBar(), SLOT(advance(int)));
+
+ // "your starter for 40%" - helps the "freeze" work
+ //
+ progressDlg.progressBar()->advance(40);
+
+ if (!rg21Loader.load(file, newDoc->getComposition())) {
+ CurrentProgressDialog::freeze();
+ KMessageBox::error(this,
+ i18n("Can't load Rosegarden 2.1 file. It appears to be corrupted."));
+ delete newDoc;
+ return 0;
+ }
+
+ // Set modification flag
+ //
+ newDoc->slotDocumentModified();
+
+ // Set the caption and add recent
+ //
+ newDoc->setTitle(QFileInfo(file).fileName());
+ newDoc->setAbsFilePath(QFileInfo(file).absFilePath());
+
+ return newDoc;
+
+}
+
+void
+RosegardenGUIApp::slotImportHydrogen()
+{
+ if (m_doc && !m_doc->saveIfModified())
+ return ;
+
+ KURL url = KFileDialog::getOpenURL
+ (":HYDROGEN",
+ i18n("*.h2song|Hydrogen files\n*|All files"), this,
+ i18n("Open Hydrogen File"));
+ if (url.isEmpty()) {
+ return ;
+ }
+
+ QString tmpfile;
+ KIO::NetAccess::download(url, tmpfile, this);
+ openFile(tmpfile, ImportHydrogen);
+
+ KIO::NetAccess::removeTempFile(tmpfile);
+}
+
+void RosegardenGUIApp::slotMergeHydrogen()
+{
+ KURL url = KFileDialog::getOpenURL
+ (":HYDROGEN",
+ i18n("*.h2song|Hydrogen files\n*|All files"), this,
+ i18n("Open Hydrogen File"));
+ if (url.isEmpty()) {
+ return ;
+ }
+
+ QString tmpfile;
+ KIO::NetAccess::download(url, tmpfile, this);
+ mergeFile(tmpfile, ImportHydrogen);
+
+ KIO::NetAccess::removeTempFile( tmpfile );
+}
+
+RosegardenGUIDoc*
+RosegardenGUIApp::createDocumentFromHydrogenFile(QString file)
+{
+ KStartupLogo::hideIfStillThere();
+ ProgressDialog progressDlg(
+ i18n("Importing Hydrogen file..."), 100, this);
+
+ CurrentProgressDialog::set
+ (&progressDlg);
+
+ // Inherent autoload
+ //
+ RosegardenGUIDoc *newDoc = new RosegardenGUIDoc(this, m_pluginManager);
+
+ HydrogenLoader hydrogenLoader(&newDoc->getStudio());
+
+ // TODO: make RG21Loader to actually emit these signals
+ //
+ connect(&hydrogenLoader, SIGNAL(setProgress(int)),
+ progressDlg.progressBar(), SLOT(setValue(int)));
+
+ connect(&hydrogenLoader, SIGNAL(incrementProgress(int)),
+ progressDlg.progressBar(), SLOT(advance(int)));
+
+ // "your starter for 40%" - helps the "freeze" work
+ //
+ progressDlg.progressBar()->advance(40);
+
+ if (!hydrogenLoader.load(file, newDoc->getComposition())) {
+ CurrentProgressDialog::freeze();
+ KMessageBox::error(this,
+ i18n("Can't load Hydrogen file. It appears to be corrupted."));
+ delete newDoc;
+ return 0;
+ }
+
+ // Set modification flag
+ //
+ newDoc->slotDocumentModified();
+
+ // Set the caption and add recent
+ //
+ newDoc->setTitle(QFileInfo(file).fileName());
+ newDoc->setAbsFilePath(QFileInfo(file).absFilePath());
+
+ return newDoc;
+
+}
+
+void
+RosegardenGUIApp::mergeFile(QString filePath, ImportType type)
+{
+ RosegardenGUIDoc *doc = createDocument(filePath, type);
+
+ if (doc) {
+ if (m_doc) {
+
+ bool timingsDiffer = false;
+ Composition &c1 = m_doc->getComposition();
+ Composition &c2 = doc->getComposition();
+
+ // compare tempos and time sigs in the two -- rather laborious
+
+ if (c1.getTimeSignatureCount() != c2.getTimeSignatureCount()) {
+ timingsDiffer = true;
+ } else {
+ for (int i = 0; i < c1.getTimeSignatureCount(); ++i) {
+ std::pair<timeT, TimeSignature> t1 =
+ c1.getTimeSignatureChange(i);
+ std::pair<timeT, TimeSignature> t2 =
+ c2.getTimeSignatureChange(i);
+ if (t1.first != t2.first || t1.second != t2.second) {
+ timingsDiffer = true;
+ break;
+ }
+ }
+ }
+
+ if (c1.getTempoChangeCount() != c2.getTempoChangeCount()) {
+ timingsDiffer = true;
+ } else {
+ for (int i = 0; i < c1.getTempoChangeCount(); ++i) {
+ std::pair<timeT, tempoT> t1 = c1.getTempoChange(i);
+ std::pair<timeT, tempoT> t2 = c2.getTempoChange(i);
+ if (t1.first != t2.first || t1.second != t2.second) {
+ timingsDiffer = true;
+ break;
+ }
+ }
+ }
+
+ FileMergeDialog dialog(this, filePath, timingsDiffer);
+ if (dialog.exec() == QDialog::Accepted) {
+ m_doc->mergeDocument(doc, dialog.getMergeOptions());
+ }
+
+ delete doc;
+
+ } else {
+ setDocument(doc);
+ }
+ }
+}
+
+void
+RosegardenGUIApp::slotUpdatePlaybackPosition()
+{
+ static int callbackCount = 0;
+
+ // Either sequencer mappper or the sequence manager could be missing at
+ // this point.
+ //
+ if (!m_seqManager || !m_seqManager->getSequencerMapper())
+ return ;
+
+ SequencerMapper *mapper = m_seqManager->getSequencerMapper();
+
+ MappedEvent ev;
+ bool haveEvent = mapper->getVisual(ev);
+ if (haveEvent)
+ getTransport()->setMidiOutLabel(&ev);
+
+ RealTime position = mapper->getPositionPointer();
+
+ // std::cerr << "RosegardenGUIApp::slotUpdatePlaybackPosition: mapper pos = " << position << std::endl;
+
+ Composition &comp = m_doc->getComposition();
+ timeT elapsedTime = comp.getElapsedTimeForRealTime(position);
+
+ // std::cerr << "RosegardenGUIApp::slotUpdatePlaybackPosition: mapper timeT = " << elapsedTime << std::endl;
+
+ if (m_seqManager->getTransportStatus() == RECORDING) {
+
+ MappedComposition mC;
+ if (mapper->getRecordedEvents(mC) > 0) {
+ m_seqManager->processAsynchronousMidi(mC, 0);
+ m_doc->insertRecordedMidi(mC);
+ }
+
+ m_doc->updateRecordingMIDISegment();
+ m_doc->updateRecordingAudioSegments();
+ }
+
+ m_originatingJump = true;
+ m_doc->slotSetPointerPosition(elapsedTime);
+ m_originatingJump = false;
+
+ if (m_audioMixer && m_audioMixer->isVisible())
+ m_audioMixer->updateMeters(mapper);
+
+ if (m_midiMixer && m_midiMixer->isVisible())
+ m_midiMixer->updateMeters(mapper);
+
+ m_view->updateMeters(mapper);
+
+ if (++callbackCount == 60) {
+ slotUpdateCPUMeter(true);
+ callbackCount = 0;
+ }
+
+ // if (elapsedTime >= comp.getEndMarker())
+ // slotStop();
+}
+
+void
+RosegardenGUIApp::slotUpdateCPUMeter(bool playing)
+{
+ static std::ifstream *statstream = 0;
+ static bool modified = false;
+ static unsigned long lastBusy = 0, lastIdle = 0;
+
+ if (playing) {
+
+ if (!statstream) {
+ statstream = new std::ifstream("/proc/stat", std::ios::in);
+ }
+
+ if (!statstream || !*statstream)
+ return ;
+ statstream->seekg(0, std::ios::beg);
+
+ std::string cpu;
+ unsigned long user, nice, sys, idle;
+ *statstream >> cpu;
+ *statstream >> user;
+ *statstream >> nice;
+ *statstream >> sys;
+ *statstream >> idle;
+
+ unsigned long busy = user + nice + sys;
+ unsigned long count = 0;
+
+ if (lastBusy > 0) {
+ unsigned long bd = busy - lastBusy;
+ unsigned long id = idle - lastIdle;
+ if (bd + id > 0)
+ count = bd * 100 / (bd + id);
+ if (count > 100)
+ count = 100;
+ }
+
+ lastBusy = busy;
+ lastIdle = idle;
+
+ if (m_progressBar) {
+ if (!modified) {
+ m_progressBar->setTextEnabled(true);
+ m_progressBar->setFormat("CPU");
+ }
+ m_progressBar->setProgress(count);
+ }
+
+ modified = true;
+
+ } else if (modified) {
+ if (m_progressBar) {
+ m_progressBar->setTextEnabled(false);
+ m_progressBar->setFormat("%p%");
+ m_progressBar->setProgress(0);
+ }
+ modified = false;
+ }
+}
+
+void
+RosegardenGUIApp::slotUpdateMonitoring()
+{
+ // Either sequencer mappper or the sequence manager could be missing at
+ // this point.
+ //
+ if (!m_seqManager || !m_seqManager->getSequencerMapper())
+ return ;
+
+ SequencerMapper *mapper = m_seqManager->getSequencerMapper();
+
+ if (m_audioMixer && m_audioMixer->isVisible())
+ m_audioMixer->updateMonitorMeters(mapper);
+
+ if (m_midiMixer && m_midiMixer->isVisible())
+ m_midiMixer->updateMonitorMeter(mapper);
+
+ m_view->updateMonitorMeters(mapper);
+
+ slotUpdateCPUMeter(false);
+}
+
+void RosegardenGUIApp::slotSetPointerPosition(timeT t)
+{
+ Composition &comp = m_doc->getComposition();
+
+ // std::cerr << "RosegardenGUIApp::slotSetPointerPosition: t = " << t << std::endl;
+
+ if (m_seqManager) {
+ if ( m_seqManager->getTransportStatus() == PLAYING ||
+ m_seqManager->getTransportStatus() == RECORDING ) {
+ if (t > comp.getEndMarker()) {
+ if (m_seqManager->getTransportStatus() == PLAYING) {
+
+ slotStop();
+ t = comp.getEndMarker();
+ m_doc->slotSetPointerPosition(t); //causes this method to be re-invoked
+ return ;
+
+ } else { // if recording, increase composition duration
+ std::pair<timeT, timeT> timeRange = comp.getBarRangeForTime(t);
+ timeT barDuration = timeRange.second - timeRange.first;
+ timeT newEndMarker = t + 10 * barDuration;
+ comp.setEndMarker(newEndMarker);
+ getView()->getTrackEditor()->slotReadjustCanvasSize();
+ getView()->getTrackEditor()->updateRulers();
+ }
+ }
+ }
+
+ // cc 20050520 - jump at the sequencer even if we're not playing,
+ // because we might be a transport master of some kind
+ try {
+ if (!m_originatingJump) {
+ m_seqManager->sendSequencerJump(comp.getElapsedRealTime(t));
+ }
+ } catch (QString s) {
+ KMessageBox::error(this, s);
+ }
+ }
+
+ // set the time sig
+ getTransport()->setTimeSignature(comp.getTimeSignatureAt(t));
+
+ // and the tempo
+ getTransport()->setTempo(comp.getTempoAtTime(t));
+
+ // and the time
+ //
+ TransportDialog::TimeDisplayMode mode =
+ getTransport()->getCurrentMode();
+
+ if (mode == TransportDialog::BarMode ||
+ mode == TransportDialog::BarMetronomeMode) {
+
+ slotDisplayBarTime(t);
+
+ } else {
+
+ RealTime rT(comp.getElapsedRealTime(t));
+
+ if (getTransport()->isShowingTimeToEnd()) {
+ rT = rT - comp.getElapsedRealTime(comp.getDuration());
+ }
+
+ if (mode == TransportDialog::RealMode) {
+
+ getTransport()->displayRealTime(rT);
+
+ } else if (mode == TransportDialog::SMPTEMode) {
+
+ getTransport()->displaySMPTETime(rT);
+
+ } else {
+
+ getTransport()->displayFrameTime(rT);
+ }
+ }
+
+ // handle transport mode configuration changes
+ std::string modeAsString = getTransport()->getCurrentModeAsString();
+
+ if (m_doc->getConfiguration().get<String>
+ (DocumentConfiguration::TransportMode) != modeAsString) {
+
+ m_doc->getConfiguration().set<String>
+ (DocumentConfiguration::TransportMode, modeAsString);
+
+ //m_doc->slotDocumentModified(); to avoid being prompted for a file change when merely changing the transport display
+ }
+
+ // Update position on the marker editor if it's available
+ //
+ if (m_markerEditor)
+ m_markerEditor->updatePosition();
+}
+
+void RosegardenGUIApp::slotDisplayBarTime(timeT t)
+{
+ Composition &comp = m_doc->getComposition();
+
+ int barNo = comp.getBarNumber(t);
+ timeT barStart = comp.getBarStart(barNo);
+
+ TimeSignature timeSig = comp.getTimeSignatureAt(t);
+ timeT beatDuration = timeSig.getBeatDuration();
+
+ int beatNo = (t - barStart) / beatDuration;
+ int unitNo = (t - barStart) - (beatNo * beatDuration);
+
+ if (getTransport()->isShowingTimeToEnd()) {
+ barNo = barNo + 1 - comp.getNbBars();
+ beatNo = timeSig.getBeatsPerBar() - 1 - beatNo;
+ unitNo = timeSig.getBeatDuration() - 1 - unitNo;
+ } else {
+ // convert to 1-based display bar numbers
+ barNo += 1;
+ beatNo += 1;
+ }
+
+ // show units in hemidemis (or whatever), not in raw time ticks
+ unitNo /= Note(Note::Shortest).getDuration();
+
+ getTransport()->displayBarTime(barNo, beatNo, unitNo);
+}
+
+void RosegardenGUIApp::slotRefreshTimeDisplay()
+{
+ if ( m_seqManager->getTransportStatus() == PLAYING ||
+ m_seqManager->getTransportStatus() == RECORDING ) {
+ return ; // it'll be refreshed in a moment anyway
+ }
+ slotSetPointerPosition(m_doc->getComposition().getPosition());
+}
+
+bool
+RosegardenGUIApp::isTrackEditorPlayTracking() const
+{
+ return m_view->getTrackEditor()->isTracking();
+}
+
+void RosegardenGUIApp::slotToggleTracking()
+{
+ m_view->getTrackEditor()->slotToggleTracking();
+}
+
+void RosegardenGUIApp::slotTestStartupTester()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotTestStartupTester" << endl;
+
+ if (!m_startupTester) {
+ m_startupTester = new StartupTester();
+ connect(m_startupTester, SIGNAL(newerVersionAvailable(QString)),
+ this, SLOT(slotNewerVersionAvailable(QString)));
+ m_startupTester->start();
+ QTimer::singleShot(100, this, SLOT(slotTestStartupTester()));
+ return ;
+ }
+
+ if (!m_startupTester->isReady()) {
+ QTimer::singleShot(100, this, SLOT(slotTestStartupTester()));
+ return ;
+ }
+
+ QStringList missingFeatures;
+ QStringList allMissing;
+
+ QStringList missing;
+ bool have = m_startupTester->haveProjectPackager(&missing);
+
+ stateChanged("have_project_packager",
+ have ?
+ KXMLGUIClient::StateNoReverse : KXMLGUIClient::StateReverse);
+
+ if (!have) {
+ missingFeatures.push_back(i18n("Export and import of Rosegarden Project files"));
+ if (missing.count() == 0) {
+ allMissing.push_back(i18n("The Rosegarden Project Packager helper script"));
+ } else {
+ for (int i = 0; i < missing.count(); ++i) {
+// if (missingFeatures.count() > 1) {
+ allMissing.push_back(i18n("%1 - for project file support").arg(missing[i]));
+// } else {
+// allMissing.push_back(missing[i]);
+// }
+ }
+ }
+ }
+
+ have = m_startupTester->haveLilyPondView(&missing);
+
+ stateChanged("have_lilypondview",
+ have ?
+ KXMLGUIClient::StateNoReverse : KXMLGUIClient::StateReverse);
+
+ if (!have) {
+ missingFeatures.push_back("Notation previews through LilyPond");
+ if (missing.count() == 0) {
+ allMissing.push_back(i18n("The Rosegarden LilyPondView helper script"));
+ } else {
+ for (int i = 0; i < missing.count(); ++i) {
+ if (missingFeatures.count() > 1) {
+ allMissing.push_back(i18n("%1 - for LilyPond preview support").arg(missing[i]));
+ } else {
+ allMissing.push_back(missing[i]);
+ }
+ }
+ }
+ }
+
+#ifdef HAVE_LIBJACK
+ if (m_seqManager && (m_seqManager->getSoundDriverStatus() & AUDIO_OK)) {
+
+ m_haveAudioImporter = m_startupTester->haveAudioFileImporter(&missing);
+
+ if (!m_haveAudioImporter) {
+ missingFeatures.push_back("General audio file import and conversion");
+ if (missing.count() == 0) {
+ allMissing.push_back(i18n("The Rosegarden Audio File Importer helper script"));
+ } else {
+ for (int i = 0; i < missing.count(); ++i) {
+ if (missingFeatures.count() > 1) {
+ allMissing.push_back(i18n("%1 - for audio file import").arg(missing[i]));
+ } else {
+ allMissing.push_back(missing[i]);
+ }
+ }
+ }
+ }
+ }
+#endif
+
+ if (missingFeatures.count() > 0) {
+ QString message = i18n("<h3>Helper programs not found</h3><p>Rosegarden could not find one or more helper programs which it needs to provide some features. The following features will not be available:</p>");
+ message += i18n("<ul>");
+ for (int i = 0; i < missingFeatures.count(); ++i) {
+ message += i18n("<li>%1</li>").arg(missingFeatures[i]);
+ }
+ message += i18n("</ul>");
+ message += i18n("<p>To fix this, you should install the following additional programs:</p>");
+ message += i18n("<ul>");
+ for (int i = 0; i < allMissing.count(); ++i) {
+ message += i18n("<li>%1</li>").arg(allMissing[i]);
+ }
+ message += i18n("</ul>");
+
+ awaitDialogClearance();
+
+ KMessageBox::information
+ (m_view,
+ message,
+ i18n("Helper programs not found"),
+ "startup-helpers-missing");
+ }
+
+ delete m_startupTester;
+ m_startupTester = 0;
+}
+
+void RosegardenGUIApp::slotDebugDump()
+{
+ Composition &comp = m_doc->getComposition();
+ comp.dump(std::cerr);
+}
+
+bool RosegardenGUIApp::launchSequencer(bool useExisting)
+{
+ if (!isUsingSequencer()) {
+ RG_DEBUG << "RosegardenGUIApp::launchSequencer() - not using seq. - returning\n";
+ return false; // no need to launch anything
+ }
+
+ if (isSequencerRunning()) {
+ RG_DEBUG << "RosegardenGUIApp::launchSequencer() - sequencer already running - returning\n";
+ if (m_seqManager) m_seqManager->checkSoundDriverStatus(false);
+ return true;
+ }
+
+ // Check to see if we're clearing down sequencer processes -
+ // if we're not we check DCOP for an existing sequencer and
+ // try to talk to use that (that's the "developer" mode).
+ //
+ // User mode should clear down sequencer processes.
+ //
+ if (kapp->dcopClient()->isApplicationRegistered(
+ QCString(ROSEGARDEN_SEQUENCER_APP_NAME))) {
+ RG_DEBUG << "RosegardenGUIApp::launchSequencer() - "
+ << "existing DCOP registered sequencer found\n";
+
+ if (useExisting) {
+ if (m_seqManager) m_seqManager->checkSoundDriverStatus(false);
+ m_sequencerProcess = (KProcess*)SequencerExternal;
+ return true;
+ }
+
+ KProcess *proc = new KProcess;
+ *proc << "/usr/bin/killall";
+ *proc << "rosegardensequencer";
+ *proc << "lt-rosegardensequencer";
+
+ proc->start(KProcess::Block, KProcess::All);
+
+ if (!proc->normalExit() || proc->exitStatus()) {
+ RG_DEBUG << "couldn't kill any sequencer processes" << endl;
+ }
+ delete proc;
+
+ sleep(1);
+
+ if (kapp->dcopClient()->isApplicationRegistered(
+ QCString(ROSEGARDEN_SEQUENCER_APP_NAME))) {
+ RG_DEBUG << "RosegardenGUIApp::launchSequencer() - "
+ << "failed to kill existing sequencer\n";
+
+ KProcess *proc = new KProcess;
+ *proc << "/usr/bin/killall";
+ *proc << "-9";
+ *proc << "rosegardensequencer";
+ *proc << "lt-rosegardensequencer";
+
+ proc->start(KProcess::Block, KProcess::All);
+
+ if (proc->exitStatus()) {
+ RG_DEBUG << "couldn't kill any sequencer processes" << endl;
+ }
+ delete proc;
+
+ sleep(1);
+ }
+ }
+
+ //
+ // No sequencer is running, so start one
+ //
+ KTmpStatusMsg msg(i18n("Starting the sequencer..."), this);
+
+ if (!m_sequencerProcess) {
+ m_sequencerProcess = new KProcess;
+
+ (*m_sequencerProcess) << "rosegardensequencer";
+
+ // Command line arguments
+ //
+ KConfig *config = kapp->config();
+ config->setGroup(SequencerOptionsConfigGroup);
+ QString options = config->readEntry("commandlineoptions");
+ if (!options.isEmpty()) {
+ (*m_sequencerProcess) << options;
+ RG_DEBUG << "sequencer options \"" << options << "\"" << endl;
+ }
+
+ } else {
+ RG_DEBUG << "RosegardenGUIApp::launchSequencer() - sequencer KProcess already created\n";
+ m_sequencerProcess->disconnect(); // disconnect processExit signal
+ // it will be reconnected later on
+ }
+
+ bool res = m_sequencerProcess->start();
+
+ if (!res) {
+ KMessageBox::error(0, i18n("Couldn't start the sequencer"));
+ RG_DEBUG << "Couldn't start the sequencer\n";
+ m_sequencerProcess = 0;
+ // If starting it didn't even work, fall back to no sequencer mode
+ m_useSequencer = false;
+ } else {
+ // connect processExited only after start, otherwise
+ // a failed startup will call slotSequencerExited()
+ // right away and we don't get to check the result
+ // of m_sequencerProcess->start() and thus make the distinction
+ // between the case where the sequencer was successfully launched
+ // but crashed right away, or the case where the process couldn't
+ // be launched at all (missing executable, etc...)
+ //
+ // We also re-check that the process is still running at this
+ // point in case it crashed between the moment we check res above
+ // and now.
+ //
+ //usleep(1000 * 1000); // even wait half a sec. to make sure it's actually running
+ if (m_sequencerProcess->isRunning()) {
+
+ try {
+ // if (m_seqManager) {
+ // RG_DEBUG << "RosegardenGUIApp::launchSequencer : checking sound driver status\n";
+ // m_seqManager->checkSoundDriverStatus();
+ // }
+
+ stateChanged("sequencer_running");
+ slotEnableTransport(true);
+
+ connect(m_sequencerProcess, SIGNAL(processExited(KProcess*)),
+ this, SLOT(slotSequencerExited(KProcess*)));
+
+ } catch (Exception e) {
+ m_sequencerProcess = 0;
+ m_useSequencer = false;
+ stateChanged("sequencer_running", KXMLGUIClient::StateReverse);
+ slotEnableTransport(false);
+ }
+
+ } else { // if it crashed so fast, it's probably pointless
+ // to try restarting it later, so also fall back to no
+ // sequencer mode
+ m_sequencerProcess = 0;
+ m_useSequencer = false;
+ stateChanged("sequencer_running", KXMLGUIClient::StateReverse);
+ slotEnableTransport(false);
+ }
+
+ }
+
+ // Sync current devices with the sequencer
+ //
+ if (m_doc)
+ m_doc->syncDevices();
+
+ if (m_doc && m_doc->getStudio().haveMidiDevices()) {
+ stateChanged("got_midi_devices");
+ } else {
+ stateChanged("got_midi_devices", KXMLGUIClient::StateReverse);
+ }
+
+ return res;
+}
+
+#ifdef HAVE_LIBJACK
+bool RosegardenGUIApp::launchJack()
+{
+ KConfig* config = kapp->config();
+ config->setGroup(SequencerOptionsConfigGroup);
+
+ bool startJack = config->readBoolEntry("jackstart", false);
+ if (!startJack)
+ return true; // we don't do anything
+
+ QString jackPath = config->readEntry("jackcommand", "");
+
+ emit startupStatusMessage(i18n("Clearing down jackd..."));
+
+ KProcess *proc = new KProcess; // TODO: do it in a less clumsy way
+ *proc << "/usr/bin/killall";
+ *proc << "-9";
+ *proc << "jackd";
+
+ proc->start(KProcess::Block, KProcess::All);
+
+ if (proc->exitStatus())
+ RG_DEBUG << "couldn't kill any jackd processes" << endl;
+ else
+ RG_DEBUG << "killed old jackd processes" << endl;
+
+ emit startupStatusMessage(i18n("Starting jackd..."));
+
+ if (jackPath != "") {
+
+ RG_DEBUG << "starting jack \"" << jackPath << "\"" << endl;
+
+ QStringList splitCommand;
+ splitCommand = QStringList::split(" ", jackPath);
+
+ RG_DEBUG << "RosegardenGUIApp::launchJack() : splitCommand length : "
+ << splitCommand.size() << endl;
+
+ // start jack process
+ m_jackProcess = new KProcess;
+
+ *m_jackProcess << splitCommand;
+
+ m_jackProcess->start();
+ }
+
+
+ return m_jackProcess != 0 ? m_jackProcess->isRunning() : true;
+}
+#endif
+
+void RosegardenGUIApp::slotDocumentDevicesResyncd()
+{
+ m_sequencerCheckedIn = true;
+ m_trackParameterBox->populateDeviceLists();
+}
+
+void RosegardenGUIApp::slotSequencerExited(KProcess*)
+{
+ RG_DEBUG << "RosegardenGUIApp::slotSequencerExited Sequencer exited\n";
+
+ KStartupLogo::hideIfStillThere();
+
+ if (m_sequencerCheckedIn) {
+
+ KMessageBox::error(0, i18n("The Rosegarden sequencer process has exited unexpectedly. Sound and recording will no longer be available for this session.\nPlease exit and restart Rosegarden to restore sound capability."));
+
+ } else {
+
+ KMessageBox::error(0, i18n("The Rosegarden sequencer could not be started, so sound and recording will be unavailable for this session.\nFor assistance with correct audio and MIDI configuration, go to http://rosegardenmusic.com."));
+ }
+
+ m_sequencerProcess = 0; // isSequencerRunning() will return false
+ // but isUsingSequencer() will keep returning true
+ // so pressing the play button may attempt to restart the sequencer
+}
+
+void RosegardenGUIApp::slotExportProject()
+{
+ KTmpStatusMsg msg(i18n("Exporting Rosegarden Project file..."), this);
+
+ QString fileName = getValidWriteFile
+ ("*.rgp|" + i18n("Rosegarden Project files\n") +
+ "\n*|" + i18n("All files"),
+ i18n("Export as..."));
+
+ if (fileName.isEmpty())
+ return ;
+
+ QString rgFile = fileName;
+ rgFile.replace(QRegExp(".rg.rgp$"), ".rg");
+ rgFile.replace(QRegExp(".rgp$"), ".rg");
+
+ CurrentProgressDialog::freeze();
+
+ QString errMsg;
+ if (!m_doc->saveDocument(rgFile, errMsg,
+ true)) { // pretend it's autosave
+ KMessageBox::sorry(this, i18n("Saving Rosegarden file to package failed: %1").arg(errMsg));
+ CurrentProgressDialog::thaw();
+ return ;
+ }
+
+ KProcess *proc = new KProcess;
+ *proc << "rosegarden-project-package";
+ *proc << "--pack";
+ *proc << rgFile;
+ *proc << fileName;
+
+ proc->start(KProcess::Block, KProcess::All);
+
+ if (!proc->normalExit() || proc->exitStatus()) {
+ KMessageBox::sorry(this, i18n("Failed to export to project file \"%1\"").arg(fileName));
+ CurrentProgressDialog::thaw();
+ delete proc;
+ return ;
+ }
+
+ delete proc;
+}
+
+void RosegardenGUIApp::slotExportMIDI()
+{
+ KTmpStatusMsg msg(i18n("Exporting MIDI file..."), this);
+
+ QString fileName = getValidWriteFile
+ ("*.mid *.midi|" + i18n("Standard MIDI files\n") +
+ "\n*|" + i18n("All files"),
+ i18n("Export as..."));
+
+ if (fileName.isEmpty())
+ return ;
+
+ exportMIDIFile(fileName);
+}
+
+void RosegardenGUIApp::exportMIDIFile(QString file)
+{
+ ProgressDialog progressDlg(i18n("Exporting MIDI file..."),
+ 100,
+ this);
+
+ std::string fname(QFile::encodeName(file));
+
+ MidiFile midiFile(fname,
+ &m_doc->getStudio());
+
+ connect(&midiFile, SIGNAL(setProgress(int)),
+ progressDlg.progressBar(), SLOT(setValue(int)));
+
+ connect(&midiFile, SIGNAL(incrementProgress(int)),
+ progressDlg.progressBar(), SLOT(advance(int)));
+
+ midiFile.convertToMidi(m_doc->getComposition());
+
+ if (!midiFile.write()) {
+ CurrentProgressDialog::freeze();
+ KMessageBox::sorry(this, i18n("Export failed. The file could not be opened for writing."));
+ }
+}
+
+void RosegardenGUIApp::slotExportCsound()
+{
+ KTmpStatusMsg msg(i18n("Exporting Csound score file..."), this);
+
+ QString fileName = getValidWriteFile(QString("*|") + i18n("All files"),
+ i18n("Export as..."));
+ if (fileName.isEmpty())
+ return ;
+
+ exportCsoundFile(fileName);
+}
+
+void RosegardenGUIApp::exportCsoundFile(QString file)
+{
+ ProgressDialog progressDlg(i18n("Exporting Csound score file..."),
+ 100,
+ this);
+
+ CsoundExporter e(this, &m_doc->getComposition(), std::string(QFile::encodeName(file)));
+
+ connect(&e, SIGNAL(setProgress(int)),
+ progressDlg.progressBar(), SLOT(setValue(int)));
+
+ connect(&e, SIGNAL(incrementProgress(int)),
+ progressDlg.progressBar(), SLOT(advance(int)));
+
+ if (!e.write()) {
+ CurrentProgressDialog::freeze();
+ KMessageBox::sorry(this, i18n("Export failed. The file could not be opened for writing."));
+ }
+}
+
+void RosegardenGUIApp::slotExportMup()
+{
+ KTmpStatusMsg msg(i18n("Exporting Mup file..."), this);
+
+ QString fileName = getValidWriteFile
+ ("*.mup|" + i18n("Mup files\n") + "\n*|" + i18n("All files"),
+ i18n("Export as..."));
+ if (fileName.isEmpty())
+ return ;
+
+ exportMupFile(fileName);
+}
+
+void RosegardenGUIApp::exportMupFile(QString file)
+{
+ ProgressDialog progressDlg(i18n("Exporting Mup file..."),
+ 100,
+ this);
+
+ MupExporter e(this, &m_doc->getComposition(), std::string(QFile::encodeName(file)));
+
+ connect(&e, SIGNAL(setProgress(int)),
+ progressDlg.progressBar(), SLOT(setValue(int)));
+
+ connect(&e, SIGNAL(incrementProgress(int)),
+ progressDlg.progressBar(), SLOT(advance(int)));
+
+ if (!e.write()) {
+ CurrentProgressDialog::freeze();
+ KMessageBox::sorry(this, i18n("Export failed. The file could not be opened for writing."));
+ }
+}
+
+void RosegardenGUIApp::slotExportLilyPond()
+{
+ KTmpStatusMsg msg(i18n("Exporting LilyPond file..."), this);
+
+ QString fileName = getValidWriteFile
+ (QString("*.ly|") + i18n("LilyPond files") +
+ "\n*|" + i18n("All files"),
+ i18n("Export as..."));
+
+ if (fileName.isEmpty())
+ return ;
+
+ exportLilyPondFile(fileName);
+}
+
+std::map<KProcess *, KTempFile *> RosegardenGUIApp::m_lilyTempFileMap;
+
+
+void RosegardenGUIApp::slotPrintLilyPond()
+{
+ KTmpStatusMsg msg(i18n("Printing LilyPond file..."), this);
+ KTempFile *file = new KTempFile(QString::null, ".ly");
+ file->setAutoDelete(true);
+ if (!file->name()) {
+ CurrentProgressDialog::freeze();
+ KMessageBox::sorry(this, i18n("Failed to open a temporary file for LilyPond export."));
+ delete file;
+ }
+ if (!exportLilyPondFile(file->name(), true)) {
+ return ;
+ }
+ KProcess *proc = new KProcess;
+ *proc << "rosegarden-lilypondview";
+ *proc << "--graphical";
+ *proc << "--print";
+ *proc << file->name();
+ connect(proc, SIGNAL(processExited(KProcess *)),
+ this, SLOT(slotLilyPondViewProcessExited(KProcess *)));
+ m_lilyTempFileMap[proc] = file;
+ proc->start(KProcess::NotifyOnExit);
+}
+
+void RosegardenGUIApp::slotPreviewLilyPond()
+{
+ KTmpStatusMsg msg(i18n("Previewing LilyPond file..."), this);
+ KTempFile *file = new KTempFile(QString::null, ".ly");
+ file->setAutoDelete(true);
+ if (!file->name()) {
+ CurrentProgressDialog::freeze();
+ KMessageBox::sorry(this, i18n("Failed to open a temporary file for LilyPond export."));
+ delete file;
+ }
+ if (!exportLilyPondFile(file->name(), true)) {
+ return ;
+ }
+ KProcess *proc = new KProcess;
+ *proc << "rosegarden-lilypondview";
+ *proc << "--graphical";
+ *proc << "--pdf";
+ *proc << file->name();
+ connect(proc, SIGNAL(processExited(KProcess *)),
+ this, SLOT(slotLilyPondViewProcessExited(KProcess *)));
+ m_lilyTempFileMap[proc] = file;
+ proc->start(KProcess::NotifyOnExit);
+}
+
+void RosegardenGUIApp::slotLilyPondViewProcessExited(KProcess *p)
+{
+ delete m_lilyTempFileMap[p];
+ m_lilyTempFileMap.erase(p);
+ delete p;
+}
+
+bool RosegardenGUIApp::exportLilyPondFile(QString file, bool forPreview)
+{
+ QString caption = "", heading = "";
+ if (forPreview) {
+ caption = i18n("LilyPond Preview Options");
+ heading = i18n("LilyPond preview options");
+ }
+
+ LilyPondOptionsDialog dialog(this, m_doc, caption, heading);
+ if (dialog.exec() != QDialog::Accepted) {
+ return false;
+ }
+
+ ProgressDialog progressDlg(i18n("Exporting LilyPond file..."),
+ 100,
+ this);
+
+ LilyPondExporter e(this, m_doc, std::string(QFile::encodeName(file)));
+
+ connect(&e, SIGNAL(setProgress(int)),
+ progressDlg.progressBar(), SLOT(setValue(int)));
+
+ connect(&e, SIGNAL(incrementProgress(int)),
+ progressDlg.progressBar(), SLOT(advance(int)));
+
+ if (!e.write()) {
+ CurrentProgressDialog::freeze();
+ KMessageBox::sorry(this, i18n("Export failed. The file could not be opened for writing."));
+ return false;
+ }
+
+ return true;
+}
+
+void RosegardenGUIApp::slotExportMusicXml()
+{
+ KTmpStatusMsg msg(i18n("Exporting MusicXML file..."), this);
+
+ QString fileName = getValidWriteFile
+ (QString("*.xml|") + i18n("XML files") +
+ "\n*|" + i18n("All files"), i18n("Export as..."));
+
+ if (fileName.isEmpty())
+ return ;
+
+ exportMusicXmlFile(fileName);
+}
+
+void RosegardenGUIApp::exportMusicXmlFile(QString file)
+{
+ ProgressDialog progressDlg(i18n("Exporting MusicXML file..."),
+ 100,
+ this);
+
+ MusicXmlExporter e(this, m_doc, std::string(QFile::encodeName(file)));
+
+ connect(&e, SIGNAL(setProgress(int)),
+ progressDlg.progressBar(), SLOT(setValue(int)));
+
+ connect(&e, SIGNAL(incrementProgress(int)),
+ progressDlg.progressBar(), SLOT(advance(int)));
+
+ if (!e.write()) {
+ CurrentProgressDialog::freeze();
+ KMessageBox::sorry(this, i18n("Export failed. The file could not be opened for writing."));
+ }
+}
+
+void
+RosegardenGUIApp::slotCloseTransport()
+{
+ m_viewTransport->setChecked(false);
+ slotToggleTransport(); // hides the transport
+}
+
+void
+RosegardenGUIApp::slotDeleteTransport()
+{
+ delete m_transport;
+ m_transport = 0;
+}
+
+void
+RosegardenGUIApp::slotActivateTool(QString toolName)
+{
+ if (toolName == SegmentSelector::ToolName) {
+ actionCollection()->action("select")->activate();
+ }
+}
+
+void
+RosegardenGUIApp::slotToggleMetronome()
+{
+ Composition &comp = m_doc->getComposition();
+
+ if (m_seqManager->getTransportStatus() == STARTING_TO_RECORD ||
+ m_seqManager->getTransportStatus() == RECORDING ||
+ m_seqManager->getTransportStatus() == RECORDING_ARMED) {
+ if (comp.useRecordMetronome())
+ comp.setRecordMetronome(false);
+ else
+ comp.setRecordMetronome(true);
+
+ getTransport()->MetronomeButton()->setOn(comp.useRecordMetronome());
+ } else {
+ if (comp.usePlayMetronome())
+ comp.setPlayMetronome(false);
+ else
+ comp.setPlayMetronome(true);
+
+ getTransport()->MetronomeButton()->setOn(comp.usePlayMetronome());
+ }
+}
+
+void
+RosegardenGUIApp::slotRewindToBeginning()
+{
+ // ignore requests if recording
+ //
+ if (m_seqManager->getTransportStatus() == RECORDING)
+ return ;
+
+ m_seqManager->rewindToBeginning();
+}
+
+void
+RosegardenGUIApp::slotFastForwardToEnd()
+{
+ // ignore requests if recording
+ //
+ if (m_seqManager->getTransportStatus() == RECORDING)
+ return ;
+
+ m_seqManager->fastForwardToEnd();
+}
+
+void
+RosegardenGUIApp::slotSetPlayPosition(timeT time)
+{
+ RG_DEBUG << "RosegardenGUIApp::slotSetPlayPosition(" << time << ")" << endl;
+ if (m_seqManager->getTransportStatus() == RECORDING)
+ return ;
+
+ m_doc->slotSetPointerPosition(time);
+
+ if (m_seqManager->getTransportStatus() == PLAYING)
+ return ;
+
+ slotPlay();
+}
+
+void RosegardenGUIApp::notifySequencerStatus(int status)
+{
+ stateChanged("not_playing",
+ (status == PLAYING ||
+ status == RECORDING) ?
+ KXMLGUIClient::StateReverse : KXMLGUIClient::StateNoReverse);
+
+ if (m_seqManager)
+ m_seqManager->setTransportStatus((TransportStatus) status);
+}
+
+void RosegardenGUIApp::processAsynchronousMidi(const MappedComposition &mC)
+{
+ if (!m_seqManager) {
+ return ; // probably getting this from a not-yet-killed runaway sequencer
+ }
+
+ m_seqManager->processAsynchronousMidi(mC, 0);
+ SequencerMapper *mapper = m_seqManager->getSequencerMapper();
+ if (mapper)
+ m_view->updateMeters(mapper);
+}
+
+void
+RosegardenGUIApp::slotRecord()
+{
+ if (!isUsingSequencer())
+ return ;
+
+ if (!isSequencerRunning()) {
+
+ // Try to launch sequencer and return if we fail
+ //
+ if (!launchSequencer(false))
+ return ;
+ }
+
+ if (m_seqManager->getTransportStatus() == RECORDING) {
+ slotStop();
+ return ;
+ } else if (m_seqManager->getTransportStatus() == PLAYING) {
+ slotToggleRecord();
+ return ;
+ }
+
+ // Attempt to start recording
+ //
+ try {
+ m_seqManager->record(false);
+ } catch (QString s) {
+ // We should already be stopped by this point so just unset
+ // the buttons after clicking the dialog.
+ //
+ KMessageBox::error(this, s);
+
+ getTransport()->MetronomeButton()->setOn(false);
+ getTransport()->RecordButton()->setOn(false);
+ getTransport()->PlayButton()->setOn(false);
+ return ;
+ } catch (AudioFileManager::BadAudioPathException e) {
+ if (KMessageBox::warningContinueCancel
+ (this,
+ i18n("The audio file path does not exist or is not writable.\nPlease set the audio file path to a valid directory in Document Properties before recording audio.\nWould you like to set it now?"),
+ i18n("Warning"),
+ i18n("Set audio file path")) == KMessageBox::Continue) {
+ slotOpenAudioPathSettings();
+ }
+ getTransport()->MetronomeButton()->setOn(false);
+ getTransport()->RecordButton()->setOn(false);
+ getTransport()->PlayButton()->setOn(false);
+ return ;
+ } catch (Exception e) {
+ KMessageBox::error(this, strtoqstr(e.getMessage()));
+
+ getTransport()->MetronomeButton()->setOn(false);
+ getTransport()->RecordButton()->setOn(false);
+ getTransport()->PlayButton()->setOn(false);
+ return ;
+ }
+
+ // plugin the keyboard accelerators for focus on this dialog
+ plugAccelerators(m_seqManager->getCountdownDialog(),
+ m_seqManager->getCountdownDialog()->getAccelerators());
+
+ connect(m_seqManager->getCountdownDialog(), SIGNAL(stopped()),
+ this, SLOT(slotStop()));
+
+ // Start the playback timer - this fetches the current sequencer position &c
+ //
+ m_stopTimer->stop();
+ m_playTimer->start(23); // avoid multiples of 10 just so as
+ // to avoid always having the same digit
+ // in one place on the transport. How
+ // shallow.)
+}
+
+void
+RosegardenGUIApp::slotToggleRecord()
+{
+ if (!isUsingSequencer() ||
+ (!isSequencerRunning() && !launchSequencer(false)))
+ return ;
+
+ try {
+ m_seqManager->record(true);
+ } catch (QString s) {
+ KMessageBox::error(this, s);
+ } catch (AudioFileManager::BadAudioPathException e) {
+ if (KMessageBox::warningContinueCancel
+ (this,
+ i18n("The audio file path does not exist or is not writable.\nPlease set the audio file path to a valid directory in Document Properties before you start to record audio.\nWould you like to set it now?"),
+ i18n("Error"),
+ i18n("Set audio file path")) == KMessageBox::Continue) {
+ slotOpenAudioPathSettings();
+ }
+ } catch (Exception e) {
+ KMessageBox::error(this, strtoqstr(e.getMessage()));
+ }
+
+}
+
+void
+RosegardenGUIApp::slotSetLoop(timeT lhs, timeT rhs)
+{
+ try {
+ m_doc->slotDocumentModified();
+
+ m_seqManager->setLoop(lhs, rhs);
+
+ // toggle the loop button
+ if (lhs != rhs) {
+ getTransport()->LoopButton()->setOn(true);
+ stateChanged("have_range", KXMLGUIClient::StateNoReverse);
+ } else {
+ getTransport()->LoopButton()->setOn(false);
+ stateChanged("have_range", KXMLGUIClient::StateReverse);
+ }
+ } catch (QString s) {
+ KMessageBox::error(this, s);
+ }
+}
+
+void RosegardenGUIApp::alive()
+{
+ if (m_doc)
+ m_doc->syncDevices();
+
+ if (m_doc && m_doc->getStudio().haveMidiDevices()) {
+ stateChanged("got_midi_devices");
+ } else {
+ stateChanged("got_midi_devices", KXMLGUIClient::StateReverse);
+ }
+}
+
+void RosegardenGUIApp::slotPlay()
+{
+ if (!isUsingSequencer())
+ return ;
+
+ if (!isSequencerRunning()) {
+
+ // Try to launch sequencer and return if it fails
+ //
+ if (!launchSequencer(false))
+ return ;
+ }
+
+ if (!m_seqManager)
+ return ;
+
+ // If we're armed and ready to record then do this instead (calling
+ // slotRecord ensures we don't toggle the recording state in
+ // SequenceManager)
+ //
+ if (m_seqManager->getTransportStatus() == RECORDING_ARMED) {
+ slotRecord();
+ return ;
+ }
+
+ // Send the controllers at start of playback if required
+ //
+ KConfig *config = kapp->config();
+ config->setGroup(SequencerOptionsConfigGroup);
+ bool sendControllers = config->readBoolEntry("alwayssendcontrollers", false);
+
+ if (sendControllers)
+ m_doc->initialiseControllers();
+
+ bool pausedPlayback = false;
+
+ try {
+ pausedPlayback = m_seqManager->play(); // this will stop playback (pause) if it's already running
+ // Check the new state of the transport and start or stop timer
+ // accordingly
+ //
+ if (!pausedPlayback) {
+
+ // Start the playback timer - this fetches the current sequencer position &c
+ //
+ m_stopTimer->stop();
+ m_playTimer->start(23);
+ } else {
+ m_playTimer->stop();
+ m_stopTimer->start(100);
+ }
+ } catch (QString s) {
+ KMessageBox::error(this, s);
+ m_playTimer->stop();
+ m_stopTimer->start(100);
+ } catch (Exception e) {
+ KMessageBox::error(this, e.getMessage());
+ m_playTimer->stop();
+ m_stopTimer->start(100);
+ }
+
+}
+
+void RosegardenGUIApp::slotJumpToTime(int sec, int usec)
+{
+ Composition *comp = &m_doc->getComposition();
+ timeT t = comp->getElapsedTimeForRealTime
+ (RealTime(sec, usec * 1000));
+ m_doc->slotSetPointerPosition(t);
+}
+
+void RosegardenGUIApp::slotStartAtTime(int sec, int usec)
+{
+ slotJumpToTime(sec, usec);
+ slotPlay();
+}
+
+void RosegardenGUIApp::slotStop()
+{
+ if (m_seqManager &&
+ m_seqManager->getCountdownDialog()) {
+ disconnect(m_seqManager->getCountdownDialog(), SIGNAL(stopped()),
+ this, SLOT(slotStop()));
+ disconnect(m_seqManager->getCountdownDialog(), SIGNAL(completed()),
+ this, SLOT(slotStop()));
+ }
+
+ try {
+ if (m_seqManager)
+ m_seqManager->stopping();
+ } catch (Exception e) {
+ KMessageBox::error(this, strtoqstr(e.getMessage()));
+ }
+
+ // stop the playback timer
+ m_playTimer->stop();
+ m_stopTimer->start(100);
+}
+
+void RosegardenGUIApp::slotRewind()
+{
+ // ignore requests if recording
+ //
+ if (m_seqManager->getTransportStatus() == RECORDING)
+ return ;
+ if (m_seqManager)
+ m_seqManager->rewind();
+}
+
+void RosegardenGUIApp::slotFastforward()
+{
+ // ignore requests if recording
+ //
+ if (m_seqManager->getTransportStatus() == RECORDING)
+ return ;
+
+ if (m_seqManager)
+ m_seqManager->fastforward();
+}
+
+void
+RosegardenGUIApp::slotSetLoop()
+{
+ // restore loop
+ m_doc->setLoop(m_storedLoopStart, m_storedLoopEnd);
+}
+
+void
+RosegardenGUIApp::slotUnsetLoop()
+{
+ Composition &comp = m_doc->getComposition();
+
+ // store the loop
+ m_storedLoopStart = comp.getLoopStart();
+ m_storedLoopEnd = comp.getLoopEnd();
+
+ // clear the loop at the composition and propagate to the rest
+ // of the display items
+ m_doc->setLoop(0, 0);
+}
+
+void
+RosegardenGUIApp::slotSetLoopStart()
+{
+ // Check so that start time is before endtime, othervise move upp the
+ // endtime to that same pos.
+ if ( m_doc->getComposition().getPosition() < m_doc->getComposition().getLoopEnd() ) {
+ m_doc->setLoop(m_doc->getComposition().getPosition(), m_doc->getComposition().getLoopEnd());
+ } else {
+ m_doc->setLoop(m_doc->getComposition().getPosition(), m_doc->getComposition().getPosition());
+ }
+}
+
+void
+RosegardenGUIApp::slotSetLoopStop()
+{
+ // Check so that end time is after start time, othervise move upp the
+ // start time to that same pos.
+ if ( m_doc->getComposition().getLoopStart() < m_doc->getComposition().getPosition() ) {
+ m_doc->setLoop(m_doc->getComposition().getLoopStart(), m_doc->getComposition().getPosition());
+ } else {
+ m_doc->setLoop(m_doc->getComposition().getPosition(), m_doc->getComposition().getPosition());
+ }
+}
+
+void RosegardenGUIApp::slotToggleSolo(bool value)
+{
+ RG_DEBUG << "RosegardenGUIApp::slotToggleSolo value = " << value << endl;
+
+ m_doc->getComposition().setSolo(value);
+ getTransport()->SoloButton()->setOn(value);
+
+ m_doc->slotDocumentModified();
+
+ emit compositionStateUpdate();
+}
+
+void RosegardenGUIApp::slotTrackUp()
+{
+ Composition &comp = m_doc->getComposition();
+
+ TrackId tid = comp.getSelectedTrack();
+ TrackId pos = comp.getTrackById(tid)->getPosition();
+
+ // If at top already
+ if (pos == 0)
+ return ;
+
+ Track *track = comp.getTrackByPosition(pos - 1);
+
+ // If the track exists
+ if (track) {
+ comp.setSelectedTrack(track->getId());
+ m_view->slotSelectTrackSegments(comp.getSelectedTrack());
+ }
+
+}
+
+void RosegardenGUIApp::slotTrackDown()
+{
+ Composition &comp = m_doc->getComposition();
+
+ TrackId tid = comp.getSelectedTrack();
+ TrackId pos = comp.getTrackById(tid)->getPosition();
+
+ Track *track = comp.getTrackByPosition(pos + 1);
+
+ // If the track exists
+ if (track) {
+ comp.setSelectedTrack(track->getId());
+ m_view->slotSelectTrackSegments(comp.getSelectedTrack());
+ }
+
+}
+
+void RosegardenGUIApp::slotMuteAllTracks()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotMuteAllTracks" << endl;
+
+ Composition &comp = m_doc->getComposition();
+
+ Composition::trackcontainer tracks = comp.getTracks();
+ Composition::trackiterator tit;
+ for (tit = tracks.begin(); tit != tracks.end(); ++tit)
+ m_view->slotSetMute((*tit).second->getInstrument(), true);
+}
+
+void RosegardenGUIApp::slotUnmuteAllTracks()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotUnmuteAllTracks" << endl;
+
+ Composition &comp = m_doc->getComposition();
+
+ Composition::trackcontainer tracks = comp.getTracks();
+ Composition::trackiterator tit;
+ for (tit = tracks.begin(); tit != tracks.end(); ++tit)
+ m_view->slotSetMute((*tit).second->getInstrument(), false);
+}
+
+void RosegardenGUIApp::slotToggleMutedCurrentTrack()
+{
+ Composition &comp = m_doc->getComposition();
+ TrackId tid = comp.getSelectedTrack();
+ Track *track = comp.getTrackById(tid);
+ // If the track exists
+ if (track) {
+ bool isMuted = track->isMuted();
+ m_view->slotSetMuteButton(tid, !isMuted);
+ }
+}
+
+void RosegardenGUIApp::slotToggleRecordCurrentTrack()
+{
+ Composition &comp = m_doc->getComposition();
+ TrackId tid = comp.getSelectedTrack();
+ int pos = comp.getTrackPositionById(tid);
+ m_view->getTrackEditor()->getTrackButtons()->slotToggleRecordTrack(pos);
+}
+
+
+void RosegardenGUIApp::slotConfigure()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotConfigure\n";
+
+ ConfigureDialog *configDlg =
+ new ConfigureDialog(m_doc, kapp->config(), this);
+
+ connect(configDlg, SIGNAL(updateAutoSaveInterval(unsigned int)),
+ this, SLOT(slotUpdateAutoSaveInterval(unsigned int)));
+ connect(configDlg, SIGNAL(updateSidebarStyle(unsigned int)),
+ this, SLOT(slotUpdateSidebarStyle(unsigned int)));
+
+ configDlg->show();
+}
+
+void RosegardenGUIApp::slotEditDocumentProperties()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotEditDocumentProperties\n";
+
+ DocumentConfigureDialog *configDlg =
+ new DocumentConfigureDialog(m_doc, this);
+
+ configDlg->show();
+}
+
+void RosegardenGUIApp::slotOpenAudioPathSettings()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotOpenAudioPathSettings\n";
+
+ DocumentConfigureDialog *configDlg =
+ new DocumentConfigureDialog(m_doc, this);
+
+ configDlg->showAudioPage();
+ configDlg->show();
+}
+
+void RosegardenGUIApp::slotEditKeys()
+{
+ KKeyDialog::configure(actionCollection());
+}
+
+void RosegardenGUIApp::slotEditToolbars()
+{
+ KEditToolbar dlg(actionCollection(), "rosegardenui.rc");
+
+ connect(&dlg, SIGNAL(newToolbarConfig()),
+ SLOT(slotUpdateToolbars()));
+
+ dlg.exec();
+}
+
+void RosegardenGUIApp::slotUpdateToolbars()
+{
+ createGUI("rosegardenui.rc");
+ m_viewToolBar->setChecked(!toolBar()->isHidden());
+}
+
+void RosegardenGUIApp::slotEditTempo()
+{
+ slotEditTempo(this);
+}
+
+void RosegardenGUIApp::slotEditTempo(timeT atTime)
+{
+ slotEditTempo(this, atTime);
+}
+
+void RosegardenGUIApp::slotEditTempo(QWidget *parent)
+{
+ slotEditTempo(parent, m_doc->getComposition().getPosition());
+}
+
+void RosegardenGUIApp::slotEditTempo(QWidget *parent, timeT atTime)
+{
+ RG_DEBUG << "RosegardenGUIApp::slotEditTempo\n";
+
+ TempoDialog tempoDialog(parent, m_doc);
+
+ connect(&tempoDialog,
+ SIGNAL(changeTempo(timeT,
+ tempoT,
+ tempoT,
+ TempoDialog::TempoDialogAction)),
+ SLOT(slotChangeTempo(timeT,
+ tempoT,
+ tempoT,
+ TempoDialog::TempoDialogAction)));
+
+ tempoDialog.setTempoPosition(atTime);
+ tempoDialog.exec();
+}
+
+void RosegardenGUIApp::slotEditTimeSignature()
+{
+ slotEditTimeSignature(this);
+}
+
+void RosegardenGUIApp::slotEditTimeSignature(timeT atTime)
+{
+ slotEditTimeSignature(this, atTime);
+}
+
+void RosegardenGUIApp::slotEditTimeSignature(QWidget *parent)
+{
+ slotEditTimeSignature(parent, m_doc->getComposition().getPosition());
+}
+
+void RosegardenGUIApp::slotEditTimeSignature(QWidget *parent,
+ timeT time)
+{
+ Composition &composition(m_doc->getComposition());
+
+ TimeSignature sig = composition.getTimeSignatureAt(time);
+
+ TimeSignatureDialog dialog(parent, &composition, time, sig);
+
+ if (dialog.exec() == QDialog::Accepted) {
+
+ time = dialog.getTime();
+
+ if (dialog.shouldNormalizeRests()) {
+ m_doc->getCommandHistory()->addCommand
+ (new AddTimeSignatureAndNormalizeCommand
+ (&composition, time, dialog.getTimeSignature()));
+ } else {
+ m_doc->getCommandHistory()->addCommand
+ (new AddTimeSignatureCommand
+ (&composition, time, dialog.getTimeSignature()));
+ }
+ }
+}
+
+void RosegardenGUIApp::slotEditTransportTime()
+{
+ slotEditTransportTime(this);
+}
+
+void RosegardenGUIApp::slotEditTransportTime(QWidget *parent)
+{
+ TimeDialog dialog(parent, i18n("Move playback pointer to time"),
+ &m_doc->getComposition(),
+ m_doc->getComposition().getPosition(),
+ true);
+ if (dialog.exec() == QDialog::Accepted) {
+ m_doc->slotSetPointerPosition(dialog.getTime());
+ }
+}
+
+void RosegardenGUIApp::slotChangeZoom(int)
+{
+ double duration44 = TimeSignature(4, 4).getBarDuration();
+ double value = double(m_zoomSlider->getCurrentSize());
+ m_zoomLabel->setText(i18n("%1%").arg(duration44 / value));
+
+ RG_DEBUG << "RosegardenGUIApp::slotChangeZoom : zoom size = "
+ << m_zoomSlider->getCurrentSize() << endl;
+
+ // initZoomToolbar sets the zoom value. With some old versions of
+ // Qt3.0, this can cause slotChangeZoom() to be called while the
+ // view hasn't been initialized yet, so we need to check it's not
+ // null
+ //
+ if (m_view)
+ m_view->setZoomSize(m_zoomSlider->getCurrentSize());
+
+ long newZoom = int(m_zoomSlider->getCurrentSize() * 1000.0);
+
+ if (m_doc->getConfiguration().get<Int>
+ (DocumentConfiguration::ZoomLevel) != newZoom) {
+
+ m_doc->getConfiguration().set<Int>
+ (DocumentConfiguration::ZoomLevel, newZoom);
+
+ m_doc->slotDocumentModified();
+ }
+}
+
+void
+RosegardenGUIApp::slotZoomIn()
+{
+ m_zoomSlider->increment();
+}
+
+void
+RosegardenGUIApp::slotZoomOut()
+{
+ m_zoomSlider->decrement();
+}
+
+void
+RosegardenGUIApp::slotChangeTempo(timeT time,
+ tempoT value,
+ tempoT target,
+ TempoDialog::TempoDialogAction action)
+{
+ //!!! handle target
+
+ Composition &comp = m_doc->getComposition();
+
+ // We define a macro command here and build up the command
+ // label as we add commands on.
+ //
+ if (action == TempoDialog::AddTempo) {
+ m_doc->getCommandHistory()->addCommand
+ (new AddTempoChangeCommand(&comp, time, value, target));
+ } else if (action == TempoDialog::ReplaceTempo) {
+ int index = comp.getTempoChangeNumberAt(time);
+
+ // if there's no previous tempo change then just set globally
+ //
+ if (index == -1) {
+ m_doc->getCommandHistory()->addCommand
+ (new AddTempoChangeCommand(&comp, 0, value, target));
+ return ;
+ }
+
+ // get time of previous tempo change
+ timeT prevTime = comp.getTempoChange(index).first;
+
+ KMacroCommand *macro =
+ new KMacroCommand(i18n("Replace Tempo Change at %1").arg(time));
+
+ macro->addCommand(new RemoveTempoChangeCommand(&comp, index));
+ macro->addCommand(new AddTempoChangeCommand(&comp, prevTime, value,
+ target));
+
+ m_doc->getCommandHistory()->addCommand(macro);
+
+ } else if (action == TempoDialog::AddTempoAtBarStart) {
+ m_doc->getCommandHistory()->addCommand(new
+ AddTempoChangeCommand(&comp, comp.getBarStartForTime(time),
+ value, target));
+ } else if (action == TempoDialog::GlobalTempo ||
+ action == TempoDialog::GlobalTempoWithDefault) {
+ KMacroCommand *macro = new KMacroCommand(i18n("Set Global Tempo"));
+
+ // Remove all tempo changes in reverse order so as the index numbers
+ // don't becoming meaningless as the command gets unwound.
+ //
+ for (int i = 0; i < comp.getTempoChangeCount(); i++)
+ macro->addCommand(new RemoveTempoChangeCommand(&comp,
+ (comp.getTempoChangeCount() - 1 - i)));
+
+ // add tempo change at time zero
+ //
+ macro->addCommand(new AddTempoChangeCommand(&comp, 0, value, target));
+
+ // are we setting default too?
+ //
+ if (action == TempoDialog::GlobalTempoWithDefault) {
+ macro->setName(i18n("Set Global and Default Tempo"));
+ macro->addCommand(new ModifyDefaultTempoCommand(&comp, value));
+ }
+
+ m_doc->getCommandHistory()->addCommand(macro);
+
+ } else {
+ RG_DEBUG << "RosegardenGUIApp::slotChangeTempo() - "
+ << "unrecognised tempo command" << endl;
+ }
+}
+
+void
+RosegardenGUIApp::slotMoveTempo(timeT oldTime,
+ timeT newTime)
+{
+ Composition &comp = m_doc->getComposition();
+ int index = comp.getTempoChangeNumberAt(oldTime);
+
+ if (index < 0)
+ return ;
+
+ KMacroCommand *macro =
+ new KMacroCommand(i18n("Move Tempo Change"));
+
+ std::pair<timeT, tempoT> tc =
+ comp.getTempoChange(index);
+ std::pair<bool, tempoT> tr =
+ comp.getTempoRamping(index, false);
+
+ macro->addCommand(new RemoveTempoChangeCommand(&comp, index));
+ macro->addCommand(new AddTempoChangeCommand(&comp,
+ newTime,
+ tc.second,
+ tr.first ? tr.second : -1));
+
+ m_doc->getCommandHistory()->addCommand(macro);
+}
+
+void
+RosegardenGUIApp::slotDeleteTempo(timeT t)
+{
+ Composition &comp = m_doc->getComposition();
+ int index = comp.getTempoChangeNumberAt(t);
+
+ if (index < 0)
+ return ;
+
+ m_doc->getCommandHistory()->addCommand(new RemoveTempoChangeCommand
+ (&comp, index));
+}
+
+void
+RosegardenGUIApp::slotAddMarker(timeT time)
+{
+ AddMarkerCommand *command =
+ new AddMarkerCommand(&m_doc->getComposition(),
+ time,
+ i18n("new marker"),
+ i18n("no description"));
+
+ m_doc->getCommandHistory()->addCommand(command);
+}
+
+void
+RosegardenGUIApp::slotDeleteMarker(int id, timeT time, QString name, QString description)
+{
+ RemoveMarkerCommand *command =
+ new RemoveMarkerCommand(&m_doc->getComposition(),
+ id,
+ time,
+ qstrtostr(name),
+ qstrtostr(description));
+
+ m_doc->getCommandHistory()->addCommand(command);
+}
+
+void
+RosegardenGUIApp::slotDocumentModified(bool m)
+{
+ RG_DEBUG << "RosegardenGUIApp::slotDocumentModified(" << m << ") - doc path = "
+ << m_doc->getAbsFilePath() << endl;
+
+ if (!m_doc->getAbsFilePath().isEmpty()) {
+ slotStateChanged("saved_file_modified", m);
+ } else {
+ slotStateChanged("new_file_modified", m);
+ }
+
+}
+
+void
+RosegardenGUIApp::slotStateChanged(QString s,
+ bool noReverse)
+{
+ // RG_DEBUG << "RosegardenGUIApp::slotStateChanged " << s << "," << noReverse << endl;
+
+ stateChanged(s, noReverse ? KXMLGUIClient::StateNoReverse : KXMLGUIClient::StateReverse);
+}
+
+void
+RosegardenGUIApp::slotTestClipboard()
+{
+ if (m_clipboard->isEmpty()) {
+ stateChanged("have_clipboard", KXMLGUIClient::StateReverse);
+ stateChanged("have_clipboard_single_segment",
+ KXMLGUIClient::StateReverse);
+ } else {
+ stateChanged("have_clipboard", KXMLGUIClient::StateNoReverse);
+ stateChanged("have_clipboard_single_segment",
+ (m_clipboard->isSingleSegment() ?
+ KXMLGUIClient::StateNoReverse :
+ KXMLGUIClient::StateReverse));
+ }
+}
+
+void
+RosegardenGUIApp::plugAccelerators(QWidget *widget, QAccel *acc)
+{
+
+ acc->connectItem(acc->insertItem(Key_Enter),
+ this,
+ SLOT(slotPlay()));
+ // Alternative shortcut for Play
+ acc->connectItem(acc->insertItem(Key_Return + CTRL),
+ this,
+ SLOT(slotPlay()));
+
+ acc->connectItem(acc->insertItem(Key_Insert),
+ this,
+ SLOT(slotStop()));
+
+ acc->connectItem(acc->insertItem(Key_PageDown),
+ this,
+ SLOT(slotFastforward()));
+
+ acc->connectItem(acc->insertItem(Key_End),
+ this,
+ SLOT(slotRewind()));
+
+ acc->connectItem(acc->insertItem(Key_Space),
+ this,
+ SLOT(slotToggleRecord()));
+
+ TransportDialog *transport =
+ dynamic_cast<TransportDialog*>(widget);
+
+ if (transport) {
+ acc->connectItem(acc->insertItem(m_jumpToQuickMarkerAction->shortcut()),
+ this,
+ SLOT(slotJumpToQuickMarker()));
+
+ acc->connectItem(acc->insertItem(m_setQuickMarkerAction->shortcut()),
+ this,
+ SLOT(slotSetQuickMarker()));
+
+ connect(transport->PlayButton(),
+ SIGNAL(clicked()),
+ this,
+ SLOT(slotPlay()));
+
+ connect(transport->StopButton(),
+ SIGNAL(clicked()),
+ this,
+ SLOT(slotStop()));
+
+ connect(transport->FfwdButton(),
+ SIGNAL(clicked()),
+ SLOT(slotFastforward()));
+
+ connect(transport->RewindButton(),
+ SIGNAL(clicked()),
+ this,
+ SLOT(slotRewind()));
+
+ connect(transport->RecordButton(),
+ SIGNAL(clicked()),
+ this,
+ SLOT(slotRecord()));
+
+ connect(transport->RewindEndButton(),
+ SIGNAL(clicked()),
+ this,
+ SLOT(slotRewindToBeginning()));
+
+ connect(transport->FfwdEndButton(),
+ SIGNAL(clicked()),
+ this,
+ SLOT(slotFastForwardToEnd()));
+
+ connect(transport->MetronomeButton(),
+ SIGNAL(clicked()),
+ this,
+ SLOT(slotToggleMetronome()));
+
+ connect(transport->SoloButton(),
+ SIGNAL(toggled(bool)),
+ this,
+ SLOT(slotToggleSolo(bool)));
+
+ connect(transport->TimeDisplayButton(),
+ SIGNAL(clicked()),
+ this,
+ SLOT(slotRefreshTimeDisplay()));
+
+ connect(transport->ToEndButton(),
+ SIGNAL(clicked()),
+ SLOT(slotRefreshTimeDisplay()));
+ }
+}
+
+void
+RosegardenGUIApp::setCursor(const QCursor& cursor)
+{
+ KDockMainWindow::setCursor(cursor);
+
+ // play it safe, so we can use this class at anytime even very early in the app init
+ if ((getView() &&
+ getView()->getTrackEditor() &&
+ getView()->getTrackEditor()->getSegmentCanvas() &&
+ getView()->getTrackEditor()->getSegmentCanvas()->viewport())) {
+
+ getView()->getTrackEditor()->getSegmentCanvas()->viewport()->setCursor(cursor);
+ }
+
+ // view, main window...
+ //
+ getView()->setCursor(cursor);
+
+ // toolbars...
+ //
+ QPtrListIterator<KToolBar> tbIter = toolBarIterator();
+ KToolBar* tb = 0;
+ while ((tb = tbIter.current()) != 0) {
+ tb->setCursor(cursor);
+ ++tbIter;
+ }
+
+ m_dockLeft->setCursor(cursor);
+}
+
+QString
+RosegardenGUIApp::createNewAudioFile()
+{
+ AudioFile *aF = 0;
+ try {
+ aF = m_doc->getAudioFileManager().createRecordingAudioFile();
+ if (!aF) {
+ // createRecordingAudioFile doesn't actually write to the disk,
+ // and in principle it shouldn't fail
+ std::cerr << "ERROR: RosegardenGUIApp::createNewAudioFile: Failed to create recording audio file" << std::endl;
+ return "";
+ } else {
+ return aF->getFilename().c_str();
+ }
+ } catch (AudioFileManager::BadAudioPathException e) {
+ delete aF;
+ std::cerr << "ERROR: RosegardenGUIApp::createNewAudioFile: Failed to create recording audio file: " << e.getMessage() << std::endl;
+ return "";
+ }
+}
+
+QValueVector<QString>
+RosegardenGUIApp::createRecordAudioFiles(const QValueVector<InstrumentId> &recordInstruments)
+{
+ QValueVector<QString> qv;
+ for (unsigned int i = 0; i < recordInstruments.size(); ++i) {
+ AudioFile *aF = 0;
+ try {
+ aF = m_doc->getAudioFileManager().createRecordingAudioFile();
+ if (aF) {
+ // createRecordingAudioFile doesn't actually write to the disk,
+ // and in principle it shouldn't fail
+ qv.push_back(aF->getFilename().c_str());
+ m_doc->addRecordAudioSegment(recordInstruments[i],
+ aF->getId());
+ } else {
+ std::cerr << "ERROR: RosegardenGUIApp::createRecordAudioFiles: Failed to create recording audio file" << std::endl;
+ return qv;
+ }
+ } catch (AudioFileManager::BadAudioPathException e) {
+ delete aF;
+ std::cerr << "ERROR: RosegardenGUIApp::createRecordAudioFiles: Failed to create recording audio file: " << e.getMessage() << std::endl;
+ return qv;
+ }
+ }
+ return qv;
+}
+
+QString
+RosegardenGUIApp::getAudioFilePath()
+{
+ return QString(m_doc->getAudioFileManager().getAudioPath().c_str());
+}
+
+QValueVector<InstrumentId>
+RosegardenGUIApp::getArmedInstruments()
+{
+ std::set
+ <InstrumentId> iid;
+
+ const Composition::recordtrackcontainer &tr =
+ m_doc->getComposition().getRecordTracks();
+
+ for (Composition::recordtrackcontainer::const_iterator i =
+ tr.begin(); i != tr.end(); ++i) {
+ TrackId tid = (*i);
+ Track *track = m_doc->getComposition().getTrackById(tid);
+ if (track) {
+ iid.insert(track->getInstrument());
+ } else {
+ std::cerr << "Warning: RosegardenGUIApp::getArmedInstruments: Armed track " << tid << " not found in Composition" << std::endl;
+ }
+ }
+
+ QValueVector<InstrumentId> iv;
+ for (std::set
+ <InstrumentId>::iterator ii = iid.begin();
+ ii != iid.end(); ++ii) {
+ iv.push_back(*ii);
+ }
+ return iv;
+}
+
+void
+RosegardenGUIApp::showError(QString error)
+{
+ KStartupLogo::hideIfStillThere();
+ CurrentProgressDialog::freeze();
+
+ // This is principally used for return values from DSSI plugin
+ // configure() calls. It seems some plugins return a string
+ // telling you when everything's OK, as well as error strings, but
+ // dssi.h does make it reasonably clear that configure() should
+ // only return a string when there is actually a problem, so we're
+ // going to stick with a sorry dialog here rather than an
+ // information one
+
+ KMessageBox::sorry(0, error);
+
+ CurrentProgressDialog::thaw();
+}
+
+void
+RosegardenGUIApp::slotAudioManager()
+{
+ if (m_audioManagerDialog) {
+ m_audioManagerDialog->show();
+ m_audioManagerDialog->raise();
+ m_audioManagerDialog->setActiveWindow();
+ return ;
+ }
+
+ m_audioManagerDialog =
+ new AudioManagerDialog(this, m_doc);
+
+ connect(m_audioManagerDialog,
+ SIGNAL(playAudioFile(AudioFileId,
+ const RealTime &,
+ const RealTime&)),
+ SLOT(slotPlayAudioFile(AudioFileId,
+ const RealTime &,
+ const RealTime &)));
+
+ connect(m_audioManagerDialog,
+ SIGNAL(addAudioFile(AudioFileId)),
+ SLOT(slotAddAudioFile(AudioFileId)));
+
+ connect(m_audioManagerDialog,
+ SIGNAL(deleteAudioFile(AudioFileId)),
+ SLOT(slotDeleteAudioFile(AudioFileId)));
+
+ //
+ // Sync segment selection between audio man. dialog and main window
+ //
+
+ // from dialog to us...
+ connect(m_audioManagerDialog,
+ SIGNAL(segmentsSelected(const SegmentSelection&)),
+ m_view,
+ SLOT(slotPropagateSegmentSelection(const SegmentSelection&)));
+
+ // and from us to dialog
+ connect(this, SIGNAL(segmentsSelected(const SegmentSelection&)),
+ m_audioManagerDialog,
+ SLOT(slotSegmentSelection(const SegmentSelection&)));
+
+
+ connect(m_audioManagerDialog,
+ SIGNAL(deleteSegments(const SegmentSelection&)),
+ SLOT(slotDeleteSegments(const SegmentSelection&)));
+
+ connect(m_audioManagerDialog,
+ SIGNAL(insertAudioSegment(AudioFileId,
+ const RealTime&,
+ const RealTime&)),
+ m_view,
+ SLOT(slotAddAudioSegmentDefaultPosition(AudioFileId,
+ const RealTime&,
+ const RealTime&)));
+ connect(m_audioManagerDialog,
+ SIGNAL(cancelPlayingAudioFile(AudioFileId)),
+ SLOT(slotCancelAudioPlayingFile(AudioFileId)));
+
+ connect(m_audioManagerDialog,
+ SIGNAL(deleteAllAudioFiles()),
+ SLOT(slotDeleteAllAudioFiles()));
+
+ // Make sure we know when the audio man. dialog is closing
+ //
+ connect(m_audioManagerDialog,
+ SIGNAL(closing()),
+ SLOT(slotAudioManagerClosed()));
+
+ // And that it goes away when the current document is changing
+ //
+ connect(this, SIGNAL(documentAboutToChange()),
+ m_audioManagerDialog, SLOT(close()));
+
+ m_audioManagerDialog->setAudioSubsystemStatus(
+ m_seqManager->getSoundDriverStatus() & AUDIO_OK);
+
+ plugAccelerators(m_audioManagerDialog,
+ m_audioManagerDialog->getAccelerators());
+
+ m_audioManagerDialog->show();
+}
+
+void
+RosegardenGUIApp::slotPlayAudioFile(unsigned int id,
+ const RealTime &startTime,
+ const RealTime &duration)
+{
+ AudioFile *aF = m_doc->getAudioFileManager().getAudioFile(id);
+
+ if (aF == 0)
+ return ;
+
+ MappedEvent mE(m_doc->getStudio().
+ getAudioPreviewInstrument(),
+ id,
+ RealTime( -120, 0),
+ duration, // duration
+ startTime); // start index
+
+ StudioControl::sendMappedEvent(mE);
+
+}
+
+void
+RosegardenGUIApp::slotAddAudioFile(unsigned int id)
+{
+ AudioFile *aF = m_doc->getAudioFileManager().getAudioFile(id);
+
+ if (aF == 0)
+ return ;
+
+ QCString replyType;
+ QByteArray replyData;
+ QByteArray data;
+ QDataStream streamOut(data, IO_WriteOnly);
+
+ // We have to pass the filename as a QString
+ //
+ streamOut << QString(strtoqstr(aF->getFilename()));
+ streamOut << (int)aF->getId();
+
+ if (rgapp->sequencerCall("addAudioFile(QString, int)", replyType, replyData, data)) {
+ QDataStream streamIn(replyData, IO_ReadOnly);
+ int result;
+ streamIn >> result;
+ if (!result) {
+ KMessageBox::error(this, i18n("Sequencer failed to add audio file %1").arg(aF->getFilename().c_str()));
+ }
+ }
+}
+
+void
+RosegardenGUIApp::slotDeleteAudioFile(unsigned int id)
+{
+ if (m_doc->getAudioFileManager().removeFile(id) == false)
+ return ;
+
+ QCString replyType;
+ QByteArray replyData;
+ QByteArray data;
+ QDataStream streamOut(data, IO_WriteOnly);
+
+ // file id
+ //
+ streamOut << (int)id;
+
+ if (rgapp->sequencerCall("removeAudioFile(int)", replyType, replyData, data)) {
+ QDataStream streamIn(replyData, IO_ReadOnly);
+ int result;
+ streamIn >> result;
+ if (!result) {
+ KMessageBox::error(this, i18n("Sequencer failed to remove audio file id %1").arg(id));
+ }
+ }
+}
+
+void
+RosegardenGUIApp::slotDeleteSegments(const SegmentSelection &selection)
+{
+ m_view->slotPropagateSegmentSelection(selection);
+ slotDeleteSelectedSegments();
+}
+
+void
+RosegardenGUIApp::slotCancelAudioPlayingFile(AudioFileId id)
+{
+ AudioFile *aF = m_doc->getAudioFileManager().getAudioFile(id);
+
+ if (aF == 0)
+ return ;
+
+ MappedEvent mE(m_doc->getStudio().
+ getAudioPreviewInstrument(),
+ MappedEvent::AudioCancel,
+ id);
+
+ StudioControl::sendMappedEvent(mE);
+}
+
+void
+RosegardenGUIApp::slotDeleteAllAudioFiles()
+{
+ m_doc->getAudioFileManager().clear();
+
+ // Clear at the sequencer
+ //
+ QCString replyType;
+ QByteArray replyData;
+ QByteArray data;
+
+ rgapp->sequencerCall("clearAllAudioFiles()", replyType, replyData, data);
+}
+
+void
+RosegardenGUIApp::slotRepeatingSegments()
+{
+ m_view->getTrackEditor()->slotTurnRepeatingSegmentToRealCopies();
+}
+
+void
+RosegardenGUIApp::slotRelabelSegments()
+{
+ if (!m_view->haveSelection())
+ return ;
+
+ SegmentSelection selection(m_view->getSelection());
+ QString editLabel;
+
+ if (selection.size() == 0)
+ return ;
+ else if (selection.size() == 1)
+ editLabel = i18n("Modify Segment label");
+ else
+ editLabel = i18n("Modify Segments label");
+
+ KTmpStatusMsg msg(i18n("Relabelling selection..."), this);
+
+ // Generate label
+ QString label = strtoqstr((*selection.begin())->getLabel());
+
+ for (SegmentSelection::iterator i = selection.begin();
+ i != selection.end(); ++i) {
+ if (strtoqstr((*i)->getLabel()) != label)
+ label = "";
+ }
+
+ bool ok = false;
+
+ QString newLabel = KInputDialog::getText(editLabel,
+ i18n("Enter new label"),
+ label,
+ &ok,
+ this);
+
+ if (ok) {
+ m_doc->getCommandHistory()->addCommand
+ (new SegmentLabelCommand(selection, newLabel));
+ m_view->getTrackEditor()->getSegmentCanvas()->slotUpdateSegmentsDrawBuffer();
+ }
+}
+
+void
+RosegardenGUIApp::slotTransposeSegments()
+{
+ if (!m_view->haveSelection())
+ return ;
+
+ IntervalDialog intervalDialog(this, true, true);
+ int ok = intervalDialog.exec();
+
+ int semitones = intervalDialog.getChromaticDistance();
+ int steps = intervalDialog.getDiatonicDistance();
+
+ if (!ok || (semitones == 0 && steps == 0)) return;
+
+ m_doc->getCommandHistory()->addCommand
+ (new SegmentTransposeCommand(m_view->getSelection(), intervalDialog.getChangeKey(), steps, semitones, intervalDialog.getTransposeSegmentBack()));
+}
+
+void
+RosegardenGUIApp::slotChangeCompositionLength()
+{
+ CompositionLengthDialog dialog(this, &m_doc->getComposition());
+
+ if (dialog.exec() == QDialog::Accepted) {
+ ChangeCompositionLengthCommand *command
+ = new ChangeCompositionLengthCommand(
+ &m_doc->getComposition(),
+ dialog.getStartMarker(),
+ dialog.getEndMarker());
+
+ m_view->getTrackEditor()->getSegmentCanvas()->clearSegmentRectsCache(true);
+ m_doc->getCommandHistory()->addCommand(command);
+ }
+}
+
+void
+RosegardenGUIApp::slotManageMIDIDevices()
+{
+ if (m_deviceManager) {
+ m_deviceManager->show();
+ m_deviceManager->raise();
+ m_deviceManager->setActiveWindow();
+ return ;
+ }
+
+ m_deviceManager = new DeviceManagerDialog(this, m_doc);
+
+ connect(m_deviceManager, SIGNAL(closing()),
+ this, SLOT(slotDeviceManagerClosed()));
+
+ connect(this, SIGNAL(documentAboutToChange()),
+ m_deviceManager, SLOT(close()));
+
+ // Cheating way of updating the track/instrument list
+ //
+ connect(m_deviceManager, SIGNAL(deviceNamesChanged()),
+ m_view, SLOT(slotSynchroniseWithComposition()));
+
+ connect(m_deviceManager, SIGNAL(editBanks(DeviceId)),
+ this, SLOT(slotEditBanks(DeviceId)));
+
+ connect(m_deviceManager, SIGNAL(editControllers(DeviceId)),
+ this, SLOT(slotEditControlParameters(DeviceId)));
+
+ if (m_midiMixer) {
+ connect(m_deviceManager, SIGNAL(deviceNamesChanged()),
+ m_midiMixer, SLOT(slotSynchronise()));
+
+ }
+
+
+ m_deviceManager->show();
+}
+
+void
+RosegardenGUIApp::slotManageSynths()
+{
+ if (m_synthManager) {
+ m_synthManager->show();
+ m_synthManager->raise();
+ m_synthManager->setActiveWindow();
+ return ;
+ }
+
+ m_synthManager = new SynthPluginManagerDialog(this, m_doc
+#ifdef HAVE_LIBLO
+ , m_pluginGUIManager
+#endif
+ );
+
+ connect(m_synthManager, SIGNAL(closing()),
+ this, SLOT(slotSynthPluginManagerClosed()));
+
+ connect(this, SIGNAL(documentAboutToChange()),
+ m_synthManager, SLOT(close()));
+
+ connect(m_synthManager,
+ SIGNAL(pluginSelected(InstrumentId, int, int)),
+ this,
+ SLOT(slotPluginSelected(InstrumentId, int, int)));
+
+ connect(m_synthManager,
+ SIGNAL(showPluginDialog(QWidget *, InstrumentId, int)),
+ this,
+ SLOT(slotShowPluginDialog(QWidget *, InstrumentId, int)));
+
+ connect(m_synthManager,
+ SIGNAL(showPluginGUI(InstrumentId, int)),
+ this,
+ SLOT(slotShowPluginGUI(InstrumentId, int)));
+
+ m_synthManager->show();
+}
+
+void
+RosegardenGUIApp::slotOpenAudioMixer()
+{
+ if (m_audioMixer) {
+ m_audioMixer->show();
+ m_audioMixer->raise();
+ m_audioMixer->setActiveWindow();
+ return ;
+ }
+
+ m_audioMixer = new AudioMixerWindow(this, m_doc);
+
+ connect(m_audioMixer, SIGNAL(windowActivated()),
+ m_view, SLOT(slotActiveMainWindowChanged()));
+
+ connect(m_view, SIGNAL(controllerDeviceEventReceived(MappedEvent *, const void *)),
+ m_audioMixer, SLOT(slotControllerDeviceEventReceived(MappedEvent *, const void *)));
+
+ connect(m_audioMixer, SIGNAL(closing()),
+ this, SLOT(slotAudioMixerClosed()));
+
+ connect(m_audioMixer, SIGNAL(selectPlugin(QWidget *, InstrumentId, int)),
+ this, SLOT(slotShowPluginDialog(QWidget *, InstrumentId, int)));
+
+ connect(this,
+ SIGNAL(pluginSelected(InstrumentId, int, int)),
+ m_audioMixer,
+ SLOT(slotPluginSelected(InstrumentId, int, int)));
+
+ connect(this,
+ SIGNAL(pluginBypassed(InstrumentId, int, bool)),
+ m_audioMixer,
+ SLOT(slotPluginBypassed(InstrumentId, int, bool)));
+
+ connect(this, SIGNAL(documentAboutToChange()),
+ m_audioMixer, SLOT(close()));
+
+ connect(m_view, SIGNAL(checkTrackAssignments()),
+ m_audioMixer, SLOT(slotTrackAssignmentsChanged()));
+
+ connect(m_audioMixer, SIGNAL(play()),
+ this, SLOT(slotPlay()));
+ connect(m_audioMixer, SIGNAL(stop()),
+ this, SLOT(slotStop()));
+ connect(m_audioMixer, SIGNAL(fastForwardPlayback()),
+ this, SLOT(slotFastforward()));
+ connect(m_audioMixer, SIGNAL(rewindPlayback()),
+ this, SLOT(slotRewind()));
+ connect(m_audioMixer, SIGNAL(fastForwardPlaybackToEnd()),
+ this, SLOT(slotFastForwardToEnd()));
+ connect(m_audioMixer, SIGNAL(rewindPlaybackToBeginning()),
+ this, SLOT(slotRewindToBeginning()));
+ connect(m_audioMixer, SIGNAL(record()),
+ this, SLOT(slotRecord()));
+ connect(m_audioMixer, SIGNAL(panic()),
+ this, SLOT(slotPanic()));
+
+ connect(m_audioMixer,
+ SIGNAL(instrumentParametersChanged(InstrumentId)),
+ this,
+ SIGNAL(instrumentParametersChanged(InstrumentId)));
+
+ connect(this,
+ SIGNAL(instrumentParametersChanged(InstrumentId)),
+ m_audioMixer,
+ SLOT(slotUpdateInstrument(InstrumentId)));
+
+ if (m_synthManager) {
+ connect(m_synthManager,
+ SIGNAL(pluginSelected(InstrumentId, int, int)),
+ m_audioMixer,
+ SLOT(slotPluginSelected(InstrumentId, int, int)));
+ }
+
+ plugAccelerators(m_audioMixer, m_audioMixer->getAccelerators());
+
+ m_audioMixer->show();
+}
+
+void
+RosegardenGUIApp::slotOpenMidiMixer()
+{
+ if (m_midiMixer) {
+ m_midiMixer->show();
+ m_midiMixer->raise();
+ m_midiMixer->setActiveWindow();
+ return ;
+ }
+
+ m_midiMixer = new MidiMixerWindow(this, m_doc);
+
+ connect(m_midiMixer, SIGNAL(windowActivated()),
+ m_view, SLOT(slotActiveMainWindowChanged()));
+
+ connect(m_view, SIGNAL(controllerDeviceEventReceived(MappedEvent *, const void *)),
+ m_midiMixer, SLOT(slotControllerDeviceEventReceived(MappedEvent *, const void *)));
+
+ connect(m_midiMixer, SIGNAL(closing()),
+ this, SLOT(slotMidiMixerClosed()));
+
+ connect(this, SIGNAL(documentAboutToChange()),
+ m_midiMixer, SLOT(close()));
+
+ connect(m_midiMixer, SIGNAL(play()),
+ this, SLOT(slotPlay()));
+ connect(m_midiMixer, SIGNAL(stop()),
+ this, SLOT(slotStop()));
+ connect(m_midiMixer, SIGNAL(fastForwardPlayback()),
+ this, SLOT(slotFastforward()));
+ connect(m_midiMixer, SIGNAL(rewindPlayback()),
+ this, SLOT(slotRewind()));
+ connect(m_midiMixer, SIGNAL(fastForwardPlaybackToEnd()),
+ this, SLOT(slotFastForwardToEnd()));
+ connect(m_midiMixer, SIGNAL(rewindPlaybackToBeginning()),
+ this, SLOT(slotRewindToBeginning()));
+ connect(m_midiMixer, SIGNAL(record()),
+ this, SLOT(slotRecord()));
+ connect(m_midiMixer, SIGNAL(panic()),
+ this, SLOT(slotPanic()));
+
+ connect(m_midiMixer,
+ SIGNAL(instrumentParametersChanged(InstrumentId)),
+ this,
+ SIGNAL(instrumentParametersChanged(InstrumentId)));
+
+ connect(this,
+ SIGNAL(instrumentParametersChanged(InstrumentId)),
+ m_midiMixer,
+ SLOT(slotUpdateInstrument(InstrumentId)));
+
+ plugAccelerators(m_midiMixer, m_midiMixer->getAccelerators());
+
+ m_midiMixer->show();
+}
+
+void
+RosegardenGUIApp::slotEditControlParameters(DeviceId device)
+{
+ for (std::set
+ <ControlEditorDialog *>::iterator i = m_controlEditors.begin();
+ i != m_controlEditors.end(); ++i) {
+ if ((*i)->getDevice() == device) {
+ (*i)->show();
+ (*i)->raise();
+ (*i)->setActiveWindow();
+ return ;
+ }
+ }
+
+ ControlEditorDialog *controlEditor = new ControlEditorDialog(this, m_doc,
+ device);
+ m_controlEditors.insert(controlEditor);
+
+ RG_DEBUG << "inserting control editor dialog, have " << m_controlEditors.size() << " now" << endl;
+
+ connect(controlEditor, SIGNAL(closing()),
+ SLOT(slotControlEditorClosed()));
+
+ connect(this, SIGNAL(documentAboutToChange()),
+ controlEditor, SLOT(close()));
+
+ connect(m_doc, SIGNAL(devicesResyncd()),
+ controlEditor, SLOT(slotUpdate()));
+
+ controlEditor->show();
+}
+
+void
+RosegardenGUIApp::slotEditBanks()
+{
+ slotEditBanks(Device::NO_DEVICE);
+}
+
+void
+RosegardenGUIApp::slotEditBanks(DeviceId device)
+{
+ if (m_bankEditor) {
+ if (device != Device::NO_DEVICE)
+ m_bankEditor->setCurrentDevice(device);
+ m_bankEditor->show();
+ m_bankEditor->raise();
+ m_bankEditor->setActiveWindow();
+ return ;
+ }
+
+ m_bankEditor = new BankEditorDialog(this, m_doc, device);
+
+ connect(m_bankEditor, SIGNAL(closing()),
+ this, SLOT(slotBankEditorClosed()));
+
+ connect(this, SIGNAL(documentAboutToChange()),
+ m_bankEditor, SLOT(slotFileClose()));
+
+ // Cheating way of updating the track/instrument list
+ //
+ connect(m_bankEditor, SIGNAL(deviceNamesChanged()),
+ m_view, SLOT(slotSynchroniseWithComposition()));
+
+ m_bankEditor->show();
+}
+
+void
+RosegardenGUIApp::slotManageTriggerSegments()
+{
+ if (m_triggerSegmentManager) {
+ m_triggerSegmentManager->show();
+ m_triggerSegmentManager->raise();
+ m_triggerSegmentManager->setActiveWindow();
+ return ;
+ }
+
+ m_triggerSegmentManager = new TriggerSegmentManager(this, m_doc);
+
+ connect(m_triggerSegmentManager, SIGNAL(closing()),
+ SLOT(slotTriggerManagerClosed()));
+
+ connect(m_triggerSegmentManager, SIGNAL(editTriggerSegment(int)),
+ m_view, SLOT(slotEditTriggerSegment(int)));
+
+ m_triggerSegmentManager->show();
+}
+
+void
+RosegardenGUIApp::slotTriggerManagerClosed()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotTriggerManagerClosed" << endl;
+
+ m_triggerSegmentManager = 0;
+}
+
+void
+RosegardenGUIApp::slotEditMarkers()
+{
+ if (m_markerEditor) {
+ m_markerEditor->show();
+ m_markerEditor->raise();
+ m_markerEditor->setActiveWindow();
+ return ;
+ }
+
+ m_markerEditor = new MarkerEditor(this, m_doc);
+
+ connect(m_markerEditor, SIGNAL(closing()),
+ SLOT(slotMarkerEditorClosed()));
+
+ connect(m_markerEditor, SIGNAL(jumpToMarker(timeT)),
+ m_doc, SLOT(slotSetPointerPosition(timeT)));
+
+ plugAccelerators(m_markerEditor, m_markerEditor->getAccelerators());
+
+ m_markerEditor->show();
+}
+
+void
+RosegardenGUIApp::slotMarkerEditorClosed()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotMarkerEditorClosed" << endl;
+
+ m_markerEditor = 0;
+}
+
+void
+RosegardenGUIApp::slotEditTempos(timeT t)
+{
+ if (m_tempoView) {
+ m_tempoView->show();
+ m_tempoView->raise();
+ m_tempoView->setActiveWindow();
+ return ;
+ }
+
+ m_tempoView = new TempoView(m_doc, getView(), t);
+
+ connect(m_tempoView, SIGNAL(closing()),
+ SLOT(slotTempoViewClosed()));
+
+ connect(m_tempoView, SIGNAL(windowActivated()),
+ getView(), SLOT(slotActiveMainWindowChanged()));
+
+ connect(m_tempoView,
+ SIGNAL(changeTempo(timeT,
+ tempoT,
+ tempoT,
+ TempoDialog::TempoDialogAction)),
+ this,
+ SLOT(slotChangeTempo(timeT,
+ tempoT,
+ tempoT,
+ TempoDialog::TempoDialogAction)));
+
+ connect(m_tempoView, SIGNAL(saveFile()), this, SLOT(slotFileSave()));
+
+ plugAccelerators(m_tempoView, m_tempoView->getAccelerators());
+
+ m_tempoView->show();
+}
+
+void
+RosegardenGUIApp::slotTempoViewClosed()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotTempoViewClosed" << endl;
+
+ m_tempoView = 0;
+}
+
+void
+RosegardenGUIApp::slotControlEditorClosed()
+{
+ const QObject *s = sender();
+
+ RG_DEBUG << "RosegardenGUIApp::slotControlEditorClosed" << endl;
+
+ for (std::set
+ <ControlEditorDialog *>::iterator i = m_controlEditors.begin();
+ i != m_controlEditors.end(); ++i) {
+ if (*i == s) {
+ m_controlEditors.erase(i);
+ RG_DEBUG << "removed control editor dialog, have " << m_controlEditors.size() << " left" << endl;
+ return ;
+ }
+ }
+
+ std::cerr << "WARNING: control editor " << s << " closed, but couldn't find it in our control editor list (we have " << m_controlEditors.size() << " editors)" << std::endl;
+}
+
+void
+RosegardenGUIApp::slotShowPluginDialog(QWidget *parent,
+ InstrumentId instrumentId,
+ int index)
+{
+ if (!parent)
+ parent = this;
+
+ int key = (index << 16) + instrumentId;
+
+ if (m_pluginDialogs[key]) {
+ m_pluginDialogs[key]->show();
+ m_pluginDialogs[key]->raise();
+ m_pluginDialogs[key]->setActiveWindow();
+ return ;
+ }
+
+ PluginContainer *container = 0;
+
+ container = m_doc->getStudio().getContainerById(instrumentId);
+ if (!container) {
+ RG_DEBUG << "RosegardenGUIApp::slotShowPluginDialog - "
+ << "no instrument or buss of id " << instrumentId << endl;
+ return ;
+ }
+
+ // only create a dialog if we've got a plugin instance
+ AudioPluginInstance *inst =
+ container->getPlugin(index);
+
+ if (!inst) {
+ RG_DEBUG << "RosegardenGUIApp::slotShowPluginDialog - "
+ << "no AudioPluginInstance found for index "
+ << index << endl;
+ return ;
+ }
+
+ // Create the plugin dialog
+ //
+ AudioPluginDialog *dialog =
+ new AudioPluginDialog(parent,
+ m_doc->getPluginManager(),
+#ifdef HAVE_LIBLO
+ m_pluginGUIManager,
+#endif
+ container,
+ index);
+
+ connect(dialog, SIGNAL(windowActivated()),
+ m_view, SLOT(slotActiveMainWindowChanged()));
+
+/* This feature isn't provided by the plugin dialog
+ connect(m_view, SIGNAL(controllerDeviceEventReceived(MappedEvent *, const void *)),
+ dialog, SLOT(slotControllerDeviceEventReceived(MappedEvent *, const void *)));
+*/
+
+ // Plug the new dialog into the standard keyboard accelerators so
+ // that we can use them still while the plugin has focus.
+ //
+ plugAccelerators(dialog, dialog->getAccelerators());
+
+ connect(dialog,
+ SIGNAL(pluginSelected(InstrumentId, int, int)),
+ this,
+ SLOT(slotPluginSelected(InstrumentId, int, int)));
+
+ connect(dialog,
+ SIGNAL(pluginPortChanged(InstrumentId, int, int)),
+ this,
+ SLOT(slotPluginPortChanged(InstrumentId, int, int)));
+
+ connect(dialog,
+ SIGNAL(pluginProgramChanged(InstrumentId, int)),
+ this,
+ SLOT(slotPluginProgramChanged(InstrumentId, int)));
+
+ connect(dialog,
+ SIGNAL(changePluginConfiguration(InstrumentId, int, bool, QString, QString)),
+ this,
+ SLOT(slotChangePluginConfiguration(InstrumentId, int, bool, QString, QString)));
+
+ connect(dialog,
+ SIGNAL(showPluginGUI(InstrumentId, int)),
+ this,
+ SLOT(slotShowPluginGUI(InstrumentId, int)));
+
+ connect(dialog,
+ SIGNAL(stopPluginGUI(InstrumentId, int)),
+ this,
+ SLOT(slotStopPluginGUI(InstrumentId, int)));
+
+ connect(dialog,
+ SIGNAL(bypassed(InstrumentId, int, bool)),
+ this,
+ SLOT(slotPluginBypassed(InstrumentId, int, bool)));
+
+ connect(dialog,
+ SIGNAL(destroyed(InstrumentId, int)),
+ this,
+ SLOT(slotPluginDialogDestroyed(InstrumentId, int)));
+
+ connect(this, SIGNAL(documentAboutToChange()), dialog, SLOT(close()));
+
+ m_pluginDialogs[key] = dialog;
+ m_pluginDialogs[key]->show();
+
+ // Set modified
+ m_doc->slotDocumentModified();
+}
+
+void
+RosegardenGUIApp::slotPluginSelected(InstrumentId instrumentId,
+ int index, int plugin)
+{
+ const QObject *s = sender();
+
+ bool fromSynthMgr = (s == m_synthManager);
+
+ // It's assumed that ports etc will already have been set up on
+ // the AudioPluginInstance before this is invoked.
+
+ PluginContainer *container = 0;
+
+ container = m_doc->getStudio().getContainerById(instrumentId);
+ if (!container) {
+ RG_DEBUG << "RosegardenGUIApp::slotPluginSelected - "
+ << "no instrument or buss of id " << instrumentId << endl;
+ return ;
+ }
+
+ AudioPluginInstance *inst =
+ container->getPlugin(index);
+
+ if (!inst) {
+ RG_DEBUG << "RosegardenGUIApp::slotPluginSelected - "
+ << "got index of unknown plugin!" << endl;
+ return ;
+ }
+
+ if (plugin == -1) {
+ // Destroy plugin instance
+ //!!! seems iffy -- why can't we just unassign it?
+
+ if (StudioControl::
+ destroyStudioObject(inst->getMappedId())) {
+ RG_DEBUG << "RosegardenGUIApp::slotPluginSelected - "
+ << "cannot destroy Studio object "
+ << inst->getMappedId() << endl;
+ }
+
+ inst->setAssigned(false);
+ } else {
+ // If unassigned then create a sequencer instance of this
+ // AudioPluginInstance.
+ //
+ if (inst->isAssigned()) {
+ RG_DEBUG << "RosegardenGUIApp::slotPluginSelected - "
+ << " setting identifier for mapper id " << inst->getMappedId()
+ << " to " << inst->getIdentifier() << endl;
+
+ StudioControl::setStudioObjectProperty
+ (inst->getMappedId(),
+ MappedPluginSlot::Identifier,
+ strtoqstr(inst->getIdentifier()));
+ } else {
+ // create a studio object at the sequencer
+ MappedObjectId newId =
+ StudioControl::createStudioObject
+ (MappedObject::PluginSlot);
+
+ RG_DEBUG << "RosegardenGUIApp::slotPluginSelected - "
+ << " new MappedObjectId = " << newId << endl;
+
+ // set the new Mapped ID and that this instance
+ // is assigned
+ inst->setMappedId(newId);
+ inst->setAssigned(true);
+
+ // set the instrument id
+ StudioControl::setStudioObjectProperty
+ (newId,
+ MappedObject::Instrument,
+ MappedObjectValue(instrumentId));
+
+ // set the position
+ StudioControl::setStudioObjectProperty
+ (newId,
+ MappedObject::Position,
+ MappedObjectValue(index));
+
+ // set the plugin id
+ StudioControl::setStudioObjectProperty
+ (newId,
+ MappedPluginSlot::Identifier,
+ strtoqstr(inst->getIdentifier()));
+ }
+ }
+
+ int pluginMappedId = inst->getMappedId();
+
+ //!!! much code duplicated here from RosegardenGUIDoc::initialiseStudio
+
+ inst->setConfigurationValue
+ (qstrtostr(PluginIdentifier::RESERVED_PROJECT_DIRECTORY_KEY),
+ m_doc->getAudioFileManager().getAudioPath());
+
+ // Set opaque string configuration data (e.g. for DSSI plugin)
+ //
+ MappedObjectPropertyList config;
+ for (AudioPluginInstance::ConfigMap::const_iterator
+ i = inst->getConfiguration().begin();
+ i != inst->getConfiguration().end(); ++i) {
+ config.push_back(strtoqstr(i->first));
+ config.push_back(strtoqstr(i->second));
+ }
+ StudioControl::setStudioObjectPropertyList
+ (pluginMappedId,
+ MappedPluginSlot::Configuration,
+ config);
+
+ // Set the bypass
+ //
+ StudioControl::setStudioObjectProperty
+ (pluginMappedId,
+ MappedPluginSlot::Bypassed,
+ MappedObjectValue(inst->isBypassed()));
+
+ // Set the program
+ //
+ if (inst->getProgram() != "") {
+ StudioControl::setStudioObjectProperty
+ (pluginMappedId,
+ MappedPluginSlot::Program,
+ strtoqstr(inst->getProgram()));
+ }
+
+ // Set all the port values
+ //
+ PortInstanceIterator portIt;
+
+ for (portIt = inst->begin();
+ portIt != inst->end(); ++portIt) {
+ StudioControl::setStudioPluginPort
+ (pluginMappedId,
+ (*portIt)->number,
+ (*portIt)->value);
+ }
+
+ if (fromSynthMgr) {
+ int key = (index << 16) + instrumentId;
+ if (m_pluginDialogs[key]) {
+ m_pluginDialogs[key]->updatePlugin(plugin);
+ }
+ } else if (m_synthManager) {
+ m_synthManager->updatePlugin(instrumentId, plugin);
+ }
+
+ emit pluginSelected(instrumentId, index, plugin);
+
+ // Set modified
+ m_doc->slotDocumentModified();
+}
+
+void
+RosegardenGUIApp::slotChangePluginPort(InstrumentId instrumentId,
+ int pluginIndex,
+ int portIndex,
+ float value)
+{
+ PluginContainer *container = 0;
+
+ container = m_doc->getStudio().getContainerById(instrumentId);
+ if (!container) {
+ RG_DEBUG << "RosegardenGUIApp::slotChangePluginPort - "
+ << "no instrument or buss of id " << instrumentId << endl;
+ return ;
+ }
+
+ AudioPluginInstance *inst = container->getPlugin(pluginIndex);
+ if (!inst) {
+ RG_DEBUG << "RosegardenGUIApp::slotChangePluginPort - "
+ << "no plugin at index " << pluginIndex << " on " << instrumentId << endl;
+ return ;
+ }
+
+ PluginPortInstance *port = inst->getPort(portIndex);
+ if (!port) {
+ RG_DEBUG << "RosegardenGUIApp::slotChangePluginPort - no port "
+ << portIndex << endl;
+ return ;
+ }
+
+ RG_DEBUG << "RosegardenGUIApp::slotPluginPortChanged - "
+ << "setting plugin port (" << inst->getMappedId()
+ << ", " << portIndex << ") from " << port->value
+ << " to " << value << endl;
+
+ port->setValue(value);
+
+ StudioControl::setStudioPluginPort(inst->getMappedId(),
+ portIndex, port->value);
+
+ m_doc->slotDocumentModified();
+
+ // This modification came from The Outside!
+ int key = (pluginIndex << 16) + instrumentId;
+ if (m_pluginDialogs[key]) {
+ m_pluginDialogs[key]->updatePluginPortControl(portIndex);
+ }
+}
+
+void
+RosegardenGUIApp::slotPluginPortChanged(InstrumentId instrumentId,
+ int pluginIndex,
+ int portIndex)
+{
+ PluginContainer *container = 0;
+
+ container = m_doc->getStudio().getContainerById(instrumentId);
+ if (!container) {
+ RG_DEBUG << "RosegardenGUIApp::slotPluginPortChanged - "
+ << "no instrument or buss of id " << instrumentId << endl;
+ return ;
+ }
+
+ AudioPluginInstance *inst = container->getPlugin(pluginIndex);
+ if (!inst) {
+ RG_DEBUG << "RosegardenGUIApp::slotPluginPortChanged - "
+ << "no plugin at index " << pluginIndex << " on " << instrumentId << endl;
+ return ;
+ }
+
+ PluginPortInstance *port = inst->getPort(portIndex);
+ if (!port) {
+ RG_DEBUG << "RosegardenGUIApp::slotPluginPortChanged - no port "
+ << portIndex << endl;
+ return ;
+ }
+
+ RG_DEBUG << "RosegardenGUIApp::slotPluginPortChanged - "
+ << "setting plugin port (" << inst->getMappedId()
+ << ", " << portIndex << ") to " << port->value << endl;
+
+ StudioControl::setStudioPluginPort(inst->getMappedId(),
+ portIndex, port->value);
+
+ m_doc->slotDocumentModified();
+
+#ifdef HAVE_LIBLO
+ // This modification came from our own plugin dialog, so update
+ // any external GUIs
+ if (m_pluginGUIManager) {
+ m_pluginGUIManager->updatePort(instrumentId,
+ pluginIndex,
+ portIndex);
+ }
+#endif
+}
+
+void
+RosegardenGUIApp::slotChangePluginProgram(InstrumentId instrumentId,
+ int pluginIndex,
+ QString program)
+{
+ PluginContainer *container = 0;
+
+ container = m_doc->getStudio().getContainerById(instrumentId);
+ if (!container) {
+ RG_DEBUG << "RosegardenGUIApp::slotChangePluginProgram - "
+ << "no instrument or buss of id " << instrumentId << endl;
+ return ;
+ }
+
+ AudioPluginInstance *inst = container->getPlugin(pluginIndex);
+ if (!inst) {
+ RG_DEBUG << "RosegardenGUIApp::slotChangePluginProgram - "
+ << "no plugin at index " << pluginIndex << " on " << instrumentId << endl;
+ return ;
+ }
+
+ RG_DEBUG << "RosegardenGUIApp::slotChangePluginProgram - "
+ << "setting plugin program ("
+ << inst->getMappedId() << ") from " << inst->getProgram()
+ << " to " << program << endl;
+
+ inst->setProgram(qstrtostr(program));
+
+ StudioControl::
+ setStudioObjectProperty(inst->getMappedId(),
+ MappedPluginSlot::Program,
+ program);
+
+ PortInstanceIterator portIt;
+
+ for (portIt = inst->begin();
+ portIt != inst->end(); ++portIt) {
+ float value = StudioControl::getStudioPluginPort
+ (inst->getMappedId(),
+ (*portIt)->number);
+ (*portIt)->value = value;
+ }
+
+ // Set modified
+ m_doc->slotDocumentModified();
+
+ int key = (pluginIndex << 16) + instrumentId;
+ if (m_pluginDialogs[key]) {
+ m_pluginDialogs[key]->updatePluginProgramControl();
+ }
+}
+
+void
+RosegardenGUIApp::slotPluginProgramChanged(InstrumentId instrumentId,
+ int pluginIndex)
+{
+ PluginContainer *container = 0;
+
+ container = m_doc->getStudio().getContainerById(instrumentId);
+ if (!container) {
+ RG_DEBUG << "RosegardenGUIApp::slotPluginProgramChanged - "
+ << "no instrument or buss of id " << instrumentId << endl;
+ return ;
+ }
+
+ AudioPluginInstance *inst = container->getPlugin(pluginIndex);
+ if (!inst) {
+ RG_DEBUG << "RosegardenGUIApp::slotPluginProgramChanged - "
+ << "no plugin at index " << pluginIndex << " on " << instrumentId << endl;
+ return ;
+ }
+
+ QString program = strtoqstr(inst->getProgram());
+
+ RG_DEBUG << "RosegardenGUIApp::slotPluginProgramChanged - "
+ << "setting plugin program ("
+ << inst->getMappedId() << ") to " << program << endl;
+
+ StudioControl::
+ setStudioObjectProperty(inst->getMappedId(),
+ MappedPluginSlot::Program,
+ program);
+
+ PortInstanceIterator portIt;
+
+ for (portIt = inst->begin();
+ portIt != inst->end(); ++portIt) {
+ float value = StudioControl::getStudioPluginPort
+ (inst->getMappedId(),
+ (*portIt)->number);
+ (*portIt)->value = value;
+ }
+
+ // Set modified
+ m_doc->slotDocumentModified();
+
+#ifdef HAVE_LIBLO
+
+ if (m_pluginGUIManager)
+ m_pluginGUIManager->updateProgram(instrumentId,
+ pluginIndex);
+#endif
+}
+
+void
+RosegardenGUIApp::slotChangePluginConfiguration(InstrumentId instrumentId,
+ int index,
+ bool global,
+ QString key,
+ QString value)
+{
+ PluginContainer *container = 0;
+
+ container = m_doc->getStudio().getContainerById(instrumentId);
+ if (!container) {
+ RG_DEBUG << "RosegardenGUIApp::slotChangePluginConfiguration - "
+ << "no instrument or buss of id " << instrumentId << endl;
+ return ;
+ }
+
+ AudioPluginInstance *inst = container->getPlugin(index);
+
+ if (global && inst) {
+
+ // Set the same configuration on other plugins in the same
+ // instance group
+
+ AudioPlugin *pl =
+ m_pluginManager->getPluginByIdentifier(strtoqstr(inst->getIdentifier()));
+
+ if (pl && pl->isGrouped()) {
+
+ InstrumentList il =
+ m_doc->getStudio().getAllInstruments();
+
+ for (InstrumentList::iterator i = il.begin();
+ i != il.end(); ++i) {
+
+ for (PluginInstanceIterator pli =
+ (*i)->beginPlugins();
+ pli != (*i)->endPlugins(); ++pli) {
+
+ if (*pli && (*pli)->isAssigned() &&
+ (*pli)->getIdentifier() == inst->getIdentifier() &&
+ (*pli) != inst) {
+
+ slotChangePluginConfiguration
+ ((*i)->getId(), (*pli)->getPosition(),
+ false, key, value);
+
+#ifdef HAVE_LIBLO
+
+ m_pluginGUIManager->updateConfiguration
+ ((*i)->getId(), (*pli)->getPosition(), key);
+#endif
+
+ }
+ }
+ }
+ }
+ }
+
+ if (inst) {
+
+ inst->setConfigurationValue(qstrtostr(key), qstrtostr(value));
+
+ MappedObjectPropertyList config;
+ for (AudioPluginInstance::ConfigMap::const_iterator
+ i = inst->getConfiguration().begin();
+ i != inst->getConfiguration().end(); ++i) {
+ config.push_back(strtoqstr(i->first));
+ config.push_back(strtoqstr(i->second));
+ }
+
+ RG_DEBUG << "RosegardenGUIApp::slotChangePluginConfiguration: setting new config on mapped id " << inst->getMappedId() << endl;
+
+ StudioControl::setStudioObjectPropertyList
+ (inst->getMappedId(),
+ MappedPluginSlot::Configuration,
+ config);
+
+ // Set modified
+ m_doc->slotDocumentModified();
+
+ int key = (index << 16) + instrumentId;
+ if (m_pluginDialogs[key]) {
+ m_pluginDialogs[key]->updatePluginProgramList();
+ }
+ }
+}
+
+void
+RosegardenGUIApp::slotPluginDialogDestroyed(InstrumentId instrumentId,
+ int index)
+{
+ int key = (index << 16) + instrumentId;
+ m_pluginDialogs[key] = 0;
+}
+
+void
+RosegardenGUIApp::slotPluginBypassed(InstrumentId instrumentId,
+ int pluginIndex, bool bp)
+{
+ PluginContainer *container = 0;
+
+ container = m_doc->getStudio().getContainerById(instrumentId);
+ if (!container) {
+ RG_DEBUG << "RosegardenGUIApp::slotPluginBypassed - "
+ << "no instrument or buss of id " << instrumentId << endl;
+ return ;
+ }
+
+ AudioPluginInstance *inst = container->getPlugin(pluginIndex);
+
+ if (inst) {
+ StudioControl::setStudioObjectProperty
+ (inst->getMappedId(),
+ MappedPluginSlot::Bypassed,
+ MappedObjectValue(bp));
+
+ // Set the bypass on the instance
+ //
+ inst->setBypass(bp);
+
+ // Set modified
+ m_doc->slotDocumentModified();
+ }
+
+ emit pluginBypassed(instrumentId, pluginIndex, bp);
+}
+
+void
+RosegardenGUIApp::slotShowPluginGUI(InstrumentId instrument,
+ int index)
+{
+#ifdef HAVE_LIBLO
+ m_pluginGUIManager->showGUI(instrument, index);
+#endif
+}
+
+void
+RosegardenGUIApp::slotStopPluginGUI(InstrumentId instrument,
+ int index)
+{
+#ifdef HAVE_LIBLO
+ m_pluginGUIManager->stopGUI(instrument, index);
+#endif
+}
+
+void
+RosegardenGUIApp::slotPluginGUIExited(InstrumentId instrument,
+ int index)
+{
+ int key = (index << 16) + instrument;
+ if (m_pluginDialogs[key]) {
+ m_pluginDialogs[key]->guiExited();
+ }
+}
+
+void
+RosegardenGUIApp::slotPlayList()
+{
+ if (!m_playList) {
+ m_playList = new PlayListDialog(i18n("Play List"), this);
+ connect(m_playList, SIGNAL(closing()),
+ SLOT(slotPlayListClosed()));
+ connect(m_playList->getPlayList(), SIGNAL(play(QString)),
+ SLOT(slotPlayListPlay(QString)));
+ }
+
+ m_playList->show();
+}
+
+void
+RosegardenGUIApp::slotPlayListPlay(QString url)
+{
+ slotStop();
+ openURL(url);
+ slotPlay();
+}
+
+void
+RosegardenGUIApp::slotPlayListClosed()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotPlayListClosed()\n";
+ m_playList = 0;
+}
+
+void
+RosegardenGUIApp::slotTutorial()
+{
+ QString exe = KStandardDirs::findExe( "x-www-browser" );
+
+ if( exe )
+ {
+ KProcess *proc = new KProcess;
+ *proc << "x-www-browser";
+ *proc << "http://rosegarden.sourceforge.net/tutorial/en/chapter-0.html";
+
+ proc->start(KProcess::DontCare);
+ proc->detach();
+ delete proc;
+ }
+ else
+ {
+ QString tutorialURL = i18n("http://rosegarden.sourceforge.net/tutorial/en/chapter-0.html");
+ kapp->invokeBrowser(tutorialURL);
+ }
+}
+
+void
+RosegardenGUIApp::slotBugGuidelines()
+{
+ QString exe = KStandardDirs::findExe( "x-www-browser" );
+
+ if( exe )
+ {
+ KProcess *proc = new KProcess;
+ *proc << "x-www-browser";
+ *proc << "http://rosegarden.sourceforge.net/tutorial/bug-guidelines.html";
+
+ proc->start(KProcess::DontCare);
+ proc->detach();
+ delete proc;
+ }
+ else
+ {
+ QString tutorialURL = i18n("http://rosegarden.sourceforge.net/tutorial/bug-guidelines.html");
+ kapp->invokeBrowser(tutorialURL);
+ }
+}
+
+void
+RosegardenGUIApp::slotBankEditorClosed()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotBankEditorClosed()\n";
+
+ if (m_doc->isModified()) {
+ if (m_view)
+ m_view->slotSelectTrackSegments(m_doc->getComposition().getSelectedTrack());
+ }
+
+ m_bankEditor = 0;
+}
+
+void
+RosegardenGUIApp::slotDeviceManagerClosed()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotDeviceManagerClosed()\n";
+
+ if (m_doc->isModified()) {
+ if (m_view)
+ m_view->slotSelectTrackSegments(m_doc->getComposition().getSelectedTrack());
+ }
+
+ m_deviceManager = 0;
+}
+
+void
+RosegardenGUIApp::slotSynthPluginManagerClosed()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotSynthPluginManagerClosed()\n";
+
+ m_synthManager = 0;
+}
+
+void
+RosegardenGUIApp::slotAudioMixerClosed()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotAudioMixerClosed()\n";
+
+ m_audioMixer = 0;
+}
+
+void
+RosegardenGUIApp::slotMidiMixerClosed()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotMidiMixerClosed()\n";
+
+ m_midiMixer = 0;
+}
+
+void
+RosegardenGUIApp::slotAudioManagerClosed()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotAudioManagerClosed()\n";
+
+ if (m_doc->isModified()) {
+ if (m_view)
+ m_view->slotSelectTrackSegments(m_doc->getComposition().getSelectedTrack());
+ }
+
+ m_audioManagerDialog = 0;
+}
+
+void
+RosegardenGUIApp::slotPanic()
+{
+ if (m_seqManager) {
+ // Stop the transport before we send a panic as the
+ // playback goes all to hell anyway.
+ //
+ slotStop();
+
+ ProgressDialog progressDlg(i18n("Queueing MIDI panic events for tranmission..."),
+ 100,
+ this);
+ CurrentProgressDialog::set
+ (&progressDlg);
+ ProgressDialog::processEvents();
+
+ connect(m_seqManager, SIGNAL(setProgress(int)),
+ progressDlg.progressBar(), SLOT(setValue(int)));
+ connect(m_seqManager, SIGNAL(incrementProgress(int)),
+ progressDlg.progressBar(), SLOT(advance(int)));
+
+ m_seqManager->panic();
+
+ }
+}
+
+void
+RosegardenGUIApp::slotPopulateTrackInstrumentPopup()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotSetTrackInstrument\n";
+ Composition &comp = m_doc->getComposition();
+ Track *track = comp.getTrackById(comp.getSelectedTrack());
+
+ if (!track) {
+ RG_DEBUG << "Weird: no track available for instrument popup!" << endl;
+ return ;
+ }
+
+ Instrument* instrument = m_doc->getStudio().getInstrumentById(track->getInstrument());
+
+ QPopupMenu* popup = dynamic_cast<QPopupMenu*>(factory()->container("set_track_instrument", this));
+
+ m_view->getTrackEditor()->getTrackButtons()->populateInstrumentPopup(instrument, popup);
+}
+
+void
+RosegardenGUIApp::slotRemapInstruments()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotRemapInstruments\n";
+ RemapInstrumentDialog dialog(this, m_doc);
+
+ connect(&dialog, SIGNAL(applyClicked()),
+ m_view->getTrackEditor()->getTrackButtons(),
+ SLOT(slotSynchroniseWithComposition()));
+
+ if (dialog.exec() == QDialog::Accepted) {
+ RG_DEBUG << "slotRemapInstruments - accepted\n";
+ }
+
+}
+
+void
+RosegardenGUIApp::slotSaveDefaultStudio()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotSaveDefaultStudio\n";
+
+ int reply = KMessageBox::warningYesNo
+ (this, i18n("Are you sure you want to save this as your default studio?"));
+
+ if (reply != KMessageBox::Yes)
+ return ;
+
+ KTmpStatusMsg msg(i18n("Saving current document as default studio..."), this);
+
+ QString autoloadFile = ::locateLocal("appdata", "autoload.rg");
+
+ RG_DEBUG << "RosegardenGUIApp::slotSaveDefaultStudio : saving studio in "
+ << autoloadFile << endl;
+
+ SetWaitCursor waitCursor;
+ QString errMsg;
+ bool res = m_doc->saveDocument(autoloadFile, errMsg);
+ if (!res) {
+ if (errMsg)
+ KMessageBox::error(this, i18n(QString("Could not auto-save document at %1\nError was : %2")
+ .arg(autoloadFile).arg(errMsg)));
+ else
+ KMessageBox::error(this, i18n(QString("Could not auto-save document at %1")
+ .arg(autoloadFile)));
+
+ }
+}
+
+void
+RosegardenGUIApp::slotImportDefaultStudio()
+{
+ int reply = KMessageBox::warningYesNo
+ (this, i18n("Are you sure you want to import your default studio and lose the current one?"));
+
+ if (reply != KMessageBox::Yes)
+ return ;
+
+ QString autoloadFile =
+ KGlobal::dirs()->findResource("appdata", "autoload.rg");
+
+ QFileInfo autoloadFileInfo(autoloadFile);
+
+ if (!autoloadFileInfo.isReadable()) {
+ RG_DEBUG << "RosegardenGUIDoc::slotImportDefaultStudio - "
+ << "can't find autoload file - defaulting" << endl;
+ return ;
+ }
+
+ slotImportStudioFromFile(autoloadFile);
+}
+
+void
+RosegardenGUIApp::slotImportStudio()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotImportStudio()\n";
+
+ QString studioDir = KGlobal::dirs()->findResource("appdata", "library/");
+ QDir dir(studioDir);
+ if (!dir.exists()) {
+ studioDir = ":ROSEGARDENDEVICE";
+ } else {
+ studioDir = "file://" + studioDir;
+ }
+
+ KURL url = KFileDialog::getOpenURL
+ (studioDir,
+ "audio/x-rosegarden-device audio/x-rosegarden",
+ this, i18n("Import Studio from File"));
+
+ if (url.isEmpty())
+ return ;
+
+ QString target;
+ if (KIO::NetAccess::download(url, target, this) == false) {
+ KMessageBox::error(this, i18n("Cannot download file %1")
+ .arg(url.prettyURL()));
+ return ;
+ }
+
+ slotImportStudioFromFile(target);
+}
+
+void
+RosegardenGUIApp::slotImportStudioFromFile(const QString &file)
+{
+ RosegardenGUIDoc *doc = new RosegardenGUIDoc(this, 0, true); // skipAutoload
+
+ Studio &oldStudio = m_doc->getStudio();
+ Studio &newStudio = doc->getStudio();
+
+ // Add some dummy devices for when we open the document. We guess
+ // that the file won't have more than 32 devices.
+ //
+ // for (unsigned int i = 0; i < 32; i++) {
+ // newStudio.addDevice("", i, Device::Midi);
+ // }
+
+ if (doc->openDocument(file, true)) { // true because we actually
+ // do want to create devices
+ // on the sequencer here
+
+ KMacroCommand *command = new KMacroCommand(i18n("Import Studio"));
+ doc->syncDevices();
+
+ // We actually only copy across MIDI play devices... for now
+ std::vector<DeviceId> midiPlayDevices;
+
+ for (DeviceList::const_iterator i =
+ oldStudio.begin(); i != oldStudio.end(); ++i) {
+
+ MidiDevice *md =
+ dynamic_cast<MidiDevice *>(*i);
+
+ if (md && (md->getDirection() == MidiDevice::Play)) {
+ midiPlayDevices.push_back((*i)->getId());
+ }
+ }
+
+ std::vector<DeviceId>::iterator di(midiPlayDevices.begin());
+
+ for (DeviceList::const_iterator i =
+ newStudio.begin(); i != newStudio.end(); ++i) {
+
+ MidiDevice *md =
+ dynamic_cast<MidiDevice *>(*i);
+
+ if (md && (md->getDirection() == MidiDevice::Play)) {
+ if (di != midiPlayDevices.end()) {
+ MidiDevice::VariationType variation
+ (md->getVariationType());
+ BankList bl(md->getBanks());
+ ProgramList pl(md->getPrograms());
+ ControlList cl(md->getControlParameters());
+
+ ModifyDeviceCommand* mdCommand = new ModifyDeviceCommand(&oldStudio,
+ *di,
+ md->getName(),
+ md->getLibrarianName(),
+ md->getLibrarianEmail());
+ mdCommand->setVariation(variation);
+ mdCommand->setBankList(bl);
+ mdCommand->setProgramList(pl);
+ mdCommand->setControlList(cl);
+ mdCommand->setOverwrite(true);
+ mdCommand->setRename(md->getName() != "");
+
+ command->addCommand(mdCommand);
+ ++di;
+ }
+ }
+ }
+
+ while (di != midiPlayDevices.end()) {
+ command->addCommand(new CreateOrDeleteDeviceCommand
+ (&oldStudio,
+ *di));
+ }
+
+ oldStudio.setMIDIThruFilter(newStudio.getMIDIThruFilter());
+ oldStudio.setMIDIRecordFilter(newStudio.getMIDIRecordFilter());
+
+ m_doc->getCommandHistory()->addCommand(command);
+ m_doc->syncDevices();
+ m_doc->initialiseStudio(); // The other document will have reset it
+ }
+
+ delete doc;
+}
+
+void
+RosegardenGUIApp::slotResetMidiNetwork()
+{
+ if (m_seqManager) {
+
+ m_seqManager->preparePlayback(true);
+
+ m_seqManager->resetMidiNetwork();
+ }
+
+}
+
+void
+RosegardenGUIApp::slotModifyMIDIFilters()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotModifyMIDIFilters" << endl;
+
+ MidiFilterDialog dialog(this, m_doc);
+
+ if (dialog.exec() == QDialog::Accepted) {
+ RG_DEBUG << "slotModifyMIDIFilters - accepted" << endl;
+ }
+}
+
+void
+RosegardenGUIApp::slotManageMetronome()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotManageMetronome" << endl;
+
+ ManageMetronomeDialog dialog(this, m_doc);
+
+ if (dialog.exec() == QDialog::Accepted) {
+ RG_DEBUG << "slotManageMetronome - accepted" << endl;
+ }
+}
+
+void
+RosegardenGUIApp::slotAutoSave()
+{
+ if (!m_seqManager ||
+ m_seqManager->getTransportStatus() == PLAYING ||
+ m_seqManager->getTransportStatus() == RECORDING)
+ return ;
+
+ KConfig* config = kapp->config();
+ config->setGroup(GeneralOptionsConfigGroup);
+ if (!config->readBoolEntry("autosave", true))
+ return ;
+
+ m_doc->slotAutoSave();
+}
+
+void
+RosegardenGUIApp::slotUpdateAutoSaveInterval(unsigned int interval)
+{
+ RG_DEBUG << "RosegardenGUIApp::slotUpdateAutoSaveInterval - "
+ << "changed interval to " << interval << endl;
+ m_autoSaveTimer->changeInterval(int(interval) * 1000);
+}
+
+void
+RosegardenGUIApp::slotUpdateSidebarStyle(unsigned int style)
+{
+ RG_DEBUG << "RosegardenGUIApp::slotUpdateSidebarStyle - "
+ << "changed style to " << style << endl;
+ m_parameterArea->setArrangement((RosegardenParameterArea::Arrangement) style);
+}
+
+void
+RosegardenGUIApp::slotShowTip()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotShowTip" << endl;
+ KTipDialog::showTip(this, locate("data", "rosegarden/tips"), true);
+}
+
+void RosegardenGUIApp::slotShowToolHelp(const QString &s)
+{
+ QString msg = s;
+ if (msg != "") msg = " " + msg;
+ slotStatusMsg(msg);
+}
+
+void
+RosegardenGUIApp::slotEnableMIDIThruRouting()
+{
+ m_seqManager->enableMIDIThruRouting(m_enableMIDIrouting->isChecked());
+}
+
+TransportDialog* RosegardenGUIApp::getTransport()
+{
+ if (m_transport == 0)
+ createAndSetupTransport();
+
+ return m_transport;
+}
+
+RosegardenGUIDoc *RosegardenGUIApp::getDocument() const
+{
+ return m_doc;
+}
+
+void
+RosegardenGUIApp::awaitDialogClearance()
+{
+ bool haveDialog = true;
+
+ std::cerr << "RosegardenGUIApp::awaitDialogClearance: entering" << std::endl;
+
+ while (haveDialog) {
+
+ const QObjectList *c = children();
+ if (!c) return;
+
+ haveDialog = false;
+ for (QObjectList::const_iterator i = c->begin(); i != c->end(); ++i) {
+ QDialog *dialog = dynamic_cast<QDialog *>(*i);
+ if (dialog && dialog->isVisible()) {
+ haveDialog = true;
+ break;
+ }
+ }
+
+// std::cerr << "RosegardenGUIApp::awaitDialogClearance: have dialog = "
+// << haveDialog << std::endl;
+
+ if (haveDialog) kapp->processEvents();
+ }
+
+ std::cerr << "RosegardenGUIApp::awaitDialogClearance: exiting" << std::endl;
+}
+
+void
+RosegardenGUIApp::slotNewerVersionAvailable(QString v)
+{
+ if (m_firstRun) return;
+ KStartupLogo::hideIfStillThere();
+ CurrentProgressDialog::freeze();
+ awaitDialogClearance();
+ KMessageBox::information
+ (this,
+ i18n("<h3>Newer version available</h3><p>A newer version of Rosegarden may be available.<br>Please consult the <a href=\"http://www.rosegardenmusic.com/getting/\">Rosegarden website</a> for more information.</p>"),
+ i18n("Newer version available"),
+ QString("version-%1-available-show").arg(v),
+ KMessageBox::AllowLink);
+ CurrentProgressDialog::thaw();
+}
+
+void
+RosegardenGUIApp::slotSetQuickMarker()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotSetQuickMarker" << endl;
+
+ m_doc->setQuickMarker();
+ getView()->getTrackEditor()->updateRulers();
+}
+
+void
+RosegardenGUIApp::slotJumpToQuickMarker()
+{
+ RG_DEBUG << "RosegardenGUIApp::slotJumpToQuickMarker" << endl;
+
+ m_doc->jumpToQuickMarker();
+}
+
+const void* RosegardenGUIApp::SequencerExternal = (void*)-1;
+RosegardenGUIApp *RosegardenGUIApp::m_myself = 0;
+
+}
+#include "RosegardenGUIApp.moc"