changeset 126:d615d0220828

* Add audio device selection to preferences * Add (not yet functional) insert, delete, edit buttons to data edit window * Add proper set methods for time fields in data edit window (using general sparse model base class)
author Chris Cannam
date Fri, 13 Jun 2008 21:09:43 +0000
parents e4635503a6d2
children 7ee6da3f2b3c
files audioio/AudioTargetFactory.cpp audioio/AudioTargetFactory.h framework/MainWindowBase.cpp framework/MainWindowBase.h
diffstat 4 files changed, 159 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/audioio/AudioTargetFactory.cpp	Thu Jun 12 14:33:45 2008 +0000
+++ b/audioio/AudioTargetFactory.cpp	Fri Jun 13 21:09:43 2008 +0000
@@ -20,13 +20,127 @@
 #include "AudioPortAudioTarget.h"
 #include "AudioPulseAudioTarget.h"
 
+#include <QCoreApplication>
+
 #include <iostream>
 
+AudioTargetFactory *
+AudioTargetFactory::m_instance = 0;
+
+AudioTargetFactory *
+AudioTargetFactory::getInstance()
+{
+    if (!m_instance) m_instance = new AudioTargetFactory();
+    return m_instance;
+}
+
+AudioTargetFactory::AudioTargetFactory()
+{
+}
+
+std::vector<QString>
+AudioTargetFactory::getCallbackTargetNames(bool includeAuto) const
+{
+    std::vector<QString> names;
+    if (includeAuto) names.push_back("auto");
+
+#ifdef HAVE_JACK
+    names.push_back("jack");
+#endif
+
+#ifdef HAVE_LIBPULSE
+    names.push_back("pulse");
+#endif
+
+#ifdef HAVE_COREAUDIO
+    names.push_back("core");
+#endif
+
+#ifdef HAVE_PORTAUDIO_2_0
+    names.push_back("port");
+#endif
+
+    return names;
+}
+
+QString
+AudioTargetFactory::getCallbackTargetDescription(QString name) const
+{
+    if (name == "auto") {
+        return QCoreApplication::translate("AudioTargetFactory",
+                                           "(auto)");
+    }
+    if (name == "jack") {
+        return QCoreApplication::translate("AudioTargetFactory",
+                                           "JACK Audio Connection Kit");
+    }
+    if (name == "pulse") {
+        return QCoreApplication::translate("AudioTargetFactory",
+                                           "PulseAudio Server");
+    }
+    if (name == "core") {
+        return QCoreApplication::translate("AudioTargetFactory",
+                                           "Core Audio Device");
+    }
+    if (name == "port") {
+        return QCoreApplication::translate("AudioTargetFactory",
+                                           "Default Soundcard Device");
+    }
+
+    return "(unknown)";
+}
+
+QString
+AudioTargetFactory::getDefaultCallbackTarget() const
+{
+    if (m_default == "") return "auto";
+    return m_default;
+}
+
+bool
+AudioTargetFactory::isAutoCallbackTarget(QString name) const
+{
+    return (name == "auto" || name == "");
+}
+
+void
+AudioTargetFactory::setDefaultCallbackTarget(QString target)
+{
+    m_default = target;
+}
+
 AudioCallbackPlayTarget *
 AudioTargetFactory::createCallbackTarget(AudioCallbackPlaySource *source)
 {
     AudioCallbackPlayTarget *target = 0;
 
+    if (m_default != "" && m_default != "auto") {
+
+#ifdef HAVE_JACK
+        if (m_default == "jack") target = new AudioJACKTarget(source);
+#endif
+
+#ifdef HAVE_LIBPULSE
+        if (m_default == "pulse") target = new AudioPulseAudioTarget(source);
+#endif
+
+#ifdef HAVE_COREAUDIO
+        if (m_default == "core") target = new AudioCoreAudioTarget(source);
+#endif
+
+#ifdef HAVE_PORTAUDIO_2_0
+        if (m_default == "port") target = new AudioPortAudioTarget(source);
+#endif
+
+        if (!target || !target->isOK()) {
+            std::cerr << "WARNING: AudioTargetFactory::createCallbackTarget: Failed to open the requested target (\"" << m_default.toStdString() << "\")" << std::endl;
+            delete target;
+            return 0;
+        } else {
+            return target;
+        }
+    }
+
 #ifdef HAVE_JACK
     target = new AudioJACKTarget(source);
     if (target->isOK()) return target;
@@ -53,15 +167,6 @@
 	delete target;
     }
 #endif
-
-#ifdef HAVE_DIRECTSOUND
-    target = new AudioDirectSoundTarget(source);
-    if (target->isOK()) return target;
-    else {
-	std::cerr << "WARNING: AudioTargetFactory::createCallbackTarget: Failed to open DirectSound target" << std::endl;
-	delete target;
-    }
-#endif
     
 #ifdef HAVE_PORTAUDIO_2_0
     target = new AudioPortAudioTarget(source);
--- a/audioio/AudioTargetFactory.h	Thu Jun 12 14:33:45 2008 +0000
+++ b/audioio/AudioTargetFactory.h	Fri Jun 13 21:09:43 2008 +0000
@@ -16,13 +16,29 @@
 #ifndef _AUDIO_TARGET_FACTORY_H_
 #define _AUDIO_TARGET_FACTORY_H_
 
+#include <vector>
+#include <QString>
+
 class AudioCallbackPlaySource;
 class AudioCallbackPlayTarget;
 
 class AudioTargetFactory 
 {
 public:
-    static AudioCallbackPlayTarget *createCallbackTarget(AudioCallbackPlaySource *);
+    static AudioTargetFactory *getInstance();
+
+    std::vector<QString> getCallbackTargetNames(bool includeAuto = true) const;
+    QString getCallbackTargetDescription(QString name) const;
+    QString getDefaultCallbackTarget() const;
+    bool isAutoCallbackTarget(QString name) const;
+    void setDefaultCallbackTarget(QString name);
+
+    AudioCallbackPlayTarget *createCallbackTarget(AudioCallbackPlaySource *);
+
+protected:
+    AudioTargetFactory();
+    static AudioTargetFactory *m_instance;
+    QString m_default;
 };
 
 #endif
--- a/framework/MainWindowBase.cpp	Thu Jun 12 14:33:45 2008 +0000
+++ b/framework/MainWindowBase.cpp	Fri Jun 13 21:09:43 2008 +0000
@@ -1337,13 +1337,30 @@
 {
     if (m_playTarget) return;
 
-    m_playTarget = AudioTargetFactory::createCallbackTarget(m_playSource);
+    QSettings settings;
+    settings.beginGroup("Preferences");
+    QString targetName = settings.value("audio-target", "").toString();
+    settings.endGroup();
+
+    AudioTargetFactory *factory = AudioTargetFactory::getInstance();
+
+    factory->setDefaultCallbackTarget(targetName);
+    m_playTarget = factory->createCallbackTarget(m_playSource);
+
     if (!m_playTarget) {
         emit hideSplash();
-	QMessageBox::warning
+
+        if (factory->isAutoCallbackTarget(targetName)) {
 	    (this, tr("Couldn't open audio device"),
-	     tr("<b>No audio available</b><p>Could not open an audio device for playback.<p>Audio playback will not be available during this session."),
+	     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>"),
 	     QMessageBox::Ok);
+        } else {
+            QMessageBox::warning
+                (this, tr("Couldn't open audio device"),
+                 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>")
+                 .arg(factory->getCallbackTargetDescription(targetName)),
+                 QMessageBox::Ok);
+        }
     }
 }
 
@@ -1945,14 +1962,17 @@
     }
 
     if (m_layerDataDialogMap.find(layer) != m_layerDataDialogMap.end()) {
-        m_layerDataDialogMap[layer]->show();
-        m_layerDataDialogMap[layer]->raise();
-        return;
+        if (!m_layerDataDialogMap[layer].isNull()) {
+            m_layerDataDialogMap[layer]->show();
+            m_layerDataDialogMap[layer]->raise();
+            return;
+        }
     }
 
     QString title = layer->getLayerPresentationName();
 
     ModelDataTableDialog *dialog = new ModelDataTableDialog(tabular, title, this);
+    dialog->setAttribute(Qt::WA_DeleteOnClose); // see below
 
     connect(m_viewManager,
             SIGNAL(globalCentreFrameChanged(unsigned long)),
--- a/framework/MainWindowBase.h	Thu Jun 12 14:33:45 2008 +0000
+++ b/framework/MainWindowBase.h	Fri Jun 13 21:09:43 2008 +0000
@@ -300,8 +300,8 @@
     Pane *addPaneToStack();
     Layer *getSnapLayer() const;
 
-    typedef std::map<Layer *, ModelDataTableDialog *> LayerDataDialogMap;
-    typedef std::set<ModelDataTableDialog *> DataDialogSet;
+    typedef std::map<Layer *, QPointer<ModelDataTableDialog> > LayerDataDialogMap;
+    typedef std::set<QPointer<ModelDataTableDialog> > DataDialogSet;
     typedef std::map<View *, DataDialogSet> ViewDataDialogMap;
 
     LayerDataDialogMap m_layerDataDialogMap;