changeset 29:8460b3bf8f04

* Implement play mute, level and pan controls and a layer visibility control * Handle swapping the buffers in AudioCallbackPlaySource more gracefully, so that in many cases it can be done inaudibly. Still gets it wrong when playing in a noncontiguous selection. * Fix to SV file save for non-2d sparse models * Fixes to LED button drawing and AudioDial mouse functionality * Add progress bar for Ogg file import * Reshuffle PropertyContainer and its subclasses so it can be a QObject * Add layer dormancy (invisible layer permitted to free its cache space) * Optimisations to SpectrogramLayer, removing locks when reading/writing individual pixels in the cache (should be unnecessary there) -- there's still an issue here as we need a lock when reading from the model in case the model is replaced, and we don't currently have one * Several munlock() calls to make it harder to exhaust real memory if running in an RT mode with mlockall() active
author Chris Cannam
date Fri, 17 Feb 2006 18:04:26 +0000
parents 4b16526b011b
children a6ef94ecbe74
files base/Layer.cpp base/Layer.h base/PlayParameterRepository.cpp base/PlayParameterRepository.h base/PlayParameters.cpp base/PlayParameters.h base/PropertyContainer.h base/System.h base/View.cpp base/View.h
diffstat 10 files changed, 174 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/base/Layer.cpp	Wed Feb 15 17:58:35 2006 +0000
+++ b/base/Layer.cpp	Fri Feb 17 18:04:26 2006 +0000
@@ -15,7 +15,8 @@
 #include "layer/LayerFactory.h" //!!! shouldn't be including this here -- does that suggest we need to move this into layer/ ?
 #include "PlayParameterRepository.h"
 
-Layer::Layer(View *w)
+Layer::Layer(View *w) :
+    m_dormant(false)
 {
     m_view = w;
 
@@ -75,8 +76,9 @@
 }
 
 PlayParameters *
-Layer::getPlayParameters() const
+Layer::getPlayParameters() 
 {
+    std::cerr << "Layer (" << this << ")::getPlayParameters: model is "<< getModel() << std::endl;
     const Model *model = getModel();
     if (model) {
 	return PlayParameterRepository::instance()->getPlayParameters(model);
@@ -84,6 +86,12 @@
     return 0;
 }
 
+void
+Layer::showLayer(bool show)
+{
+    setLayerDormant(!show);
+    emit layerParametersChanged();
+}
 
 
 #ifdef INCLUDE_MOCFILES
--- a/base/Layer.h	Wed Feb 15 17:58:35 2006 +0000
+++ b/base/Layer.h	Fri Feb 17 18:04:26 2006 +0000
@@ -30,8 +30,7 @@
  * View, and may also be editable.
  */
 
-class Layer : public QObject,
-	      public PropertyContainer,
+class Layer : public PropertyContainer,
 	      public XmlExportable
 {
     Q_OBJECT
@@ -199,11 +198,21 @@
      * expected to become visible in the near future (for example
      * because the user has explicitly removed or hidden it).  The
      * layer may respond by (for example) freeing any cache memory it
-     * is using, until next time its paint method is called.
+     * is using, until next time its paint method is called.  It does
+     * not need to remember not to draw itself; the view will handle
+     * that.
      */
-    virtual void setLayerDormant() { }
+    virtual void setLayerDormant(bool dormant) { m_dormant = dormant; }
 
-    virtual PlayParameters *getPlayParameters() const;
+    /**
+     * Return whether the layer is dormant (i.e. hidden).
+     */
+    virtual bool isLayerDormant() const { return m_dormant; }
+
+    virtual PlayParameters *getPlayParameters();
+
+public slots:
+    void showLayer(bool show);
 
 signals:
     void modelChanged();
@@ -216,6 +225,7 @@
 
 protected:
     View *m_view;
+    bool m_dormant;
 };
 
 #endif
--- a/base/PlayParameterRepository.cpp	Wed Feb 15 17:58:35 2006 +0000
+++ b/base/PlayParameterRepository.cpp	Fri Feb 17 18:04:26 2006 +0000
@@ -10,6 +10,8 @@
 #include "PlayParameterRepository.h"
 #include "PlayParameters.h"
 
+#include <iostream>
+
 PlayParameterRepository *
 PlayParameterRepository::m_instance = new PlayParameterRepository;
 
@@ -28,13 +30,22 @@
 {
     if (m_playParameters.find(model) == m_playParameters.end()) {
 	// Give all models the same type of play parameters for the moment
+	std::cerr << "Creating new PlayParameters for model " << model << std::endl;
 	m_playParameters[model] = new PlayParameters;
+	connect(m_playParameters[model], SIGNAL(playParametersChanged()),
+		this, SLOT(playParametersChanged()));
     }
 
     return m_playParameters[model];
 }
 
 void
+PlayParameterRepository::playParametersChanged()
+{
+    emit playParametersChanged(dynamic_cast<PlayParameters *>(sender()));
+}
+
+void
 PlayParameterRepository::clear()
 {
     while (!m_playParameters.empty()) {
--- a/base/PlayParameterRepository.h	Wed Feb 15 17:58:35 2006 +0000
+++ b/base/PlayParameterRepository.h	Fri Feb 17 18:04:26 2006 +0000
@@ -15,8 +15,12 @@
 
 #include <map>
 
-class PlayParameterRepository
+#include <QObject>
+
+class PlayParameterRepository : public QObject
 {
+    Q_OBJECT
+
 public:
     static PlayParameterRepository *instance();
 
@@ -27,6 +31,12 @@
 
     void clear();
 
+signals:
+    void playParametersChanged(PlayParameters *);
+
+protected slots:
+    void playParametersChanged();
+
 protected:
     std::map<const Model *, PlayParameters *> m_playParameters;
 
--- a/base/PlayParameters.cpp	Wed Feb 15 17:58:35 2006 +0000
+++ b/base/PlayParameters.cpp	Fri Feb 17 18:04:26 2006 +0000
@@ -9,26 +9,37 @@
 
 #include "PlayParameters.h"
 
+#include <iostream>
+
 void
 PlayParameters::setPlayMuted(bool muted)
 {
+    std::cerr << "PlayParameters: setPlayMuted(" << muted << ")" << std::endl;
     m_playMuted = muted;
+    emit playMutedChanged(muted);
     emit playParametersChanged();
 }
 
+void
+PlayParameters::setPlayAudible(bool audible)
+{
+    std::cerr << "PlayParameters: setPlayAudible(" << audible << ")" << std::endl;
+    setPlayMuted(!audible);
+}
 
 void
 PlayParameters::setPlayPan(float pan)
 {
     m_playPan = pan;
+    emit playPanChanged(pan);
     emit playParametersChanged();
 }
 
-
 void
 PlayParameters::setPlayGain(float gain)
 {
     m_playGain = gain;
+    emit playGainChanged(gain);
     emit playParametersChanged();
 }
 
--- a/base/PlayParameters.h	Wed Feb 15 17:58:35 2006 +0000
+++ b/base/PlayParameters.h	Fri Feb 17 18:04:26 2006 +0000
@@ -12,7 +12,7 @@
 
 #include <QObject>
 
-class PlayParameters : virtual public QObject
+class PlayParameters : public QObject
 {
     Q_OBJECT
 
@@ -20,16 +20,20 @@
     PlayParameters() : m_playMuted(false), m_playPan(0.0), m_playGain(1.0) { }
 
     virtual bool isPlayMuted() const { return m_playMuted; }
-    virtual void setPlayMuted(bool muted);
-    
     virtual float getPlayPan() const { return m_playPan; } // -1.0 -> 1.0
-    virtual void setPlayPan(float pan);
-    
     virtual float getPlayGain() const { return m_playGain; }
-    virtual void setPlayGain(float gain);
 
 signals:
     void playParametersChanged();
+    void playMutedChanged(bool);
+    void playPanChanged(float);
+    void playGainChanged(float);
+
+public slots:
+    virtual void setPlayMuted(bool muted);
+    virtual void setPlayAudible(bool nonMuted);
+    virtual void setPlayPan(float pan);
+    virtual void setPlayGain(float gain);
 
 protected:
     bool m_playMuted;
--- a/base/PropertyContainer.h	Wed Feb 15 17:58:35 2006 +0000
+++ b/base/PropertyContainer.h	Fri Feb 17 18:04:26 2006 +0000
@@ -16,8 +16,10 @@
 
 class PlayParameters;
 
-class PropertyContainer
+class PropertyContainer : public QObject
 {
+    Q_OBJECT
+
 public:
     virtual ~PropertyContainer() { }
 
@@ -72,17 +74,21 @@
     virtual QString getPropertyValueLabel(const PropertyName &,
 					  int value) const;
 
+    virtual QString getPropertyContainerName() const = 0;
+    virtual QString getPropertyContainerIconName() const = 0;
+
+    virtual PlayParameters *getPlayParameters() { return 0; }
+
+signals:
+    void propertyChanged(PropertyName);
+    
+public slots:
     /**
      * Set a property.  This is used for all property types.  For
      * boolean properties, zero is false and non-zero true; for
      * colours, the integer value should be treated as a qRgb.
      */
     virtual void setProperty(const PropertyName &, int value);
-
-    virtual QString getPropertyContainerName() const = 0;
-    virtual QString getPropertyContainerIconName() const = 0;
-
-    virtual PlayParameters *getPlayParameters() const { return 0; }
 };
 
 #endif
--- a/base/System.h	Wed Feb 15 17:58:35 2006 +0000
+++ b/base/System.h	Fri Feb 17 18:04:26 2006 +0000
@@ -17,6 +17,7 @@
 
 #define MLOCK(a,b)   1
 #define MUNLOCK(a,b) 1
+#define MUNLOCK_SAMPLEBLOCK(a) 1
 
 #define DLOPEN(a,b)  LoadLibrary((a).toStdWString().c_str())
 #define DLSYM(a,b)   GetProcAddress((HINSTANCE)(a),(b))
@@ -35,7 +36,8 @@
 #include <dlfcn.h>
 
 #define MLOCK(a,b)   ::mlock((a),(b))
-#define MUNLOCK(a,b) ::munlock((a),(b))
+#define MUNLOCK(a,b) (::munlock((a),(b)) ? (::perror("munlock failed"), 0) : 0)
+#define MUNLOCK_SAMPLEBLOCK(a) do { const float &b = *(a).begin(); MUNLOCK(&b, (a).capacity() * sizeof(float)); } while(0);
 
 #define DLOPEN(a,b)  dlopen((a).toStdString().c_str(),(b))
 #define DLSYM(a,b)   dlsym((a),(b))
--- a/base/View.cpp	Wed Feb 15 17:58:35 2006 +0000
+++ b/base/View.cpp	Fri Feb 17 18:04:26 2006 +0000
@@ -44,7 +44,8 @@
     m_selectionCached(false),
     m_deleting(false),
     m_haveSelectedLayer(false),
-    m_manager(0)
+    m_manager(0),
+    m_propertyContainer(new ViewPropertyContainer(this))
 {
 //    QWidget::setAttribute(Qt::WA_PaintOnScreen);
 }
@@ -56,12 +57,14 @@
     for (LayerList::iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
 	delete *i;
     }
+
+    delete m_propertyContainer;
 }
 
 PropertyContainer::PropertyList
 View::getProperties() const
 {
-    PropertyList list;
+    PropertyContainer::PropertyList list;
     list.push_back(tr("Global Scroll"));
     list.push_back(tr("Global Zoom"));
     list.push_back(tr("Follow Playback"));
@@ -69,27 +72,33 @@
 }
 
 PropertyContainer::PropertyType
-View::getPropertyType(const PropertyName &name) const
+View::getPropertyType(const PropertyContainer::PropertyName &name) const
 {
-    if (name == tr("Global Scroll")) return ToggleProperty;
-    if (name == tr("Global Zoom")) return ToggleProperty;
-    if (name == tr("Follow Playback")) return ValueProperty;
-    return InvalidProperty;
+    if (name == tr("Global Scroll")) return PropertyContainer::ToggleProperty;
+    if (name == tr("Global Zoom")) return PropertyContainer::ToggleProperty;
+    if (name == tr("Follow Playback")) return PropertyContainer::ValueProperty;
+    return PropertyContainer::InvalidProperty;
 }
 
 int
-View::getPropertyRangeAndValue(const PropertyName &name,
-				       int *min, int *max) const
+View::getPropertyRangeAndValue(const PropertyContainer::PropertyName &name,
+			       int *min, int *max) const
 {
     if (name == tr("Global Scroll")) return m_followPan;
     if (name == tr("Global Zoom")) return m_followZoom;
-    if (name == tr("Follow Playback")) { *min = 0; *max = 2; return int(m_followPlay); }
-    return PropertyContainer::getPropertyRangeAndValue(name, min, max);
+    if (name == tr("Follow Playback")) {
+	if (min) *min = 0;
+	if (max) *max = 2;
+	return int(m_followPlay);
+    }
+    if (min) *min = 0;
+    if (max) *max = 0;
+    return 0;
 }
 
 QString
-View::getPropertyValueLabel(const PropertyName &name,
-				  int value) const
+View::getPropertyValueLabel(const PropertyContainer::PropertyName &name,
+			    int value) const
 {
     if (name == tr("Follow Playback")) {
 	switch (value) {
@@ -103,7 +112,7 @@
 }
 
 void
-View::setProperty(const PropertyName &name, int value)
+View::setProperty(const PropertyContainer::PropertyName &name, int value)
 {
     if (name == tr("Global Scroll")) {
 	setFollowGlobalPan(value != 0);
@@ -135,14 +144,14 @@
 PropertyContainer *
 View::getPropertyContainer(size_t i)
 {
-    if (i == 0) return this;
+    if (i == 0) return m_propertyContainer;
     return m_layers[i-1];
 }
 
 void
 View::propertyContainerSelected(PropertyContainer *pc)
 {
-    if (pc == this) {
+    if (pc == m_propertyContainer) {
 	if (m_haveSelectedLayer) {
 	    m_haveSelectedLayer = false;
 	    update();
@@ -380,21 +389,21 @@
 View::setFollowGlobalPan(bool f)
 {
     m_followPan = f;
-    emit propertyContainerPropertyChanged(this);
+    emit propertyContainerPropertyChanged(m_propertyContainer);
 }
 
 void
 View::setFollowGlobalZoom(bool f)
 {
     m_followZoom = f;
-    emit propertyContainerPropertyChanged(this);
+    emit propertyContainerPropertyChanged(m_propertyContainer);
 }
 
 void
 View::setPlaybackFollow(PlaybackFollowMode m)
 {
     m_followPlay = m;
-    emit propertyContainerPropertyChanged(this);
+    emit propertyContainerPropertyChanged(m_propertyContainer);
 }
 
 void
@@ -692,6 +701,7 @@
 
     LayerList scrollables;
     for (LayerList::const_iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
+	if ((*i)->isLayerDormant()) continue;
 	if ((*i)->isLayerScrollable()) scrollables.push_back(*i);
 	else {
 	    if (scrollables != m_lastScrollableBackLayers) {
@@ -730,6 +740,7 @@
 
     size_t count = 0;
     for (LayerList::const_iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
+	if ((*i)->isLayerDormant()) continue;
 	if (count < scrollables.size()) {
 	    ++count;
 	    continue;
@@ -1234,6 +1245,12 @@
     return s;
 }
 
+ViewPropertyContainer::ViewPropertyContainer(View *v) :
+    m_v(v)
+{
+    connect(m_v, SIGNAL(propertyChanged(PropertyName)),
+	    this, SIGNAL(propertyChanged(PropertyName)));
+}
 
 #ifdef INCLUDE_MOCFILES
 #include "View.moc.cpp"
--- a/base/View.h	Wed Feb 15 17:58:35 2006 +0000
+++ b/base/View.h	Fri Feb 17 18:04:26 2006 +0000
@@ -19,6 +19,7 @@
 #include "base/XmlExportable.h"
 
 class Layer;
+class ViewPropertyContainer;
 
 #include <map>
 
@@ -36,7 +37,6 @@
  */
 
 class View : public QFrame,
-	     public PropertyContainer,
 	     public XmlExportable
 {
     Q_OBJECT
@@ -159,22 +159,26 @@
     virtual void setPlaybackFollow(PlaybackFollowMode m);
     virtual PlaybackFollowMode getPlaybackFollow() const { return m_followPlay; }
 
-    virtual PropertyList getProperties() const;
-    virtual PropertyType getPropertyType(const PropertyName &) const;
-    virtual int getPropertyRangeAndValue(const PropertyName &,
-					   int *min, int *max) const;
-    virtual QString getPropertyValueLabel(const PropertyName &,
+    // We implement the PropertyContainer API, although we don't
+    // actually subclass PropertyContainer.  We have our own
+    // PropertyContainer that we can return on request that just
+    // delegates back to us.
+    virtual PropertyContainer::PropertyList getProperties() const;
+    virtual PropertyContainer::PropertyType getPropertyType(const PropertyContainer::PropertyName &) const;
+    virtual int getPropertyRangeAndValue(const PropertyContainer::PropertyName &,
+					 int *min, int *max) const;
+    virtual QString getPropertyValueLabel(const PropertyContainer::PropertyName &,
 					  int value) const;
-    virtual void setProperty(const PropertyName &, int value);
-
-    virtual size_t getPropertyContainerCount() const;
-    virtual const PropertyContainer *getPropertyContainer(size_t i) const;
-    virtual PropertyContainer *getPropertyContainer(size_t i);
-
+    virtual void setProperty(const PropertyContainer::PropertyName &, int value);
     virtual QString getPropertyContainerName() const {
 	return objectName();
     }
 
+    virtual size_t getPropertyContainerCount() const;
+
+    virtual const PropertyContainer *getPropertyContainer(size_t i) const;
+    virtual PropertyContainer *getPropertyContainer(size_t i);
+
     virtual QString toXmlString(QString indent = "",
 				QString extraAttributes = "") const;
 
@@ -262,6 +266,44 @@
     ProgressMap m_progressBars; // I own the ProgressBars
 
     ViewManager *m_manager; // I don't own this
+    ViewPropertyContainer *m_propertyContainer; // I own this
+};
+
+
+// Use this for delegation, because we can't subclass from
+// PropertyContainer (which is a QObject) ourselves because of
+// ambiguity with QFrame parent
+
+class ViewPropertyContainer : public PropertyContainer
+{
+    Q_OBJECT
+
+public:
+    ViewPropertyContainer(View *v);
+    PropertyList getProperties() const { return m_v->getProperties(); }
+    PropertyType getPropertyType(const PropertyName &n) const {
+	return m_v->getPropertyType(n);
+    }
+    int getPropertyRangeAndValue(const PropertyName &n, int *min, int *max) const {
+	return m_v->getPropertyRangeAndValue(n, min, max);
+    }
+    QString getPropertyValueLabel(const PropertyName &n, int value) const {
+	return m_v->getPropertyValueLabel(n, value);
+    }
+    QString getPropertyContainerName() const {
+	return m_v->getPropertyContainerName();
+    }
+    QString getPropertyContainerIconName() const {
+	return "view";
+    }
+
+public slots:
+    virtual void setProperty(const PropertyName &n, int value) {
+	m_v->setProperty(n, value);
+    }
+
+protected:
+    View *m_v;
 };
 
 #endif