comparison framework/MainWindowBase.cpp @ 515:51befd6165a3 alignment-simple

Merge in from SV 3.0-integration branches
author Chris Cannam
date Wed, 02 Mar 2016 17:25:27 +0000
parents 74d575708e06 68ab0fe3bce4
children b926f08909b8
comparison
equal deleted inserted replaced
459:74d575708e06 515:51befd6165a3
14 */ 14 */
15 15
16 #include "MainWindowBase.h" 16 #include "MainWindowBase.h"
17 #include "Document.h" 17 #include "Document.h"
18 18
19
20 #include "view/Pane.h" 19 #include "view/Pane.h"
21 #include "view/PaneStack.h" 20 #include "view/PaneStack.h"
22 #include "data/model/WaveFileModel.h" 21 #include "data/model/ReadOnlyWaveFileModel.h"
22 #include "data/model/WritableWaveFileModel.h"
23 #include "data/model/SparseOneDimensionalModel.h" 23 #include "data/model/SparseOneDimensionalModel.h"
24 #include "data/model/NoteModel.h" 24 #include "data/model/NoteModel.h"
25 #include "data/model/FlexiNoteModel.h" 25 #include "data/model/FlexiNoteModel.h"
26 #include "data/model/Labeller.h" 26 #include "data/model/Labeller.h"
27 #include "data/model/TabularModel.h" 27 #include "data/model/TabularModel.h"
45 #include "widgets/MIDIFileImportDialog.h" 45 #include "widgets/MIDIFileImportDialog.h"
46 #include "widgets/CSVFormatDialog.h" 46 #include "widgets/CSVFormatDialog.h"
47 #include "widgets/ModelDataTableDialog.h" 47 #include "widgets/ModelDataTableDialog.h"
48 #include "widgets/InteractiveFileFinder.h" 48 #include "widgets/InteractiveFileFinder.h"
49 49
50 #include "audioio/AudioCallbackPlaySource.h" 50 #include "audio/AudioCallbackPlaySource.h"
51 #include "audioio/AudioCallbackPlayTarget.h" 51 #include "audio/AudioRecordTarget.h"
52 #include "audioio/AudioTargetFactory.h" 52 #include "audio/PlaySpeedRangeMapper.h"
53 #include "audioio/PlaySpeedRangeMapper.h" 53
54 #include "data/fileio/DataFileReaderFactory.h" 54 #include "data/fileio/DataFileReaderFactory.h"
55 #include "data/fileio/PlaylistFileReader.h" 55 #include "data/fileio/PlaylistFileReader.h"
56 #include "data/fileio/WavFileWriter.h" 56 #include "data/fileio/WavFileWriter.h"
57 #include "data/fileio/MIDIFileWriter.h" 57 #include "data/fileio/MIDIFileWriter.h"
58 #include "data/fileio/BZipFileDevice.h" 58 #include "data/fileio/BZipFileDevice.h"
70 #include "base/Exceptions.h" 70 #include "base/Exceptions.h"
71 #include "base/ResourceFinder.h" 71 #include "base/ResourceFinder.h"
72 72
73 #include "data/osc/OSCQueue.h" 73 #include "data/osc/OSCQueue.h"
74 #include "data/midi/MIDIInput.h" 74 #include "data/midi/MIDIInput.h"
75
76 #include <bqaudioio/SystemPlaybackTarget.h>
77 #include <bqaudioio/SystemAudioIO.h>
78 #include <bqaudioio/AudioFactory.h>
75 79
76 #include <QApplication> 80 #include <QApplication>
77 #include <QMessageBox> 81 #include <QMessageBox>
78 #include <QGridLayout> 82 #include <QGridLayout>
79 #include <QLabel> 83 #include <QLabel>
127 return 0; 131 return 0;
128 } 132 }
129 #undef Window 133 #undef Window
130 #endif 134 #endif
131 135
132 MainWindowBase::MainWindowBase(bool withAudioOutput, 136 MainWindowBase::MainWindowBase(SoundOptions options) :
133 bool withMIDIInput) :
134 m_document(0), 137 m_document(0),
135 m_paneStack(0), 138 m_paneStack(0),
136 m_viewManager(0), 139 m_viewManager(0),
137 m_timeRulerLayer(0), 140 m_timeRulerLayer(0),
138 m_audioOutput(withAudioOutput), 141 m_soundOptions(options),
139 m_playSource(0), 142 m_playSource(0),
143 m_recordTarget(0),
140 m_playTarget(0), 144 m_playTarget(0),
145 m_audioIO(0),
141 m_oscQueue(0), 146 m_oscQueue(0),
142 m_oscQueueStarter(0), 147 m_oscQueueStarter(0),
143 m_midiInput(0), 148 m_midiInput(0),
144 m_recentFiles("RecentFiles", 20), 149 m_recentFiles("RecentFiles", 20),
145 m_recentTransforms("RecentTransforms", 20), 150 m_recentTransforms("RecentTransforms", 20),
148 m_abandoning(false), 153 m_abandoning(false),
149 m_labeller(0), 154 m_labeller(0),
150 m_lastPlayStatusSec(0), 155 m_lastPlayStatusSec(0),
151 m_initialDarkBackground(false), 156 m_initialDarkBackground(false),
152 m_defaultFfwdRwdStep(2, 0), 157 m_defaultFfwdRwdStep(2, 0),
158 m_audioRecordMode(RecordCreateAdditionalModel),
153 m_statusLabel(0), 159 m_statusLabel(0),
154 m_iconsVisibleInMenus(true), 160 m_iconsVisibleInMenus(true),
155 m_menuShortcutMapper(0) 161 m_menuShortcutMapper(0)
156 { 162 {
157 Profiler profiler("MainWindowBase::MainWindowBase"); 163 Profiler profiler("MainWindowBase::MainWindowBase");
158 164
165 if (options & WithAudioInput) {
166 if (!(options & WithAudioOutput)) {
167 cerr << "WARNING: MainWindowBase: WithAudioInput requires WithAudioOutput -- recording will not work" << endl;
168 }
169 }
170
159 qRegisterMetaType<sv_frame_t>("sv_frame_t"); 171 qRegisterMetaType<sv_frame_t>("sv_frame_t");
160 qRegisterMetaType<sv_samplerate_t>("sv_samplerate_t"); 172 qRegisterMetaType<sv_samplerate_t>("sv_samplerate_t");
161 173
162 #ifdef Q_WS_X11 174 #ifdef Q_WS_X11
163 XSetErrorHandler(handle_x11_error); 175 XSetErrorHandler(handle_x11_error);
183 settings.beginGroup("Preferences"); 195 settings.beginGroup("Preferences");
184 viewFontSize = settings.value("view-font-size", viewFontSize).toInt(); 196 viewFontSize = settings.value("view-font-size", viewFontSize).toInt();
185 settings.setValue("view-font-size", viewFontSize); 197 settings.setValue("view-font-size", viewFontSize);
186 settings.endGroup(); 198 settings.endGroup();
187 199
200 #ifdef NOT_DEFINED // This no longer works correctly on any platform AFAICS
188 Preferences::BackgroundMode mode = 201 Preferences::BackgroundMode mode =
189 Preferences::getInstance()->getBackgroundMode(); 202 Preferences::getInstance()->getBackgroundMode();
190 m_initialDarkBackground = m_viewManager->getGlobalDarkBackground(); 203 m_initialDarkBackground = m_viewManager->getGlobalDarkBackground();
191 if (mode != Preferences::BackgroundFromTheme) { 204 if (mode != Preferences::BackgroundFromTheme) {
192 m_viewManager->setGlobalDarkBackground 205 m_viewManager->setGlobalDarkBackground
193 (mode == Preferences::DarkBackground); 206 (mode == Preferences::DarkBackground);
194 } 207 }
208 #endif
195 209
196 m_paneStack = new PaneStack(0, m_viewManager); 210 m_paneStack = new PaneStack(0, m_viewManager);
197 connect(m_paneStack, SIGNAL(currentPaneChanged(Pane *)), 211 connect(m_paneStack, SIGNAL(currentPaneChanged(Pane *)),
198 this, SLOT(currentPaneChanged(Pane *))); 212 this, SLOT(currentPaneChanged(Pane *)));
199 connect(m_paneStack, SIGNAL(currentLayerChanged(Pane *, Layer *)), 213 connect(m_paneStack, SIGNAL(currentLayerChanged(Pane *, Layer *)),
215 connect(m_paneStack, SIGNAL(paneDeleteButtonClicked(Pane *)), 229 connect(m_paneStack, SIGNAL(paneDeleteButtonClicked(Pane *)),
216 this, SLOT(paneDeleteButtonClicked(Pane *))); 230 this, SLOT(paneDeleteButtonClicked(Pane *)));
217 231
218 m_playSource = new AudioCallbackPlaySource(m_viewManager, 232 m_playSource = new AudioCallbackPlaySource(m_viewManager,
219 QApplication::applicationName()); 233 QApplication::applicationName());
234 if (m_soundOptions & WithAudioInput) {
235 m_recordTarget = new AudioRecordTarget(m_viewManager,
236 QApplication::applicationName());
237 connect(m_recordTarget, SIGNAL(recordDurationChanged(sv_frame_t, sv_samplerate_t)),
238 this, SLOT(recordDurationChanged(sv_frame_t, sv_samplerate_t)));
239 }
220 240
221 connect(m_playSource, SIGNAL(sampleRateMismatch(sv_samplerate_t, sv_samplerate_t, bool)), 241 connect(m_playSource, SIGNAL(sampleRateMismatch(sv_samplerate_t, sv_samplerate_t, bool)),
222 this, SLOT(sampleRateMismatch(sv_samplerate_t, sv_samplerate_t, bool))); 242 this, SLOT(sampleRateMismatch(sv_samplerate_t, sv_samplerate_t, bool)));
223 connect(m_playSource, SIGNAL(audioOverloadPluginDisabled()), 243 connect(m_playSource, SIGNAL(audioOverloadPluginDisabled()),
224 this, SLOT(audioOverloadPluginDisabled())); 244 this, SLOT(audioOverloadPluginDisabled()));
255 settings.endGroup(); 275 settings.endGroup();
256 276
257 m_labeller = new Labeller(labellerType); 277 m_labeller = new Labeller(labellerType);
258 m_labeller->setCounterCycleSize(cycle); 278 m_labeller->setCounterCycleSize(cycle);
259 279
260 if (withMIDIInput) { 280 if (m_soundOptions & WithMIDIInput) {
261 m_midiInput = new MIDIInput(QApplication::applicationName(), this); 281 m_midiInput = new MIDIInput(QApplication::applicationName(), this);
262 } 282 }
263 283
264 QTimer::singleShot(1500, this, SIGNAL(hideSplash())); 284 QTimer::singleShot(1500, this, SIGNAL(hideSplash()));
265 } 285 }
266 286
267 MainWindowBase::~MainWindowBase() 287 MainWindowBase::~MainWindowBase()
268 { 288 {
269 SVDEBUG << "MainWindowBase::~MainWindowBase" << endl; 289 SVDEBUG << "MainWindowBase::~MainWindowBase" << endl;
270 if (m_playTarget) m_playTarget->shutdown(); 290 delete m_playTarget;
271 // delete m_playTarget;
272 delete m_playSource; 291 delete m_playSource;
292 delete m_audioIO;
293 delete m_recordTarget;
273 delete m_viewManager; 294 delete m_viewManager;
274 delete m_oscQueue; 295 delete m_oscQueue;
275 delete m_oscQueueStarter; 296 delete m_oscQueueStarter;
276 delete m_midiInput; 297 delete m_midiInput;
277 Profiles::getInstance()->dump(); 298 Profiles::getInstance()->dump();
549 (haveCurrentPane && 570 (haveCurrentPane &&
550 (currentLayer != 0)); 571 (currentLayer != 0));
551 bool haveMainModel = 572 bool haveMainModel =
552 (getMainModel() != 0); 573 (getMainModel() != 0);
553 bool havePlayTarget = 574 bool havePlayTarget =
554 (m_playTarget != 0); 575 (m_playTarget != 0 || m_audioIO != 0);
555 bool haveSelection = 576 bool haveSelection =
556 (m_viewManager && 577 (m_viewManager &&
557 !m_viewManager->getSelections().empty()); 578 !m_viewManager->getSelections().empty());
558 bool haveCurrentEditableLayer = 579 bool haveCurrentEditableLayer =
559 (haveCurrentLayer && 580 (haveCurrentLayer &&
594 emit canEditLayer(haveCurrentEditableLayer); 615 emit canEditLayer(haveCurrentEditableLayer);
595 emit canEditLayerTabular(haveCurrentEditableLayer || haveTabularLayer); 616 emit canEditLayerTabular(haveCurrentEditableLayer || haveTabularLayer);
596 emit canMeasureLayer(haveCurrentLayer); 617 emit canMeasureLayer(haveCurrentLayer);
597 emit canSelect(haveMainModel && haveCurrentPane); 618 emit canSelect(haveMainModel && haveCurrentPane);
598 emit canPlay(haveMainModel && havePlayTarget); 619 emit canPlay(haveMainModel && havePlayTarget);
620 emit canRecord(m_recordTarget != 0);
599 emit canFfwd(haveMainModel); 621 emit canFfwd(haveMainModel);
600 emit canRewind(haveMainModel); 622 emit canRewind(haveMainModel);
601 emit canPaste(haveClipboardContents); 623 emit canPaste(haveClipboardContents);
602 emit canInsertInstant(haveCurrentPane); 624 emit canInsertInstant(haveCurrentPane);
603 emit canInsertInstantsAtBoundaries(haveCurrentPane && haveSelection); 625 emit canInsertInstantsAtBoundaries(haveCurrentPane && haveSelection);
1310 rate = Preferences::getInstance()->getFixedSampleRate(); 1332 rate = Preferences::getInstance()->getFixedSampleRate();
1311 } else if (Preferences::getInstance()->getResampleOnLoad()) { 1333 } else if (Preferences::getInstance()->getResampleOnLoad()) {
1312 rate = m_playSource->getSourceSampleRate(); 1334 rate = m_playSource->getSourceSampleRate();
1313 } 1335 }
1314 1336
1315 WaveFileModel *newModel = new WaveFileModel(source, rate); 1337 ReadOnlyWaveFileModel *newModel = new ReadOnlyWaveFileModel(source, rate);
1316 1338
1317 if (!newModel->isOK()) { 1339 if (!newModel->isOK()) {
1318 delete newModel; 1340 delete newModel;
1319 m_openingAudioFile = false; 1341 m_openingAudioFile = false;
1320 if (source.wasCancelled()) { 1342 if (source.wasCancelled()) {
2202 m_recentFiles.addFile(source.getLocation()); 2224 m_recentFiles.addFile(source.getLocation());
2203 return FileOpenSucceeded; 2225 return FileOpenSucceeded;
2204 } 2226 }
2205 2227
2206 void 2228 void
2207 MainWindowBase::createPlayTarget() 2229 MainWindowBase::createAudioIO()
2208 { 2230 {
2209 if (m_playTarget) return; 2231 if (m_playTarget || m_audioIO) return;
2210 2232
2233 if (!(m_soundOptions & WithAudioOutput)) return;
2234
2235 //!!! how to handle preferences
2236 /*
2211 QSettings settings; 2237 QSettings settings;
2212 settings.beginGroup("Preferences"); 2238 settings.beginGroup("Preferences");
2213 QString targetName = settings.value("audio-target", "").toString(); 2239 QString targetName = settings.value("audio-target", "").toString();
2214 settings.endGroup(); 2240 settings.endGroup();
2215
2216 AudioTargetFactory *factory = AudioTargetFactory::getInstance(); 2241 AudioTargetFactory *factory = AudioTargetFactory::getInstance();
2217 2242
2218 factory->setDefaultCallbackTarget(targetName); 2243 factory->setDefaultCallbackTarget(targetName);
2219 m_playTarget = factory->createCallbackTarget(m_playSource); 2244 */
2220 2245
2221 if (!m_playTarget) { 2246 if (m_soundOptions & WithAudioInput) {
2247 m_audioIO = breakfastquay::AudioFactory::
2248 createCallbackIO(m_recordTarget, m_playSource);
2249 m_audioIO->suspend(); // start in suspended state
2250 m_playSource->setSystemPlaybackTarget(m_audioIO);
2251 } else {
2252 m_playTarget = breakfastquay::AudioFactory::
2253 createCallbackPlayTarget(m_playSource);
2254 m_playTarget->suspend(); // start in suspended state
2255 m_playSource->setSystemPlaybackTarget(m_playTarget);
2256 }
2257
2258 if (!m_playTarget && !m_audioIO) {
2222 emit hideSplash(); 2259 emit hideSplash();
2223 2260
2224 if (factory->isAutoCallbackTarget(targetName)) { 2261 // if (factory->isAutoCallbackTarget(targetName)) {
2225 QMessageBox::warning 2262 QMessageBox::warning
2226 (this, tr("Couldn't open audio device"), 2263 (this, tr("Couldn't open audio device"),
2227 tr("<b>No audio available</b><p>Could not open an audio device for playback.<p>Automatic audio device detection failed. Audio playback will not be available during this session.</p>"), 2264 tr("<b>No audio available</b><p>Could not open an audio device for playback.<p>Automatic audio device detection failed. Audio playback will not be available during this session.</p>"),
2228 QMessageBox::Ok); 2265 QMessageBox::Ok);
2266 /*
2229 } else { 2267 } else {
2230 QMessageBox::warning 2268 QMessageBox::warning
2231 (this, tr("Couldn't open audio device"), 2269 (this, tr("Couldn't open audio device"),
2232 tr("<b>No audio available</b><p>Failed to open your preferred audio device (\"%1\").<p>Audio playback will not be available during this session.</p>") 2270 tr("<b>No audio available</b><p>Failed to open your preferred audio device (\"%1\").<p>Audio playback will not be available during this session.</p>")
2233 .arg(factory->getCallbackTargetDescription(targetName)), 2271 .arg(factory->getCallbackTargetDescription(targetName)),
2234 QMessageBox::Ok); 2272 QMessageBox::Ok);
2235 } 2273 }
2274 */
2275 return;
2236 } 2276 }
2237 } 2277 }
2238 2278
2239 WaveFileModel * 2279 WaveFileModel *
2240 MainWindowBase::getMainModel() 2280 MainWindowBase::getMainModel()
2664 } 2704 }
2665 2705
2666 void 2706 void
2667 MainWindowBase::play() 2707 MainWindowBase::play()
2668 { 2708 {
2669 if (m_playSource->isPlaying()) { 2709 if (m_recordTarget->isRecording() || m_playSource->isPlaying()) {
2670 stop(); 2710 stop();
2711 QAction *action = qobject_cast<QAction *>(sender());
2712 if (action) action->setChecked(false);
2671 } else { 2713 } else {
2714 if (m_audioIO) m_audioIO->resume();
2715 else if (m_playTarget) m_playTarget->resume();
2672 playbackFrameChanged(m_viewManager->getPlaybackFrame()); 2716 playbackFrameChanged(m_viewManager->getPlaybackFrame());
2673 m_playSource->play(m_viewManager->getPlaybackFrame()); 2717 m_playSource->play(m_viewManager->getPlaybackFrame());
2674 } 2718 }
2719 }
2720
2721 void
2722 MainWindowBase::record()
2723 {
2724 if (!(m_soundOptions & WithAudioInput)) {
2725 return;
2726 }
2727
2728 if (!m_recordTarget) {
2729 //!!! report
2730 return;
2731 }
2732
2733 if (!m_audioIO) {
2734 createAudioIO();
2735 }
2736
2737 if (!m_audioIO) {
2738 //!!! report
2739 return;
2740 }
2741
2742 if (m_recordTarget->isRecording()) {
2743 stop();
2744 return;
2745 }
2746
2747 QAction *action = qobject_cast<QAction *>(sender());
2748
2749 if (m_audioRecordMode == RecordReplaceSession) {
2750 if (!checkSaveModified()) {
2751 if (action) action->setChecked(false);
2752 return;
2753 }
2754 }
2755
2756 m_audioIO->resume();
2757
2758 WritableWaveFileModel *model = m_recordTarget->startRecording();
2759 if (!model) {
2760 cerr << "ERROR: MainWindowBase::record: Recording failed" << endl;
2761 //!!! report
2762 if (action) action->setChecked(false);
2763 return;
2764 }
2765
2766 if (!model->isOK()) {
2767 m_recordTarget->stopRecording();
2768 m_audioIO->suspend();
2769 delete model;
2770 return;
2771 }
2772
2773 PlayParameterRepository::getInstance()->addPlayable(model);
2774
2775 if (m_audioRecordMode == RecordReplaceSession || !getMainModel()) {
2776
2777 //!!! duplication with openAudio here
2778
2779 QString templateName = getDefaultSessionTemplate();
2780 bool loadedTemplate = false;
2781
2782 if (templateName != "") {
2783 FileOpenStatus tplStatus = openSessionTemplate(templateName);
2784 if (tplStatus == FileOpenCancelled) {
2785 m_recordTarget->stopRecording();
2786 m_audioIO->suspend();
2787 PlayParameterRepository::getInstance()->removePlayable(model);
2788 return;
2789 }
2790 if (tplStatus != FileOpenFailed) {
2791 loadedTemplate = true;
2792 }
2793 }
2794
2795 if (!loadedTemplate) {
2796 closeSession();
2797 createDocument();
2798 }
2799
2800 Model *prevMain = getMainModel();
2801 if (prevMain) {
2802 m_playSource->removeModel(prevMain);
2803 PlayParameterRepository::getInstance()->removePlayable(prevMain);
2804 }
2805
2806 m_document->setMainModel(model);
2807 setupMenus();
2808
2809 if (loadedTemplate || (m_sessionFile == "")) {
2810 //!!! shouldn't be dealing directly with title from here -- call a method
2811 setWindowTitle(tr("%1: %2")
2812 .arg(QApplication::applicationName())
2813 .arg(model->getLocation()));
2814 CommandHistory::getInstance()->clear();
2815 CommandHistory::getInstance()->documentSaved();
2816 m_documentModified = false;
2817 } else {
2818 setWindowTitle(tr("%1: %2 [%3]")
2819 .arg(QApplication::applicationName())
2820 .arg(QFileInfo(m_sessionFile).fileName())
2821 .arg(model->getLocation()));
2822 if (m_documentModified) {
2823 m_documentModified = false;
2824 documentModified(); // so as to restore "(modified)" window title
2825 }
2826 }
2827
2828 } else {
2829
2830 CommandHistory::getInstance()->startCompoundOperation
2831 (tr("Import Recorded Audio"), true);
2832
2833 m_document->addImportedModel(model);
2834
2835 AddPaneCommand *command = new AddPaneCommand(this);
2836 CommandHistory::getInstance()->addCommand(command);
2837
2838 Pane *pane = command->getPane();
2839
2840 if (m_timeRulerLayer) {
2841 m_document->addLayerToView(pane, m_timeRulerLayer);
2842 }
2843
2844 Layer *newLayer = m_document->createImportedLayer(model);
2845
2846 if (newLayer) {
2847 m_document->addLayerToView(pane, newLayer);
2848 }
2849
2850 CommandHistory::getInstance()->endCompoundOperation();
2851 }
2852
2853 updateMenuStates();
2854 m_recentFiles.addFile(model->getLocation());
2855 currentPaneChanged(m_paneStack->getCurrentPane());
2856
2857 emit audioFileLoaded();
2675 } 2858 }
2676 2859
2677 void 2860 void
2678 MainWindowBase::ffwd() 2861 MainWindowBase::ffwd()
2679 { 2862 {
2900 } 3083 }
2901 3084
2902 void 3085 void
2903 MainWindowBase::stop() 3086 MainWindowBase::stop()
2904 { 3087 {
3088 if (m_recordTarget->isRecording()) {
3089 m_recordTarget->stopRecording();
3090 }
3091
2905 m_playSource->stop(); 3092 m_playSource->stop();
2906 3093
3094 if (m_audioIO) m_audioIO->suspend();
3095 else if (m_playTarget) m_playTarget->suspend();
3096
2907 if (m_paneStack && m_paneStack->getCurrentPane()) { 3097 if (m_paneStack && m_paneStack->getCurrentPane()) {
2908 updateVisibleRangeDisplay(m_paneStack->getCurrentPane()); 3098 updateVisibleRangeDisplay(m_paneStack->getCurrentPane());
2909 } else { 3099 } else {
2910 m_myStatusMessage = ""; 3100 m_myStatusMessage = "";
2911 getStatusLabel()->setText(""); 3101 getStatusLabel()->setText("");
3235 remainingStr = (then - now).toText(true).c_str(); 3425 remainingStr = (then - now).toText(true).c_str();
3236 } 3426 }
3237 3427
3238 m_myStatusMessage = tr("Playing: %1 of %2 (%3 remaining)") 3428 m_myStatusMessage = tr("Playing: %1 of %2 (%3 remaining)")
3239 .arg(nowStr).arg(thenStr).arg(remainingStr); 3429 .arg(nowStr).arg(thenStr).arg(remainingStr);
3430
3431 getStatusLabel()->setText(m_myStatusMessage);
3432 }
3433
3434 void
3435 MainWindowBase::recordDurationChanged(sv_frame_t frame, sv_samplerate_t rate)
3436 {
3437 RealTime duration = RealTime::frame2RealTime(frame, rate);
3438 QString durStr = duration.toSecText().c_str();
3439
3440 m_myStatusMessage = tr("Recording: %1").arg(durStr);
3240 3441
3241 getStatusLabel()->setText(m_myStatusMessage); 3442 getStatusLabel()->setText(m_myStatusMessage);
3242 } 3443 }
3243 3444
3244 void 3445 void
3370 MainWindowBase::mainModelChanged(WaveFileModel *model) 3571 MainWindowBase::mainModelChanged(WaveFileModel *model)
3371 { 3572 {
3372 // SVDEBUG << "MainWindowBase::mainModelChanged(" << model << ")" << endl; 3573 // SVDEBUG << "MainWindowBase::mainModelChanged(" << model << ")" << endl;
3373 updateDescriptionLabel(); 3574 updateDescriptionLabel();
3374 if (model) m_viewManager->setMainModelSampleRate(model->getSampleRate()); 3575 if (model) m_viewManager->setMainModelSampleRate(model->getSampleRate());
3375 if (model && !m_playTarget && m_audioOutput) { 3576 if (model && !(m_playTarget || m_audioIO) &&
3376 createPlayTarget(); 3577 (m_soundOptions & WithAudioOutput)) {
3578 createAudioIO();
3377 } 3579 }
3378 } 3580 }
3379 3581
3380 void 3582 void
3381 MainWindowBase::modelAboutToBeDeleted(Model *model) 3583 MainWindowBase::modelAboutToBeDeleted(Model *model)
3506 } 3708 }
3507 #endif 3709 #endif
3508 #endif 3710 #endif
3509 } 3711 }
3510 3712
3511 3713 void
3714 MainWindowBase::openLocalFolder(QString path)
3715 {
3716 QDir d(path);
3717 if (d.exists()) {
3718 QStringList args;
3719 QString path = d.canonicalPath();
3720 #if defined Q_OS_WIN32
3721 // Although the Win32 API is quite happy to have
3722 // forward slashes as directory separators, Windows
3723 // Explorer is not
3724 path = path.replace('/', '\\');
3725 args << path;
3726 QProcess::execute("c:/windows/explorer.exe", args);
3727 #else
3728 args << path;
3729 QProcess::execute(
3730 #if defined Q_OS_MAC
3731 "/usr/bin/open",
3732 #else
3733 "/usr/bin/xdg-open",
3734 #endif
3735 args);
3736 #endif
3737 }
3738 }
3739