# HG changeset patch # User Chris Cannam # Date 1140199466 0 # Node ID 8460b3bf8f041463d70db0e43d5ad5d6353e2402 # Parent 4b16526b011b5fecf83fb85566af059c346ecf00 * 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 diff -r 4b16526b011b -r 8460b3bf8f04 base/Layer.cpp --- 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 diff -r 4b16526b011b -r 8460b3bf8f04 base/Layer.h --- 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 diff -r 4b16526b011b -r 8460b3bf8f04 base/PlayParameterRepository.cpp --- 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 + 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(sender())); +} + +void PlayParameterRepository::clear() { while (!m_playParameters.empty()) { diff -r 4b16526b011b -r 8460b3bf8f04 base/PlayParameterRepository.h --- 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 -class PlayParameterRepository +#include + +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 m_playParameters; diff -r 4b16526b011b -r 8460b3bf8f04 base/PlayParameters.cpp --- 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 + 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(); } diff -r 4b16526b011b -r 8460b3bf8f04 base/PlayParameters.h --- 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 -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; diff -r 4b16526b011b -r 8460b3bf8f04 base/PropertyContainer.h --- 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 diff -r 4b16526b011b -r 8460b3bf8f04 base/System.h --- 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 #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)) diff -r 4b16526b011b -r 8460b3bf8f04 base/View.cpp --- 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" diff -r 4b16526b011b -r 8460b3bf8f04 base/View.h --- 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 @@ -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