summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--muse2/awl/CMakeLists.txt117
-rw-r--r--muse2/awl/aslider.cpp241
-rw-r--r--muse2/awl/aslider.h135
-rw-r--r--muse2/awl/awl.cpp27
-rw-r--r--muse2/awl/awl.h30
-rw-r--r--muse2/awl/awlplugin.cpp127
-rw-r--r--muse2/awl/awlplugin.h273
-rw-r--r--muse2/awl/checkbox.cpp36
-rw-r--r--muse2/awl/checkbox.h55
-rw-r--r--muse2/awl/clock.xpm24
-rw-r--r--muse2/awl/combobox.cpp36
-rw-r--r--muse2/awl/combobox.h55
-rw-r--r--muse2/awl/drawbar.cpp130
-rw-r--r--muse2/awl/drawbar.h54
-rw-r--r--muse2/awl/fastlog.h39
-rw-r--r--muse2/awl/floatentry.cpp317
-rw-r--r--muse2/awl/floatentry.h112
-rw-r--r--muse2/awl/knob.cpp281
-rw-r--r--muse2/awl/knob.h85
-rw-r--r--muse2/awl/ltest.cpp14
-rw-r--r--muse2/awl/metronom.xpm24
-rw-r--r--muse2/awl/midimeter.cpp137
-rw-r--r--muse2/awl/midimeter.h56
-rw-r--r--muse2/awl/midimslider.cpp143
-rw-r--r--muse2/awl/midimslider.h56
-rw-r--r--muse2/awl/midipanentry.cpp47
-rw-r--r--muse2/awl/midipanentry.h48
-rw-r--r--muse2/awl/midipanknob.cpp37
-rw-r--r--muse2/awl/midipanknob.h55
-rw-r--r--muse2/awl/midivolentry.cpp50
-rw-r--r--muse2/awl/midivolentry.h47
-rw-r--r--muse2/awl/mslider.cpp273
-rw-r--r--muse2/awl/mslider.h68
-rw-r--r--muse2/awl/panentry.cpp35
-rw-r--r--muse2/awl/panentry.h40
-rw-r--r--muse2/awl/panknob.cpp38
-rw-r--r--muse2/awl/panknob.h46
-rw-r--r--muse2/awl/pitchedit.cpp89
-rw-r--r--muse2/awl/pitchedit.h50
-rw-r--r--muse2/awl/pitchlabel.cpp106
-rw-r--r--muse2/awl/pitchlabel.h51
-rw-r--r--muse2/awl/posedit.cpp441
-rw-r--r--muse2/awl/posedit.h72
-rw-r--r--muse2/awl/poslabel.cpp100
-rw-r--r--muse2/awl/poslabel.h56
-rw-r--r--muse2/awl/sigedit.cpp224
-rw-r--r--muse2/awl/sigedit.h66
-rw-r--r--muse2/awl/slider.cpp251
-rw-r--r--muse2/awl/slider.h81
-rw-r--r--muse2/awl/tcanvas.cpp1871
-rw-r--r--muse2/awl/tcanvas.h293
-rw-r--r--muse2/awl/tempoedit.cpp88
-rw-r--r--muse2/awl/tempoedit.h55
-rw-r--r--muse2/awl/tempolabel.cpp72
-rw-r--r--muse2/awl/tempolabel.h48
-rw-r--r--muse2/awl/utils.cpp50
-rw-r--r--muse2/awl/utils.h31
-rw-r--r--muse2/awl/volentry.cpp37
-rw-r--r--muse2/awl/volentry.h41
-rw-r--r--muse2/awl/volknob.cpp39
-rw-r--r--muse2/awl/volknob.h46
-rw-r--r--muse2/awl/volslider.cpp85
-rw-r--r--muse2/awl/volslider.h57
63 files changed, 7788 insertions, 0 deletions
diff --git a/muse2/awl/CMakeLists.txt b/muse2/awl/CMakeLists.txt
new file mode 100644
index 00000000..9045e028
--- /dev/null
+++ b/muse2/awl/CMakeLists.txt
@@ -0,0 +1,117 @@
+#=============================================================================
+# MusE
+# Linux Music Editor
+# $Id:$
+#
+# Copyright (C) 2002-2006 by Werner Schweer and others
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#=============================================================================
+
+include(${PROJECT_SOURCE_DIR}/pch.txt)
+
+MACRO(WRAP_CPP outfiles )
+ FOREACH(it ${ARGN})
+ SET(${outfiles} ${${outfiles}} ${it}.cpp)
+ ENDFOREACH(it)
+ ENDMACRO(WRAP_CPP)
+
+MACRO(WRAP_H outfiles )
+ FOREACH(it ${ARGN})
+ SET(${outfiles} ${${outfiles}} ${it}.h)
+ ENDFOREACH(it)
+ ENDMACRO(WRAP_H)
+
+set(mocs
+ aslider knob panknob slider volknob volslider floatentry
+ volentry panentry midivolentry midipanentry midipanknob
+ mslider midimslider midimeter combobox checkbox
+ # posedit
+ pitchedit
+ # poslabel
+ pitchlabel tempolabel
+ # sigedit
+ # tcanvas
+ tempoedit drawbar
+ )
+
+WRAP_H(mocH ${mocs})
+WRAP_CPP(mocCPP ${mocs})
+
+QT4_WRAP_CPP (moc_headers ${mocH})
+
+set(awl_src
+ awl.cpp utils.cpp ${mocCPP} ${moc_headers}
+ )
+
+add_library (
+ awl
+ STATIC
+ ${awl_src}
+ ${PROJECT_BINARY_DIR}/all.h.pch
+ )
+
+set_target_properties( awl
+ PROPERTIES COMPILE_FLAGS "-fPIC -include ${PROJECT_BINARY_DIR}/all.h"
+ )
+
+# IF (APPLE)
+# message("Not yet able to build awlplugin under OS X.")
+# ELSE (APPLE)
+#
+# #
+# # build libawlplugin.so
+# #
+# QT4_WRAP_CPP (moc_awlplugin_headers
+# awlplugin.h
+# volknob.h knob.h aslider.h
+# slider.h volslider.h mslider.h
+# posedit.h poslabel.h
+# tempoedit.h tempolabel.h
+# combobox.h checkbox.h
+# panknob.h midipanknob.h
+# floatentry.h
+# drawbar.h
+# )
+#
+# add_library ( awlplugin SHARED
+# awlplugin.cpp
+# volknob.cpp knob.cpp aslider.cpp
+# slider.cpp volslider.cpp mslider.cpp
+# posedit.cpp poslabel.cpp
+# tempoedit.cpp tempolabel.cpp
+# combobox.cpp checkbox.cpp
+# panknob.cpp midipanknob.cpp
+# floatentry.cpp
+# drawbar.cpp
+# ${moc_awlplugin_headers}
+# ${PROJECT_BINARY_DIR}/all-pic.h.pch
+# )
+#
+# set_target_properties( awlplugin
+# PROPERTIES COMPILE_FLAGS
+# "-D_GNU_SOURCE -D_REENTRANT -DHAVE_CONFIG_H -DQT_PLUGIN -DQT_SHARED -DQT_NO_DEBUG -include ${PROJECT_BINARY_DIR}/all-pic.h"
+# )
+# target_link_libraries( awlplugin
+# al pthread asound
+# )
+#
+# install( TARGETS awlplugin DESTINATION ${QT_PLUGINS_DIR}/designer/ )
+#
+# add_executable( ltest ltest.cpp )
+# target_link_libraries ( ltest
+# awlplugin
+# ${QT_LIBRARIES}
+# )
+#
+# ENDIF (APPLE)
diff --git a/muse2/awl/aslider.cpp b/muse2/awl/aslider.cpp
new file mode 100644
index 00000000..79a36b88
--- /dev/null
+++ b/muse2/awl/aslider.cpp
@@ -0,0 +1,241 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "fastlog.h"
+#include "aslider.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// AbstractSlider
+//---------------------------------------------------------
+
+AbstractSlider::AbstractSlider(QWidget* parent)
+ : QWidget(parent), _scaleColor(Qt::black), _scaleValueColor(Qt::blue)
+ {
+ _id = 0;
+ _value = 0.5;
+ _minValue = 0.0;
+ _maxValue = 1.0;
+ _lineStep = 0.1;
+ _pageStep = 0.2;
+ _center = false;
+ _invert = false;
+ _scaleWidth = 4;
+ _log = false;
+ _integer = false;
+ }
+
+//---------------------------------------------------------
+// setEnabled
+//---------------------------------------------------------
+
+void AbstractSlider::setEnabled(bool val)
+ {
+ QWidget::setEnabled(val);
+ update();
+ }
+
+//---------------------------------------------------------
+// setCenter
+//! If the center flag is set, a notch is drawn to
+//! show the center position.
+//---------------------------------------------------------
+
+void AbstractSlider::setCenter(bool val)
+ {
+ if (val != _center) {
+ _center = val;
+ update();
+ }
+ }
+
+//!--------------------------------------------------------
+// setScaleWidth
+//---------------------------------------------------------
+
+void AbstractSlider::setScaleWidth(int val)
+ {
+ if (val != _scaleWidth) {
+ _scaleWidth = val;
+ update();
+ }
+ }
+
+//---------------------------------------------------------
+// setScaleColor
+//---------------------------------------------------------
+
+void AbstractSlider::setScaleColor(const QColor& c)
+ {
+ if (c != _scaleColor) {
+ _scaleColor = c;
+ update();
+ }
+ }
+
+//---------------------------------------------------------
+// setScaleValueColor
+//---------------------------------------------------------
+
+void AbstractSlider::setScaleValueColor(const QColor& c)
+ {
+ if (c != _scaleValueColor) {
+ _scaleValueColor = c;
+ update();
+ }
+ }
+
+//---------------------------------------------------------
+// wheelEvent
+//---------------------------------------------------------
+
+void AbstractSlider::wheelEvent(QWheelEvent* ev)
+ {
+ double div = 120.0;
+ if (ev->modifiers() & Qt::ShiftModifier)
+ _value += (ev->delta() * pageStep()) / div;
+ else
+ _value += (ev->delta() * lineStep()) / div;
+ if (_value < _minValue)
+ _value = _minValue;
+ else if (_value > _maxValue)
+ _value = _maxValue;
+ valueChange();
+ update();
+ }
+
+//---------------------------------------------------------
+// keyPressEvent
+//---------------------------------------------------------
+
+void AbstractSlider::keyPressEvent(QKeyEvent* ev)
+ {
+ double oval = _value;
+
+ switch (ev->key()) {
+ case Qt::Key_Home: _value = _minValue; break;
+ case Qt::Key_End: _value = _maxValue; break;
+ case Qt::Key_Up:
+ case Qt::Key_Left: _value += lineStep(); break;
+ case Qt::Key_Down:
+ case Qt::Key_Right: _value -= lineStep(); break;
+ case Qt::Key_PageDown: _value -= pageStep(); break;
+ case Qt::Key_PageUp: _value += pageStep(); break;
+ default:
+ break;
+ }
+ if (_value < _minValue)
+ _value = _minValue;
+ else if (_value > _maxValue)
+ _value = _maxValue;
+
+ if (oval != _value) {
+ if (_integer && (rint(oval) == rint(_value)))
+ return;
+ valueChange();
+ update();
+ }
+ }
+
+//---------------------------------------------------------
+// setValue
+//---------------------------------------------------------
+
+void AbstractSlider::setValue(double val)
+ {
+ if (_log) {
+ if (val == 0.0f)
+ _value = _minValue;
+ else {
+ _value = fast_log10(val) * 20.0f;
+ if (_value < _minValue)
+ _value = _minValue;
+ }
+ }
+ else if (_integer)
+ _value = rint(val);
+ else
+ _value = val;
+ update();
+ }
+
+//---------------------------------------------------------
+// valueChange
+//---------------------------------------------------------
+
+void AbstractSlider::valueChange()
+ {
+ emit valueChanged(value(), _id);
+ }
+
+//---------------------------------------------------------
+// value
+//---------------------------------------------------------
+
+double AbstractSlider::value() const
+ {
+ if (_log)
+ return pow(10.0, _value*0.05f);
+ if (_integer)
+ return rint(_value);
+ return _value;
+ }
+
+//---------------------------------------------------------
+// minLogValue
+//---------------------------------------------------------
+
+//double AbstractSlider::minValue() const {
+// return _log ? pow(10.0, _minValue*0.05f) : _minValue;
+//}
+
+//---------------------------------------------------------
+// setMinLogValue
+//---------------------------------------------------------
+
+void AbstractSlider::setMinLogValue(double val) {
+ if (_log) {
+ if (val == 0.0f) _minValue = -100;
+ else _minValue = fast_log10(val) * 20.0f;
+ }
+ else _minValue = val;
+}
+
+//---------------------------------------------------------
+// maxLogValue
+//---------------------------------------------------------
+
+//double AbstractSlider::maxValue() const {
+// return _log ? pow(10.0, _maxValue*0.05f) : _maxValue;
+//}
+
+//---------------------------------------------------------
+// setMaxLogValue
+//---------------------------------------------------------
+
+void AbstractSlider::setMaxLogValue(double val) {
+ if (_log) {
+ _maxValue = fast_log10(val) * 20.0f;
+ }
+ else _maxValue = val;
+}
+
+}
diff --git a/muse2/awl/aslider.h b/muse2/awl/aslider.h
new file mode 100644
index 00000000..32fc89f9
--- /dev/null
+++ b/muse2/awl/aslider.h
@@ -0,0 +1,135 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AWLASLIDER_H__
+#define __AWLASLIDER_H__
+
+namespace Awl {
+
+//---------------------------------------------------------
+// AbstractSlider
+//
+//! The AwlAbstractSlider class provides an double value
+//! within a range
+//
+//! The class is designed as a common super class for
+//! widgets like AwlKnob and AwlSlider
+//!
+//---------------------------------------------------------
+
+class AbstractSlider : public QWidget {
+
+ Q_OBJECT
+ Q_PROPERTY(double value READ value WRITE setValue)
+ Q_PROPERTY(bool center READ center WRITE setCenter)
+ Q_PROPERTY(bool invertedAppearance READ invertedAppearance WRITE setInvertedAppearance)
+
+ Q_PROPERTY(int scaleWidth READ scaleWidth WRITE setScaleWidth)
+ Q_PROPERTY(QColor scaleColor READ scaleColor WRITE setScaleColor)
+ Q_PROPERTY(QColor scaleValueColor READ scaleValueColor WRITE setScaleValueColor)
+
+ Q_PROPERTY(int id READ id WRITE setId)
+
+ Q_PROPERTY(double minValue READ minValue WRITE setMinValue)
+ Q_PROPERTY(double maxValue READ maxValue WRITE setMaxValue)
+ Q_PROPERTY(double lineStep READ lineStep WRITE setLineStep)
+ Q_PROPERTY(double pageStep READ pageStep WRITE setPageStep)
+ Q_PROPERTY(bool log READ log WRITE setLog)
+ Q_PROPERTY(bool integer READ integer WRITE setInteger)
+
+ protected:
+ int _id;
+ double _value;
+ double _minValue, _maxValue, _lineStep, _pageStep;
+ bool _center;
+ bool _invert;
+ int _scaleWidth; //! scale line width
+ QColor _scaleColor;
+ QColor _scaleValueColor;
+ bool _log;
+ bool _integer;
+
+ virtual void wheelEvent(QWheelEvent*);
+ virtual void keyPressEvent(QKeyEvent*);
+ virtual void valueChange();
+
+ signals:
+ void valueChanged(double, int);
+
+ public slots:
+ virtual void setValue(double v);
+
+ public:
+ AbstractSlider(QWidget* parent = 0);
+
+ virtual void setCenter(bool val);
+ virtual void setScaleWidth(int);
+ virtual void setScaleColor(const QColor&);
+ virtual void setScaleValueColor(const QColor&);
+
+ //! return the center flag
+ bool center() const { return _center; }
+
+ //! return the scale line width
+ int scaleWidth() const { return _scaleWidth; }
+
+ //! return current scale color
+ QColor scaleColor() const { return _scaleColor; }
+
+ //! return color of active scale part
+ QColor scaleValueColor() const { return _scaleValueColor; }
+
+ virtual void setInvertedAppearance(bool val) { _invert = val; }
+ bool invertedAppearance() const { return _invert; }
+
+ int id() const { return _id; }
+ void setId(int i) { _id = i; }
+
+ virtual double value() const;
+
+ double minValue() const { return _minValue; }
+ void setMinValue(double v) { _minValue = v; }
+ void setMinLogValue(double v);
+ double maxValue() const {return _maxValue; }
+ void setMaxValue(double v) { _maxValue = v; }
+ void setMaxLogValue(double v);
+ void setRange(double a, double b) {
+ setMinValue(a);
+ setMaxValue(b);
+ }
+ void setLogRange(double a, double b) {
+ setMinLogValue(a);
+ setMaxLogValue(b);
+ }
+ bool log() const { return _log; }
+ void setLog(bool v) { _log = v; }
+ bool integer() const { return _integer; }
+ void setInteger(bool v) { _integer = v; }
+ double lineStep() const { return _lineStep; }
+ void setLineStep(double v) { _lineStep = v; }
+ double pageStep() const { return _pageStep; }
+ void setPageStep(double f) { _pageStep = f; }
+ void setEnabled(bool val);
+ };
+
+}
+
+#endif
+
diff --git a/muse2/awl/awl.cpp b/muse2/awl/awl.cpp
new file mode 100644
index 00000000..87aac3e7
--- /dev/null
+++ b/muse2/awl/awl.cpp
@@ -0,0 +1,27 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "awl.h"
+
+namespace Awl {
+// int sampleRate = 44100;
+// int mtcType = 0;
+ };
+
diff --git a/muse2/awl/awl.h b/muse2/awl/awl.h
new file mode 100644
index 00000000..2019c4bd
--- /dev/null
+++ b/muse2/awl/awl.h
@@ -0,0 +1,30 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AWL_H__
+#define __AWL_H__
+
+namespace Awl {
+// extern int sampleRate;
+// extern int mtcType;
+ };
+
+#endif
+
diff --git a/muse2/awl/awlplugin.cpp b/muse2/awl/awlplugin.cpp
new file mode 100644
index 00000000..43435f5e
--- /dev/null
+++ b/muse2/awl/awlplugin.cpp
@@ -0,0 +1,127 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "volknob.h"
+#include "volslider.h"
+#include "mslider.h"
+#include "awlplugin.h"
+#include "posedit.h"
+#include "poslabel.h"
+#include "tempoedit.h"
+#include "tempolabel.h"
+#include "checkbox.h"
+#include "combobox.h"
+#include "floatentry.h"
+#include "panknob.h"
+#include "midipanknob.h"
+#include "drawbar.h"
+
+#include <QtCore/QtPlugin>
+#include <QtDesigner/QDesignerCustomWidgetInterface>
+
+QWidget* KnobPlugin::createWidget(QWidget* parent)
+ {
+ return new Awl::Knob(parent);
+ }
+QWidget* VolKnobPlugin::createWidget(QWidget* parent)
+ {
+ return new Awl::VolKnob(parent);
+ }
+QWidget* SliderPlugin::createWidget(QWidget* parent)
+ {
+ return new Awl::Slider(parent);
+ }
+QWidget* VolSliderPlugin::createWidget(QWidget* parent)
+ {
+ return new Awl::VolSlider(parent);
+ }
+QWidget* MeterSliderPlugin::createWidget(QWidget* parent)
+ {
+ return new Awl::MeterSlider(parent);
+ }
+QWidget* PosEditPlugin::createWidget(QWidget* parent)
+ {
+ return new Awl::PosEdit(parent);
+ }
+QWidget* PosLabelPlugin::createWidget(QWidget* parent)
+ {
+ return new Awl::PosLabel(parent);
+ }
+QWidget* TempoEditPlugin::createWidget(QWidget* parent)
+ {
+ return new Awl::TempoEdit(parent);
+ }
+QWidget* TempoLabelPlugin::createWidget(QWidget* parent)
+ {
+ return new Awl::TempoLabel(parent);
+ }
+QWidget* CheckBoxPlugin::createWidget(QWidget* parent)
+ {
+ return new Awl::CheckBox(parent);
+ }
+QWidget* ComboBoxPlugin::createWidget(QWidget* parent)
+ {
+ return new Awl::ComboBox(parent);
+ }
+QWidget* FloatEntryPlugin::createWidget(QWidget* parent)
+ {
+ return new Awl::FloatEntry(parent);
+ }
+QWidget* PanKnobPlugin::createWidget(QWidget* parent)
+ {
+ return new Awl::PanKnob(parent);
+ }
+QWidget* MidiPanKnobPlugin::createWidget(QWidget* parent)
+ {
+ return new Awl::MidiPanKnob(parent);
+ }
+QWidget* DrawbarPlugin::createWidget(QWidget* parent)
+ {
+ return new Awl::Drawbar(parent);
+ }
+
+//---------------------------------------------------------
+// customWidgets
+//---------------------------------------------------------
+
+QList<QDesignerCustomWidgetInterface*> AwlPlugins::customWidgets() const
+ {
+ QList<QDesignerCustomWidgetInterface*> plugins;
+ plugins
+ << new VolKnobPlugin
+ << new PanKnobPlugin
+ << new MidiPanKnobPlugin
+ << new KnobPlugin
+ << new SliderPlugin
+ << new VolSliderPlugin
+ << new MeterSliderPlugin
+ << new PosEditPlugin
+ << new PosLabelPlugin
+ << new TempoEditPlugin
+ << new TempoLabelPlugin
+ << new CheckBoxPlugin
+ << new ComboBoxPlugin
+ << new FloatEntryPlugin
+ << new DrawbarPlugin;
+ return plugins;
+ }
+
+Q_EXPORT_PLUGIN(AwlPlugins)
+
diff --git a/muse2/awl/awlplugin.h b/muse2/awl/awlplugin.h
new file mode 100644
index 00000000..79b180fd
--- /dev/null
+++ b/muse2/awl/awlplugin.h
@@ -0,0 +1,273 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AWLPLUGIN_H__
+#define __AWLPLUGIN_H__
+
+#include <QtDesigner/QDesignerCustomWidgetInterface>
+
+//---------------------------------------------------------
+// AwlPlugin
+//---------------------------------------------------------
+
+class AwlPlugin : public QDesignerCustomWidgetInterface {
+ Q_INTERFACES(QDesignerCustomWidgetInterface)
+ bool m_initialized;
+
+ public:
+ AwlPlugin() : m_initialized(false) { }
+ bool isContainer() const { return false; }
+ bool isInitialized() const { return m_initialized; }
+ QIcon icon() const { return QIcon(); }
+ virtual QString codeTemplate() const { return QString(); }
+ QString whatsThis() const { return QString(); }
+ QString toolTip() const { return QString(); }
+ QString group() const { return "MusE Awl Widgets"; }
+ void initialize(QDesignerFormEditorInterface *) {
+ if (m_initialized)
+ return;
+ m_initialized = true;
+ }
+ };
+
+//---------------------------------------------------------
+// KnobPlugin
+//---------------------------------------------------------
+
+class KnobPlugin : public QObject, public AwlPlugin {
+ Q_OBJECT
+
+ public:
+ KnobPlugin(QObject* parent = 0) : QObject(parent) {}
+ QString includeFile() const { return QString("awl/knob.h"); }
+ QString name() const { return "Awl::Knob"; }
+ QWidget* createWidget(QWidget* parent);
+ };
+
+//---------------------------------------------------------
+// VolKnobPlugin
+//---------------------------------------------------------
+
+class VolKnobPlugin : public QObject, public AwlPlugin {
+ Q_OBJECT
+
+ public:
+ VolKnobPlugin(QObject* parent = 0) : QObject(parent) {}
+ QString includeFile() const { return "awl/volknob.h"; }
+ QString name() const { return "Awl::VolKnob"; }
+ QWidget* createWidget(QWidget* parent);
+ };
+
+//---------------------------------------------------------
+// SliderPlugin
+//---------------------------------------------------------
+
+class SliderPlugin : public QObject, public AwlPlugin {
+ Q_OBJECT
+
+ public:
+ SliderPlugin(QObject* parent = 0) : QObject(parent) {}
+ QString includeFile() const { return "awl/slider.h"; }
+ QString name() const { return "Awl::Slider"; }
+ QWidget* createWidget(QWidget* parent);
+ };
+
+//---------------------------------------------------------
+// VolSliderPlugin
+//---------------------------------------------------------
+
+class VolSliderPlugin : public QObject, public AwlPlugin {
+ Q_OBJECT
+
+ public:
+ VolSliderPlugin(QObject* parent = 0) : QObject(parent) {}
+ QString includeFile() const { return "awl/volslider.h"; }
+ QString name() const { return "Awl::VolSlider"; }
+ QWidget* createWidget(QWidget* parent);
+ };
+
+//---------------------------------------------------------
+// MeterSliderPlugin
+//---------------------------------------------------------
+
+class MeterSliderPlugin : public QObject, public AwlPlugin {
+ Q_OBJECT
+
+ public:
+ MeterSliderPlugin(QObject* parent = 0) : QObject(parent) {}
+ QString includeFile() const { return "awl/mslider.h"; }
+ QString name() const { return "Awl::MeterSlider"; }
+ QWidget* createWidget(QWidget* parent);
+ };
+
+//---------------------------------------------------------
+// PosEditPlugin
+//---------------------------------------------------------
+
+class PosEditPlugin : public QObject, public AwlPlugin {
+ Q_OBJECT
+
+ public:
+ PosEditPlugin(QObject* parent = 0) : QObject(parent) {}
+ QString includeFile() const { return "awl/posedit.h"; }
+ QString name() const { return "Awl::PosEdit"; }
+ QWidget* createWidget(QWidget* parent);
+ };
+
+//---------------------------------------------------------
+// PosLabelPlugin
+//---------------------------------------------------------
+
+class PosLabelPlugin : public QObject, public AwlPlugin {
+ Q_OBJECT
+
+ public:
+ PosLabelPlugin(QObject* parent = 0) : QObject(parent) {}
+ QString includeFile() const { return "awl/poslabel.h"; }
+ QString name() const { return "Awl::PosLabel"; }
+ QWidget* createWidget(QWidget* parent);
+ };
+
+//---------------------------------------------------------
+// TempoEditPlugin
+//---------------------------------------------------------
+
+class TempoEditPlugin : public QObject, public AwlPlugin {
+ Q_OBJECT
+
+ public:
+ TempoEditPlugin(QObject* parent = 0) : QObject(parent) {}
+ QString includeFile() const { return "awl/tempoedit.h"; }
+ QString name() const { return "Awl::TempoEdit"; }
+ QWidget* createWidget(QWidget* parent);
+ };
+
+//---------------------------------------------------------
+// TempoLabelPlugin
+//---------------------------------------------------------
+
+class TempoLabelPlugin : public QObject, public AwlPlugin {
+ Q_OBJECT
+
+ public:
+ TempoLabelPlugin(QObject* parent = 0) : QObject(parent) {}
+ QString includeFile() const { return "awl/tempolabel.h"; }
+ QString name() const { return "Awl::TempoLabel"; }
+ QWidget* createWidget(QWidget* parent);
+ };
+
+//---------------------------------------------------------
+// CheckBoxPlugin
+//---------------------------------------------------------
+
+class CheckBoxPlugin : public QObject, public AwlPlugin {
+ Q_OBJECT
+
+ public:
+ CheckBoxPlugin(QObject* parent = 0) : QObject(parent) {}
+ QString includeFile() const { return "awl/checkbox.h"; }
+ QString name() const { return "Awl::CheckBox"; }
+ QWidget* createWidget(QWidget* parent);
+ };
+
+//---------------------------------------------------------
+// ComboBoxPlugin
+//---------------------------------------------------------
+
+class ComboBoxPlugin : public QObject, public AwlPlugin {
+ Q_OBJECT
+
+ public:
+ ComboBoxPlugin(QObject* parent = 0) : QObject(parent) {}
+ QString includeFile() const { return "awl/combobox.h"; }
+ QString name() const { return "Awl::ComboBox"; }
+ QWidget* createWidget(QWidget* parent);
+ };
+
+//---------------------------------------------------------
+// FloatEntryPlugin
+//---------------------------------------------------------
+
+class FloatEntryPlugin : public QObject, public AwlPlugin {
+ Q_OBJECT
+
+ public:
+ FloatEntryPlugin(QObject* parent = 0) : QObject(parent) {}
+ QString includeFile() const { return "awl/floatentry.h"; }
+ QString name() const { return "Awl::FloatEntry"; }
+ QWidget* createWidget(QWidget* parent);
+ };
+
+//---------------------------------------------------------
+// PanKnobPlugin
+//---------------------------------------------------------
+
+class PanKnobPlugin : public QObject, public AwlPlugin {
+ Q_OBJECT
+
+ public:
+ PanKnobPlugin(QObject* parent = 0) : QObject(parent) {}
+ QString includeFile() const { return "awl/panknob.h"; }
+ QString name() const { return "Awl::PanKnob"; }
+ QWidget* createWidget(QWidget* parent);
+ };
+
+//---------------------------------------------------------
+// MidiPanKnobPlugin
+//---------------------------------------------------------
+
+class MidiPanKnobPlugin : public QObject, public AwlPlugin {
+ Q_OBJECT
+
+ public:
+ MidiPanKnobPlugin(QObject* parent = 0) : QObject(parent) {}
+ QString includeFile() const { return "awl/midipanknob.h"; }
+ QString name() const { return "Awl::MidiPanKnob"; }
+ QWidget* createWidget(QWidget* parent);
+ };
+
+//---------------------------------------------------------
+// DrawbarPlugin
+//---------------------------------------------------------
+
+class DrawbarPlugin : public QObject, public AwlPlugin {
+ Q_OBJECT
+
+ public:
+ DrawbarPlugin(QObject* parent = 0) : QObject(parent) {}
+ QString includeFile() const { return "awl/drawbar.h"; }
+ QString name() const { return "Awl::Drawbar"; }
+ QWidget* createWidget(QWidget* parent);
+ };
+
+//---------------------------------------------------------
+// AwlPlugins
+//---------------------------------------------------------
+
+class AwlPlugins : public QObject, public QDesignerCustomWidgetCollectionInterface {
+ Q_OBJECT
+ Q_INTERFACES(QDesignerCustomWidgetCollectionInterface)
+
+ public:
+ QList<QDesignerCustomWidgetInterface*> customWidgets() const;
+ };
+
+#endif
+
diff --git a/muse2/awl/checkbox.cpp b/muse2/awl/checkbox.cpp
new file mode 100644
index 00000000..6ef74386
--- /dev/null
+++ b/muse2/awl/checkbox.cpp
@@ -0,0 +1,36 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "checkbox.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// CheckBox
+//---------------------------------------------------------
+
+CheckBox::CheckBox(QWidget* parent)
+ : QCheckBox(parent)
+ {
+ _id = 0;
+ connect(this, SIGNAL(toggled(bool)), SLOT(hasToggled(bool)));
+ }
+}
+
diff --git a/muse2/awl/checkbox.h b/muse2/awl/checkbox.h
new file mode 100644
index 00000000..ac67fc57
--- /dev/null
+++ b/muse2/awl/checkbox.h
@@ -0,0 +1,55 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AWLCHECKBOX_H__
+#define __AWLCHECKBOX_H__
+
+namespace Awl {
+
+//---------------------------------------------------------
+// CheckBox
+//---------------------------------------------------------
+
+class CheckBox : public QCheckBox {
+ Q_OBJECT
+ Q_PROPERTY(int id READ id WRITE setId)
+
+ int _id;
+
+ private slots:
+ void hasToggled(bool val) {
+ emit valueChanged(double(val), _id);
+ }
+ signals:
+ void valueChanged(double, int);
+
+ public slots:
+ void setValue(double val) { setDown(val > 0.5f); }
+
+ public:
+ CheckBox(QWidget* parent);
+ int id() const { return _id; }
+ void setId(int i) { _id = i; }
+ };
+
+}
+
+#endif
+
diff --git a/muse2/awl/clock.xpm b/muse2/awl/clock.xpm
new file mode 100644
index 00000000..3bf15e01
--- /dev/null
+++ b/muse2/awl/clock.xpm
@@ -0,0 +1,24 @@
+/* XPM */
+static char *clock_xpm[]={
+"18 18 3 1",
+". c None",
+"# c #000000",
+"a c #0000c0",
+"...####a#####.....",
+"..####.aaa.###....",
+".####..aaa..###...",
+".###...aaa...###..",
+".#.....aaa....##..",
+"##.....aaa.....##.",
+"##.....aaa.....##.",
+"###....aaaaaaaaa#.",
+"###....aaaaaaaaa#.",
+"##.....aaaaaaaaa#.",
+"##............#.#.",
+".##...........##..",
+".##..........###..",
+"..##........####..",
+"...####...####....",
+"....#########.....",
+"......######......",
+".................."};
diff --git a/muse2/awl/combobox.cpp b/muse2/awl/combobox.cpp
new file mode 100644
index 00000000..58c82c54
--- /dev/null
+++ b/muse2/awl/combobox.cpp
@@ -0,0 +1,36 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "combobox.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// ComboBox
+//---------------------------------------------------------
+
+ComboBox::ComboBox(QWidget* parent)
+ : QComboBox(parent)
+ {
+ _id = 0;
+ connect(this, SIGNAL(activated(int)), SLOT(activatedIntern(int)));
+ }
+}
+
diff --git a/muse2/awl/combobox.h b/muse2/awl/combobox.h
new file mode 100644
index 00000000..d335d993
--- /dev/null
+++ b/muse2/awl/combobox.h
@@ -0,0 +1,55 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AWLCOMBOBOX_H__
+#define __AWLCOMBOBOX_H__
+
+namespace Awl {
+
+//---------------------------------------------------------
+// ComboBox
+//---------------------------------------------------------
+
+class ComboBox : public QComboBox {
+ Q_OBJECT
+ Q_PROPERTY(int id READ id WRITE setId)
+
+ int _id;
+
+ private slots:
+ void activatedIntern(int val) {
+ emit valueChanged(double(val), _id);
+ }
+
+ signals:
+ void valueChanged(double, int);
+
+ public slots:
+ void setValue(double val) { setCurrentIndex(int(val)); }
+
+ public:
+ ComboBox(QWidget* parent);
+ int id() const { return _id; }
+ void setId(int i) { _id = i; }
+ };
+
+}
+
+#endif
diff --git a/muse2/awl/drawbar.cpp b/muse2/awl/drawbar.cpp
new file mode 100644
index 00000000..18525ded
--- /dev/null
+++ b/muse2/awl/drawbar.cpp
@@ -0,0 +1,130 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2007 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "drawbar.h"
+
+namespace Awl {
+
+#if 0
+ }
+#endif
+
+//---------------------------------------------------------
+// Drawbar
+//---------------------------------------------------------
+
+Drawbar::Drawbar(QWidget* parent)
+ : Slider(parent)
+ {
+ _sliderColor = Qt::darkGray;
+ setOrientation(Qt::Vertical);
+ setInvertedAppearance(true);
+ setRange(0.0, 8.0);
+ setLineStep(1.0);
+ setPageStep(1.0);
+ setInteger(true);
+ }
+
+Drawbar::~Drawbar()
+ {
+ }
+
+//---------------------------------------------------------
+// setSliderColor
+//---------------------------------------------------------
+
+void Drawbar::setSliderColor(const QColor& c)
+ {
+ if (c != _sliderColor) {
+ _sliderColor = c;
+ update();
+ }
+ }
+
+//---------------------------------------------------------
+// paint
+//---------------------------------------------------------
+
+void Drawbar::paintEvent(QPaintEvent*)
+ {
+ int h = height();
+ int w = width();
+
+ int kh = w * 2; // knob height
+ int kw = w;
+ int pixel = h - kh;
+ int ppos = int(pixel * value() / 8.0);
+
+ QPainter p(this);
+
+ QColor sc(Qt::darkGray);
+ QColor svc(Qt::gray);
+
+ p.setBrush(svc);
+
+ //---------------------------------------------------
+ // draw scale
+ //---------------------------------------------------
+
+ int sx = (w + 9) / 10;
+ int sw = w - 2 * sx;
+ p.fillRect(sx, 0, sw, ppos, sc);
+ QPen pen(Qt::white);
+ int lw = 2;
+ pen.setWidth(lw);
+ p.setPen(pen);
+ int sx1 = sx + lw/2;
+ p.drawLine(sx1, 0, sx1, ppos);
+ int sx2 = sx + sw - lw/2;
+ p.drawLine(sx2, 0, sx2, ppos);
+
+ //---------------------------------------------------
+ // draw numbers
+ //---------------------------------------------------
+
+ p.save();
+ p.setClipRect(QRect(sx, 0, sw, ppos));
+ QFont f = p.font();
+ f.setPixelSize(8);
+
+ int ch = pixel / 8;
+ QString num("%1");
+ for (int i = 0; i < 8; ++i) {
+ p.drawText(0, i * pixel / 8 - (pixel - ppos), w, ch, Qt::AlignCenter, num.arg(8-i));
+ }
+ p.restore();
+
+ //---------------------------------------------------
+ // draw slider
+ //---------------------------------------------------
+
+ p.fillRect(0, ppos, kw, kh, _sliderColor);
+
+ pen.setWidth(1);
+ pen.setColor(Qt::black);
+ p.setPen(pen);
+
+ int y1 = ppos + kh / 5 * 2;
+ int y2 = ppos + kh / 5 * 3;
+ p.drawLine(0, y1, kw, y1);
+ p.drawLine(0, y2, kw, y2);
+ }
+}
+
diff --git a/muse2/awl/drawbar.h b/muse2/awl/drawbar.h
new file mode 100644
index 00000000..4794b784
--- /dev/null
+++ b/muse2/awl/drawbar.h
@@ -0,0 +1,54 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2007 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AWLDRAWBAR_H__
+#define __AWLDRAWBAR_H__
+
+#include "slider.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// Drawbar
+//---------------------------------------------------------
+
+class Drawbar : public Slider {
+ Q_OBJECT
+
+ Q_PROPERTY(QColor sliderColor READ sliderColor WRITE setSliderColor)
+
+ virtual void paintEvent(QPaintEvent*);
+
+ protected:
+ QColor _sliderColor;
+
+ public:
+ Drawbar(QWidget* parent = 0);
+ ~Drawbar();
+
+ //! return current slider color
+ QColor sliderColor() const { return _sliderColor; }
+ void setSliderColor(const QColor&);
+ };
+
+}
+
+#endif
+
diff --git a/muse2/awl/fastlog.h b/muse2/awl/fastlog.h
new file mode 100644
index 00000000..90a85342
--- /dev/null
+++ b/muse2/awl/fastlog.h
@@ -0,0 +1,39 @@
+/* Copyright unknown. Code by Laurent de Soras <laurent@ohmforce.com>.
+ */
+
+#ifndef __FASTLOG_H__
+#define __FASTLOG_H__
+
+#include <math.h> /* for HUGE_VAL */
+
+static inline float fast_log2 (float val)
+ {
+ /* don't use reinterpret_cast<> because that prevents this
+ from being used by pure C code (for example, GnomeCanvasItems)
+ */
+ union {float f; int i;} t;
+ t.f = val;
+ int* const exp_ptr = &t.i;
+ int x = *exp_ptr;
+ const int log_2 = ((x >> 23) & 255) - 128;
+ x &= ~(255 << 23);
+ x += 127 << 23;
+ *exp_ptr = x;
+ val = ((-1.0f/3) * t.f + 2) * t.f - 2.0f/3;
+ return (val + log_2);
+ }
+
+static inline float fast_log (const float val)
+ {
+ return (fast_log2 (val) * 0.69314718f);
+ }
+
+static inline float fast_log10 (const float val)
+ {
+ return fast_log2(val) / 3.312500f;
+ }
+
+static inline float minus_infinity() { return -HUGE_VAL; }
+
+#endif
+
diff --git a/muse2/awl/floatentry.cpp b/muse2/awl/floatentry.cpp
new file mode 100644
index 00000000..7831614f
--- /dev/null
+++ b/muse2/awl/floatentry.cpp
@@ -0,0 +1,317 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "floatentry.h"
+#include "fastlog.h"
+
+#define TIMER1 400
+#define TIMER2 200
+#define TIMEC 7
+#define TIMER3 100
+#define TIMEC2 20
+#define TIMER4 50
+
+namespace Awl {
+
+//---------------------------------------------------------
+// FloatEntry
+//---------------------------------------------------------
+
+FloatEntry::FloatEntry(QWidget* parent)
+ : QLineEdit(parent)
+ {
+ _id = 0;
+ _minValue = 0.0;
+ _maxValue = 1.0;
+ _log = false;
+ evx = 1.0;
+ _precision = 3;
+ timer = new QTimer(this);
+ connect(timer, SIGNAL(timeout()), SLOT(repeat()));
+ _value = 0.0f;
+ connect(this, SIGNAL(returnPressed()), SLOT(endEdit()));
+ setCursor(QCursor(Qt::ArrowCursor));
+ updateValue();
+ }
+
+//---------------------------------------------------------
+// setString
+//---------------------------------------------------------
+
+bool FloatEntry::setString(double v)
+ {
+ QString s;
+// if (v < _minValue || v > _maxValue) {
+ if (v < _minValue) {
+ if (!_specialText.isEmpty())
+ setText(_specialText);
+ return true;
+ }
+ s.setNum(v, 'f', _precision);
+ if (!_suffix.isEmpty()) {
+ // s += " ";
+ s += _suffix;
+ }
+ setText(s);
+ return false;
+ }
+
+//---------------------------------------------------------
+// setSValue
+//---------------------------------------------------------
+
+void FloatEntry::setSValue(const QString& s)
+ {
+ bool ok;
+ double v = s.toFloat(&ok);
+ if (ok && (v != _value)) {
+ if (v < _minValue)
+ v = _minValue;
+ if (v > _maxValue)
+ v = _maxValue;
+ _value = v;
+ updateValue();
+ valueChange();
+ }
+ }
+
+//---------------------------------------------------------
+// valueChange
+//---------------------------------------------------------
+
+void FloatEntry::valueChange()
+ {
+ emit valueChanged(value(), _id);
+ }
+
+//---------------------------------------------------------
+// incValue
+//---------------------------------------------------------
+
+void FloatEntry::incValue(double)
+ {
+ if (_value + 1.0 < _maxValue) {
+ _value = _value + 1.0;
+ updateValue();
+ valueChange();
+ }
+ }
+
+//---------------------------------------------------------
+// decValue
+//---------------------------------------------------------
+
+void FloatEntry::decValue(double)
+ {
+ if (_value - 1.0 > _minValue) {
+ _value = _value - 1.0;
+ updateValue();
+ valueChange();
+ }
+ }
+
+//---------------------------------------------------------
+// setPrecision
+//---------------------------------------------------------
+
+void FloatEntry::setPrecision(int v)
+ {
+ _precision = v;
+ setString(_value);
+ }
+
+//---------------------------------------------------------
+// sizeHint
+//---------------------------------------------------------
+
+QSize FloatEntry::sizeHint() const
+ {
+ QFontMetrics fm = fontMetrics();
+ int h = fm.height() + 4;
+ int n = _precision + 3;
+ int w = fm.width(QString("-0.")) + fm.width('0') * n + 6;
+ return QSize(w, h);
+ }
+
+//---------------------------------------------------------
+// endEdit
+//---------------------------------------------------------
+
+void FloatEntry::endEdit()
+ {
+ if (QLineEdit::isModified())
+ setSValue(text());
+ clearFocus();
+ }
+
+//---------------------------------------------------------
+// mousePressEvent
+//---------------------------------------------------------
+
+void FloatEntry::mousePressEvent(QMouseEvent* event)
+ {
+ button = event->button();
+ starty = event->y();
+ evx = double(event->x());
+ timecount = 0;
+ repeat();
+ timer->start(TIMER1);
+ }
+
+//---------------------------------------------------------
+// wheelEvent
+//---------------------------------------------------------
+
+void FloatEntry::wheelEvent(QWheelEvent* event)
+ {
+ int delta = event->delta();
+
+ if (delta < 0)
+ decValue(-1.0);
+ else if (delta > 0)
+ incValue(1.0);
+ }
+
+//---------------------------------------------------------
+// repeat
+//---------------------------------------------------------
+
+void FloatEntry::repeat()
+ {
+ if (timecount == 1) {
+ ++timecount;
+ timer->stop();
+ timer->start(TIMER2);
+ return;
+ }
+ ++timecount;
+ if (timecount == TIMEC) {
+ timer->stop();
+ timer->start(TIMER3);
+ }
+ if (timecount == TIMEC2) {
+ timer->stop();
+ timer->start(TIMER4);
+ }
+
+ switch (button) {
+ case Qt::LeftButton:
+ return;
+ case Qt::MidButton:
+ decValue(evx);
+ break;
+ case Qt::RightButton:
+ incValue(evx);
+ break;
+ default:
+ break;
+ }
+ }
+
+//---------------------------------------------------------
+// mouseReleaseEvent
+//---------------------------------------------------------
+
+void FloatEntry::mouseReleaseEvent(QMouseEvent*)
+ {
+ button = Qt::NoButton;
+ timer->stop();
+ }
+
+//---------------------------------------------------------
+// mouseMoveEvent
+//---------------------------------------------------------
+
+void FloatEntry::mouseMoveEvent(QMouseEvent*)
+ {
+ switch (button) {
+ case Qt::LeftButton:
+ break;
+ case Qt::MidButton:
+ break;
+ case Qt::RightButton:
+ break;
+ default:
+ break;
+ }
+ }
+
+//---------------------------------------------------------
+// mouseDoubleClickEvent
+//---------------------------------------------------------
+
+void FloatEntry::mouseDoubleClickEvent(QMouseEvent* event)
+ {
+ if (event->button() != Qt::LeftButton) {
+ mousePressEvent(event);
+ return;
+ }
+ setFocus();
+ QLineEdit::setFrame(true);
+ update();
+ }
+
+//---------------------------------------------------------
+// setValue
+//---------------------------------------------------------
+
+void FloatEntry::setValue(double val)
+ {
+ if (_log) {
+ if (val == 0.0f)
+ _value = _minValue;
+ else
+ _value = fast_log10(val) * 20.0f;
+ }
+ else
+ _value = val;
+ updateValue();
+ }
+
+//---------------------------------------------------------
+// updateValue
+//---------------------------------------------------------
+
+void FloatEntry::updateValue()
+ {
+ if (setString(_value)) {
+ // value is out of range:
+ if (_value > _maxValue)
+ _value = _maxValue;
+ else if (_value < _minValue)
+ _value = _minValue;
+ }
+ }
+
+//---------------------------------------------------------
+// value
+//---------------------------------------------------------
+
+double FloatEntry::value() const
+ {
+ double rv;
+ if (_log)
+ rv = pow(10.0, _value * 0.05f);
+ else
+ rv = _value;
+ return rv;
+ }
+}
+
diff --git a/muse2/awl/floatentry.h b/muse2/awl/floatentry.h
new file mode 100644
index 00000000..a90232a9
--- /dev/null
+++ b/muse2/awl/floatentry.h
@@ -0,0 +1,112 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __FLOATLABEL_H__
+#define __FLOATLABEL_H__
+
+namespace Awl {
+
+//---------------------------------------------------------
+// FloatEntry
+//---------------------------------------------------------
+
+class FloatEntry : public QLineEdit {
+ Q_OBJECT
+ Q_PROPERTY(int id READ id WRITE setId)
+
+ Q_PROPERTY(double minValue READ minValue WRITE setMinValue)
+ Q_PROPERTY(double maxValue READ maxValue WRITE setMaxValue)
+
+ Q_PROPERTY(QString specialText READ specialText WRITE setSpecialText)
+ Q_PROPERTY(QString suffix READ suffix WRITE setSuffix)
+ Q_PROPERTY(int precision READ precision WRITE setPrecision)
+ Q_PROPERTY(bool log READ log WRITE setLog)
+
+ int button;
+ int starty;
+ QTimer* timer;
+ double evx;
+ int timecount;
+ double _minValue, _maxValue;
+ QString _specialText; // text to show if value outside min,max
+ QString _suffix;
+ int _precision;
+ bool _log;
+
+ virtual void wheelEvent(QWheelEvent*);
+ virtual void mousePressEvent(QMouseEvent*);
+ virtual void mouseMoveEvent(QMouseEvent*);
+ virtual void mouseDoubleClickEvent(QMouseEvent*);
+ virtual void mouseReleaseEvent(QMouseEvent*);
+ virtual void setSValue(const QString&);
+ virtual bool setString(double);
+ virtual void incValue(double);
+ virtual void decValue(double);
+
+ void updateValue();
+
+ protected:
+ int _id;
+ double _value;
+ virtual void valueChange();
+
+ private slots:
+ void repeat();
+
+ protected slots:
+ void endEdit();
+
+ public slots:
+ virtual void setValue(double);
+
+ signals:
+ void valueChanged(double, int);
+
+ public:
+ FloatEntry(QWidget*);
+ virtual QSize sizeHint() const;
+ virtual double value() const;
+ int id() const { return _id; }
+ void setId(int i) { _id = i; }
+ double minValue() const { return _minValue; }
+ double maxValue() const { return _maxValue; }
+ void setMinValue(double v) { _minValue = v; }
+ void setMaxValue(double v) { _maxValue = v; }
+ void setRange(double a, double b) {
+ _minValue = a;
+ _maxValue = b;
+ }
+ int precision() const { return _precision; }
+ void setPrecision(int val);
+ QString specialText() const { return _specialText; }
+ void setSpecialText(const QString& s) {
+ _specialText = s;
+ update();
+ }
+ QString suffix() const { return _suffix; }
+ void setSuffix(const QString& s) { _suffix = s; }
+ bool log() const { return _log; }
+ void setLog(bool v) { _log = v; }
+ };
+
+}
+
+#endif
+
diff --git a/muse2/awl/knob.cpp b/muse2/awl/knob.cpp
new file mode 100644
index 00000000..ccc3988e
--- /dev/null
+++ b/muse2/awl/knob.cpp
@@ -0,0 +1,281 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "knob.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// Knob
+/// this is the AwlKnob contructor
+//---------------------------------------------------------
+
+Knob::Knob(QWidget* parent)
+ : AbstractSlider(parent)
+ {
+ _scaleSize = 270;
+ _markSize = 6;
+ _border = 2;
+ points = 0;
+ }
+
+//---------------------------------------------------------
+// Knob
+//---------------------------------------------------------
+
+Knob::~Knob()
+ {
+ if (points)
+ delete points;
+ }
+
+//---------------------------------------------------------
+// setText
+//---------------------------------------------------------
+
+void Knob::setText(const QString& s)
+ {
+ if (s != _text) {
+ _text = s;
+ update();
+ }
+ }
+
+//---------------------------------------------------------
+// setScaleSize
+//! set the scale size in degrees
+//
+//! the scale size is the max moving angle measured
+//! in degrees
+//---------------------------------------------------------
+
+void Knob::setScaleSize(int val)
+ {
+ if (val != _scaleSize) {
+ _scaleSize = val;
+ update();
+ }
+ }
+
+//---------------------------------------------------------
+// setMarkSize
+//! set size of the center marker
+//---------------------------------------------------------
+
+void Knob::setMarkSize(int val)
+ {
+ if (val != _markSize) {
+ _markSize = val;
+ update();
+ }
+ }
+
+//---------------------------------------------------------
+// setBorder
+//! set border size
+//---------------------------------------------------------
+
+void Knob::setBorder(int val)
+ {
+ if (val != _border) {
+ _border = val;
+ update();
+ }
+ }
+
+//---------------------------------------------------------
+// mousePressEvent
+//---------------------------------------------------------
+
+void Knob::mousePressEvent(QMouseEvent* ev)
+ {
+ startY = ev->y();
+ emit sliderPressed(_id);
+ if (_center) {
+ QRect r(points->boundingRect().toRect());
+ if (r.contains(ev->pos())) {
+ setValue(.0f);
+ valueChange();
+ update();
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// mouseReleaseEvent
+//---------------------------------------------------------
+
+void Knob::mouseReleaseEvent(QMouseEvent*)
+ {
+ emit sliderReleased(_id);
+ }
+
+//---------------------------------------------------------
+// mouseMoveEvent
+//---------------------------------------------------------
+
+void Knob::mouseMoveEvent(QMouseEvent* ev)
+ {
+ int y = ev->y();
+ double delta = (maxValue() - minValue()) / 100.0f;
+ if (delta == 0)
+ delta = 1;
+ _value += (startY - y) * delta;
+ if (_value < minValue())
+ _value = _minValue;
+ else if (_value > maxValue())
+ _value = _maxValue;
+ startY = y;
+ valueChange();
+ update();
+ }
+
+//---------------------------------------------------------
+// paintEvent
+//---------------------------------------------------------
+
+void Knob::paintEvent(QPaintEvent* ev)
+ {
+ QRect rr(ev->rect());
+ QPainter p(this);
+ p.setRenderHint(QPainter::Antialiasing, true);
+
+ int markSize2 = _markSize/2;
+ int restR = 360 - _scaleSize;
+ int w = width() - _scaleWidth - 2 * _border;
+ int h = height() - _scaleWidth/2 - 2 * _border;
+
+ int xoffset, yoffset;
+ if (_center)
+ h -= _markSize;
+ if (w > h) {
+ yoffset = 0;
+ xoffset = (w - h) / 2;
+ w = h;
+ }
+ else {
+ xoffset = 0;
+ // yoffset = (h - w) / 2; // center
+ yoffset = h - w; // top align
+ h = w;
+ }
+
+ int x = xoffset + _scaleWidth / 2 + _border;
+ int y = yoffset + _scaleWidth / 2 + _border + (_center ? _markSize+_scaleWidth/2 : 0);
+ QRectF ar(x, y, w, h);
+
+ QColor sc(isEnabled() ? _scaleColor : Qt::gray);
+ QColor svc(isEnabled() ? _scaleValueColor : Qt::gray);
+
+ //-----------------------------------------
+ // draw arc
+ //-----------------------------------------
+
+ double dvalue = maxValue() - minValue();
+ if (_center) {
+ int size = _scaleSize * 8;
+ if (_value >= 0) {
+ int offset = (restR-180) * 8;
+ int r1 = int (size * _value / maxValue());
+ int r2 = size - r1;
+ p.setPen(QPen(sc, _scaleWidth));
+ if (r2 > 1)
+ p.drawArc(ar, offset, r2);
+ if (size > 1)
+ p.drawArc(ar, 90*16, size);
+ if (r1 > 1) {
+ p.setPen(QPen(svc, _scaleWidth));
+ p.drawArc(ar, offset+r2, r1);
+ }
+ }
+ else {
+ // int offset = (restR+180) * 8;
+ int r1 = int(size * _value / minValue());
+ int r2 = size - r1;
+
+ p.setPen(QPen(sc, _scaleWidth));
+ if (size > 1)
+ p.drawArc(ar, (restR-180)*8, size);
+ if (r2 > 1)
+ p.drawArc(ar, 90 * 16 + r1, r2);
+ if (r1 > 1) {
+ p.setPen(QPen(svc, _scaleWidth));
+ p.drawArc(ar, 90*16, r1);
+ }
+ }
+ }
+ else {
+ int offset = (180-restR) * 8;
+ int size = _scaleSize * 16;
+ int r1 = int(size * (_value - minValue()) / dvalue);
+ int r2 = size - r1;
+ if (r2 >= 1) {
+ p.setPen(QPen(sc, _scaleWidth));
+ p.drawArc(ar, -offset, r2);
+ }
+ if (r1 >= 1) {
+ p.setPen(QPen(svc, _scaleWidth));
+ p.drawArc(ar, r2-offset, r1);
+ }
+ }
+
+ //-----------------------------------------
+ // draw pointer
+ //-----------------------------------------
+
+ p.setPen(QPen(svc, _scaleWidth));
+ double r1 = double(_scaleSize) * (_value-minValue()) / dvalue + 90.0
+ + double(restR/2);
+ r1 = r1 / 180.0 * M_PI; // convert to radians
+ int rd = w/2;
+ int x1 = x + rd;
+ int y1 = y + rd;
+ int x2 = x1 + lrint(cos(r1) * double(rd));
+ int y2 = y1 + lrint(sin(r1) * double(rd));
+ p.drawLine(x1, y1, x2, y2);
+
+ //-----------------------------------------
+ // draw center mark
+ //-----------------------------------------
+
+ p.setPen(QPen(svc, 0));
+ p.setBrush(svc);
+ if (_center) {
+ if (points)
+ delete points;
+ qreal x = ar.width() / 2 + ar.x();
+ qreal y = ar.y() - _markSize - _scaleWidth/2;
+ points = new QPainterPath(QPointF(x - markSize2, y));
+ points->lineTo(x + markSize2, y);
+ points->lineTo(x, _markSize + y);
+ points->closeSubpath();
+ p.drawPath(*points);
+ }
+
+ //-----------------------------------------
+ // draw text
+ //-----------------------------------------
+
+ if (!_text.isEmpty()) {
+ p.drawText(rect(), Qt::AlignBottom | Qt::AlignHCenter, _text);
+ }
+ }
+}
+
diff --git a/muse2/awl/knob.h b/muse2/awl/knob.h
new file mode 100644
index 00000000..b7be932b
--- /dev/null
+++ b/muse2/awl/knob.h
@@ -0,0 +1,85 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AWLKNOB_H__
+#define __AWLKNOB_H__
+
+#include "aslider.h"
+// #include <QtDesigner/QDesignerExportWidget>
+
+namespace Awl {
+
+//---------------------------------------------------------
+// Knob
+//
+//! Base class of all dialer type input widgets.
+//
+//! xxxxxxxxx
+//!
+//---------------------------------------------------------
+
+class Q_DECL_EXPORT Knob : public AbstractSlider {
+ Q_OBJECT
+ Q_PROPERTY(int scaleSize READ scaleSize WRITE setScaleSize)
+ Q_PROPERTY(int markSize READ markSize WRITE setMarkSize)
+ Q_PROPERTY(int border READ border WRITE setBorder)
+ Q_PROPERTY(QString text READ text WRITE setText)
+
+ int _scaleSize; //! scale size in degrees
+ int _markSize;
+ int _border;
+ QPainterPath* points;
+
+ virtual void paintEvent(QPaintEvent*);
+ virtual void mousePressEvent(QMouseEvent*);
+ virtual void mouseReleaseEvent(QMouseEvent*);
+ virtual void mouseMoveEvent(QMouseEvent*);
+
+ protected:
+ int startY;
+ QString _text;
+
+ signals:
+ void sliderPressed(int);
+ void sliderReleased(int);
+
+ public:
+ Knob(QWidget* parent = 0);
+ ~Knob();
+ virtual QSize sizeHint() const { return QSize(50, 50); }
+ virtual int heightForWidth(int w) { return w; }
+
+ //! return text decoration
+ QString text() const { return _text; }
+ void setText(const QString& s);
+
+ //! return scale size in degrees
+ int scaleSize() const { return _scaleSize; }
+ void setScaleSize(int val);
+ int markSize() const { return _markSize; }
+ void setMarkSize(int val);
+ int border() const { return _border; }
+ void setBorder(int val);
+ };
+
+}
+
+#endif
+
diff --git a/muse2/awl/ltest.cpp b/muse2/awl/ltest.cpp
new file mode 100644
index 00000000..55fe1749
--- /dev/null
+++ b/muse2/awl/ltest.cpp
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include "awlplugin.h"
+
+//---------------------------------------------------------
+// main
+//---------------------------------------------------------
+
+int main(int /*argc*/, char* /*argv*/[])
+ {
+ printf("Hello MusE\n");
+ new KnobPlugin;
+ return 0;
+ }
+
diff --git a/muse2/awl/metronom.xpm b/muse2/awl/metronom.xpm
new file mode 100644
index 00000000..d16a2fb5
--- /dev/null
+++ b/muse2/awl/metronom.xpm
@@ -0,0 +1,24 @@
+/* XPM */
+static char *metronom_xpm[]={
+"18 18 3 1",
+". c None",
+"# c #000000",
+"a c #0000ff",
+".........##.......",
+".........##.......",
+"........###....a..",
+".......###.#..aaa.",
+".......##..#.aaa..",
+"......###...#aa...",
+"......##....aaa...",
+".....##....aaa....",
+"....###...aaa#....",
+"....##....aa.#....",
+"...###...aa...#...",
+"..###...aaa...#...",
+"..##...aaa....#...",
+".###...aaa.....#..",
+".##....aa......#..",
+"###.....a.......#.",
+"##################",
+"##################"};
diff --git a/muse2/awl/midimeter.cpp b/muse2/awl/midimeter.cpp
new file mode 100644
index 00000000..312e5efe
--- /dev/null
+++ b/muse2/awl/midimeter.cpp
@@ -0,0 +1,137 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "fastlog.h"
+#include "midimeter.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// MidiMeter
+//---------------------------------------------------------
+
+MidiMeter::MidiMeter(QWidget* parent)
+ : Slider(parent)
+ {
+ setRange(0.0f, 127.0f);
+ setLineStep(2);
+ setPageStep(4);
+
+ setScaleWidth(7);
+ _meterWidth = _scaleWidth * 3;
+ meterval = 0.0f;
+ }
+
+//---------------------------------------------------------
+// setMeterVal
+// v - 0.0 < 1.0
+//---------------------------------------------------------
+
+void MidiMeter::setMeterVal(double v)
+ {
+ if (v < 0.001)
+ v = .0f;
+ if (meterval != v) {
+ meterval = v;
+ update();
+ }
+ }
+
+//---------------------------------------------------------
+// mouseDoubleClickEvent
+//---------------------------------------------------------
+
+void MidiMeter::mouseDoubleClickEvent(QMouseEvent*)
+ {
+ _value = _minValue;
+ valueChange();
+ update();
+ }
+
+//---------------------------------------------------------
+// paintEvent
+//---------------------------------------------------------
+
+void MidiMeter::paintEvent(QPaintEvent* ev)
+ {
+ int pixel = height() - sliderSize().height();
+ double range = maxValue() - minValue();
+ int ppos = int(pixel * (_value - minValue()) / range);
+ if (_invert)
+ ppos = pixel - ppos;
+
+ QRect rr(ev->rect());
+ QPainter p(this);
+
+ QColor sc(isEnabled() ? _scaleColor : Qt::gray);
+ QColor svc(isEnabled() ? _scaleValueColor : Qt::gray);
+ p.setBrush(svc);
+
+ int h = height();
+ int kh = sliderSize().height();
+
+ //---------------------------------------------------
+ // draw meter
+ //---------------------------------------------------
+
+ int mw = _meterWidth;
+ int x = 0;
+
+ int y1 = kh / 2;
+ int y3 = h - y1;
+
+ int mh = h - kh;
+
+ p.setPen(Qt::white);
+ h = lrint(meterval * mh);
+ if (h < 0)
+ h = 0;
+ else if (h > mh)
+ h = mh;
+ p.fillRect(x, y3-h, mw, h, QBrush(0x00ff00)); // green
+ p.fillRect(x, y1, mw, mh-h, QBrush(0x007000)); // dark green
+ x += mw;
+
+#if 0
+ //---------------------------------------------------
+ // draw scale
+ //---------------------------------------------------
+
+ x += _scaleWidth/2;
+
+ p.setPen(QPen(sc, _scaleWidth));
+ p.drawLine(x, y1, x, y2);
+ p.setPen(QPen(svc, _scaleWidth));
+ p.drawLine(x, y2, x, y3);
+
+ //---------------------------------------------------
+ // draw slider
+ //---------------------------------------------------
+
+ x += _scaleWidth/2;
+ p.setPen(QPen(svc, 0));
+ points.setPoint(0, x, y2);
+ points.setPoint(1, x + kw, y2 - kh/2);
+ points.setPoint(2, x + kw, y2 + kh/2);
+ p.drawConvexPolygon(points);
+#endif
+ }
+}
+
diff --git a/muse2/awl/midimeter.h b/muse2/awl/midimeter.h
new file mode 100644
index 00000000..2b0d3518
--- /dev/null
+++ b/muse2/awl/midimeter.h
@@ -0,0 +1,56 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AWLMIDIMETER_H__
+#define __AWLMIDIMETER_H__
+
+#include "slider.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// MidiMeter
+//---------------------------------------------------------
+
+class MidiMeter : public Slider
+ {
+ Q_PROPERTY(int meterWidth READ meterWidth WRITE setMeterWidth)
+ Q_OBJECT
+
+ double meterval;
+ int _meterWidth;
+
+ virtual void paintEvent(QPaintEvent*);
+
+ protected:
+ virtual void mouseDoubleClickEvent(QMouseEvent*);
+
+ public slots:
+ void setMeterVal(double value);
+
+ public:
+ MidiMeter(QWidget* parent = 0);
+ int meterWidth() const { return _meterWidth; }
+ void setMeterWidth(int v) { _meterWidth = v; }
+ };
+}
+
+#endif
+
diff --git a/muse2/awl/midimslider.cpp b/muse2/awl/midimslider.cpp
new file mode 100644
index 00000000..92325d4a
--- /dev/null
+++ b/muse2/awl/midimslider.cpp
@@ -0,0 +1,143 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "fastlog.h"
+#include "midimslider.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// MidiMeterSlider
+//---------------------------------------------------------
+
+MidiMeterSlider::MidiMeterSlider(QWidget* parent)
+ : Slider(parent)
+ {
+ setRange(0.0f, 127.0f);
+ setLineStep(2);
+ setPageStep(4);
+
+ setScaleWidth(7);
+ _meterWidth = _scaleWidth * 3;
+ meterval = 0.0f;
+ }
+
+//---------------------------------------------------------
+// setMeterVal
+// v - 0.0 < 1.0
+//---------------------------------------------------------
+
+void MidiMeterSlider::setMeterVal(double v)
+ {
+ if (v < 0.001)
+ v = .0f;
+ if (meterval != v) {
+ meterval = v;
+ update();
+ }
+ }
+
+//---------------------------------------------------------
+// mouseDoubleClickEvent
+//---------------------------------------------------------
+
+void MidiMeterSlider::mouseDoubleClickEvent(QMouseEvent*)
+ {
+ _value = _minValue;
+ valueChange();
+ update();
+ }
+
+//---------------------------------------------------------
+// drawScale
+//---------------------------------------------------------
+
+void MidiMeterSlider::paintEvent(QPaintEvent* ev)
+ {
+ int pixel = height() - sliderSize().height();
+ double range = maxValue() - minValue();
+ int ppos = int(pixel * (_value - minValue()) / range);
+ if (_invert)
+ ppos = pixel - ppos;
+
+ QRect rr(ev->rect());
+ QPainter p(this);
+
+ QColor sc(isEnabled() ? _scaleColor : Qt::gray);
+ QColor svc(isEnabled() ? _scaleValueColor : Qt::gray);
+ p.setBrush(svc);
+
+ int h = height();
+// int kw = sliderSize().width();
+ int kh = sliderSize().height();
+
+ //---------------------------------------------------
+ // draw meter
+ //---------------------------------------------------
+
+ int mw = _meterWidth;
+ int x = 0;
+
+ int y1 = kh / 2;
+ int y2 = h - (ppos + y1);
+ int y3 = h - y1;
+
+ int mh = h - kh;
+
+ p.setPen(Qt::white);
+ h = lrint(meterval * mh);
+ if (h < 0)
+ h = 0;
+ else if (h > mh)
+ h = mh;
+ //QColor qc;
+ //float v = 5.0/6.0 + 1.0/6.0 * meterval;
+ //qc.setHsvF(1.0/3.0, 1.0, (v<=1.0?v:1.0));
+ p.fillRect(x, y3-h, mw, h, QBrush(0x00ff00)); // green
+ //p.fillRect(x, y3-h, mw, h, QBrush(qc)); // green get a bit darker
+ p.fillRect(x, y1, mw, mh-h, QBrush(0x007000)); // dark green
+ x += mw;
+
+ //---------------------------------------------------
+ // draw scale
+ //---------------------------------------------------
+
+// x += _scaleWidth/2;
+
+// p.setPen(QPen(sc, _scaleWidth));
+// p.drawLine(x, y1, x, y2);
+// p.setPen(QPen(svc, _scaleWidth));
+// p.drawLine(x, y2, x, y3);
+
+ p.fillRect(x, y1, _scaleWidth, y2-y1, sc);
+ p.fillRect(x, y2, _scaleWidth, y3-y2, svc);
+
+ //---------------------------------------------------
+ // draw slider
+ //---------------------------------------------------
+
+ x += _scaleWidth/2;
+ p.setPen(QPen(svc, 0));
+ p.translate(QPointF(x, y2));
+ p.setRenderHint(QPainter::Antialiasing, true);
+ p.drawPath(*points);
+ }
+}
+
diff --git a/muse2/awl/midimslider.h b/muse2/awl/midimslider.h
new file mode 100644
index 00000000..a2a2bdaf
--- /dev/null
+++ b/muse2/awl/midimslider.h
@@ -0,0 +1,56 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AWLMIDIMSLIDER_H__
+#define __AWLMIDIMSLIDER_H__
+
+#include "slider.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// MidiMeterSlider
+//---------------------------------------------------------
+
+class MidiMeterSlider : public Slider
+ {
+ Q_PROPERTY(int meterWidth READ meterWidth WRITE setMeterWidth)
+ Q_OBJECT
+
+ double meterval;
+ int _meterWidth;
+
+ virtual void paintEvent(QPaintEvent*);
+
+ protected:
+ virtual void mouseDoubleClickEvent(QMouseEvent*);
+
+ public slots:
+ void setMeterVal(double value);
+
+ public:
+ MidiMeterSlider(QWidget* parent = 0);
+ int meterWidth() const { return _meterWidth; }
+ void setMeterWidth(int v) { _meterWidth = v; }
+ };
+}
+
+#endif
+
diff --git a/muse2/awl/midipanentry.cpp b/muse2/awl/midipanentry.cpp
new file mode 100644
index 00000000..5e4e4f9a
--- /dev/null
+++ b/muse2/awl/midipanentry.cpp
@@ -0,0 +1,47 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "fastlog.h"
+#include "midipanentry.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// MidiPanEntry
+//---------------------------------------------------------
+
+MidiPanEntry::MidiPanEntry(QWidget* parent)
+ : FloatEntry(parent)
+ {
+ setRange(-64.0f, 63.0f);
+ setFrame(true);
+ setPrecision(0);
+ }
+
+//---------------------------------------------------------
+// valueChange
+//---------------------------------------------------------
+
+void MidiPanEntry::valueChange()
+ {
+ emit valueChanged(_value + 64.0f, _id);
+ }
+}
+
diff --git a/muse2/awl/midipanentry.h b/muse2/awl/midipanentry.h
new file mode 100644
index 00000000..25f7333a
--- /dev/null
+++ b/muse2/awl/midipanentry.h
@@ -0,0 +1,48 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AWLMIDIPANENTRY_H__
+#define __AWLMIDIPANENTRY_H__
+
+#include "floatentry.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// MidiPanEntry
+//---------------------------------------------------------
+
+class MidiPanEntry : public FloatEntry {
+ Q_OBJECT
+
+ protected:
+ virtual void valueChange();
+
+ public slots:
+ virtual void setValue(double v) {
+ FloatEntry::setValue(v - 64.0f);
+ }
+ public:
+ MidiPanEntry(QWidget* parent);
+ virtual double value() const { return _value + 64.0f; }
+ };
+}
+
+#endif
diff --git a/muse2/awl/midipanknob.cpp b/muse2/awl/midipanknob.cpp
new file mode 100644
index 00000000..a2530119
--- /dev/null
+++ b/muse2/awl/midipanknob.cpp
@@ -0,0 +1,37 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "midipanknob.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// MidiPanKnob
+//---------------------------------------------------------
+
+MidiPanKnob::MidiPanKnob(QWidget* parent)
+ : Knob(parent)
+ {
+ setCenter(true);
+ setRange(-64.0f, 63.0f);
+ setLineStep(1.0f);
+ setPageStep(10.0f);
+ }
+}
diff --git a/muse2/awl/midipanknob.h b/muse2/awl/midipanknob.h
new file mode 100644
index 00000000..9b628e6b
--- /dev/null
+++ b/muse2/awl/midipanknob.h
@@ -0,0 +1,55 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AWLMIDIPANKNOB_H__
+#define __AWLMIDIPANKNOB_H__
+
+#include "knob.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// MidiPanKnob
+//! MidiPan Knob entry widget
+//
+//! This widget implements a centered floating point
+//! knob used to adjust the pan position in an audio
+//! mixer.
+//---------------------------------------------------------
+
+class MidiPanKnob : public Knob {
+ Q_OBJECT
+
+ virtual void valueChange() {
+ emit valueChanged(_value + 64.0f, _id);
+ }
+
+ public slots:
+ virtual void setValue(double v) {
+ AbstractSlider::setValue(v - 64.0f);
+ }
+ public:
+ MidiPanKnob(QWidget* parent = 0);
+ virtual double value() const { return _value + 64.0f; }
+ };
+}
+
+#endif
+
diff --git a/muse2/awl/midivolentry.cpp b/muse2/awl/midivolentry.cpp
new file mode 100644
index 00000000..0b74afcc
--- /dev/null
+++ b/muse2/awl/midivolentry.cpp
@@ -0,0 +1,50 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "fastlog.h"
+#include "midivolentry.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// MidiVolEntry
+//---------------------------------------------------------
+
+MidiVolEntry::MidiVolEntry(QWidget* parent)
+ : FloatEntry(parent)
+ {
+ _max = 127;
+ setRange(-98.0f, 0.0f);
+ setSpecialText(tr("off"));
+ setSuffix(tr("db"));
+ setFrame(true);
+ setPrecision(0);
+ }
+
+//---------------------------------------------------------
+// setValue
+//---------------------------------------------------------
+
+void MidiVolEntry::setValue(double v)
+ {
+ FloatEntry::setValue(-fast_log10(double(_max*_max)/(v*v))*20.0f);
+ }
+}
+
diff --git a/muse2/awl/midivolentry.h b/muse2/awl/midivolentry.h
new file mode 100644
index 00000000..99155877
--- /dev/null
+++ b/muse2/awl/midivolentry.h
@@ -0,0 +1,47 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AWLMIDIVOLENTRY_H__
+#define __AWLMIDIVOLENTRY_H__
+
+#include "floatentry.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// MidiVolEntry
+//---------------------------------------------------------
+
+class MidiVolEntry : public FloatEntry {
+ Q_OBJECT
+ Q_PROPERTY(int max READ max WRITE setMax)
+
+ int _max;
+
+ public:
+ virtual void setValue(double);
+ void setMax(int val) { _max = val; }
+ int max() const { return _max; }
+ MidiVolEntry(QWidget* parent);
+ };
+}
+
+#endif
+
diff --git a/muse2/awl/mslider.cpp b/muse2/awl/mslider.cpp
new file mode 100644
index 00000000..63c3ea4e
--- /dev/null
+++ b/muse2/awl/mslider.cpp
@@ -0,0 +1,273 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "fastlog.h"
+
+#include "mslider.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// MeterSlider
+//---------------------------------------------------------
+
+MeterSlider::MeterSlider(QWidget* parent)
+ : VolSlider(parent)
+ {
+ setAttribute(Qt::WA_NoSystemBackground, true);
+// setAutoFillBackground(true);
+ _channel = 0;
+ yellowScale = -16; //-10;
+ redScale = 0;
+ _meterWidth = _scaleWidth * 3;
+ setChannel(1);
+ setMinimumHeight(50);
+ }
+
+//---------------------------------------------------------
+// sizeHint
+//---------------------------------------------------------
+
+QSize MeterSlider::sizeHint() const
+ {
+ int w = _meterWidth + _scaleWidth + _scaleWidth + 30;
+ return orientation() == Qt::Vertical ? QSize(w, 200) : QSize(200, w);
+ }
+
+//---------------------------------------------------------
+// setChannel
+//---------------------------------------------------------
+
+void MeterSlider::setChannel(int n)
+ {
+ if (n > _channel) {
+ for (int i = _channel; i < n; ++i) {
+ meterval.push_back(0.0f);
+ meterPeak.push_back(0.0f);
+ }
+ }
+ _channel = n;
+ }
+
+//---------------------------------------------------------
+// setMeterVal
+//---------------------------------------------------------
+
+void MeterSlider::setMeterVal(int channel, double v, double peak)
+ {
+ bool mustRedraw = false;
+ if (meterval[channel] != v) {
+ meterval[channel] = v;
+ mustRedraw = true;
+ }
+ if (peak != meterPeak[channel]) {
+ meterPeak[channel] = peak;
+ mustRedraw = true;
+ }
+ if (mustRedraw) {
+ int kh = sliderSize().height();
+ int mh = height() - kh;
+ update(20, kh / 2, _meterWidth-1, mh);
+ }
+ }
+
+//---------------------------------------------------------
+// resetPeaks
+// reset peak and overflow indicator
+//---------------------------------------------------------
+
+void MeterSlider::resetPeaks()
+ {
+ for (int i = 0; i < _channel; ++i)
+ meterPeak[i] = meterval[i];
+ update();
+ }
+
+//---------------------------------------------------------
+// resizeEvent
+//---------------------------------------------------------
+
+void MeterSlider::resizeEvent(QResizeEvent* /*ev*/)
+ {
+ int h = height();
+ int kh = sliderSize().height();
+ int mh = h - kh;
+ int mw = _meterWidth / _channel;
+
+ onPm = QPixmap(mw, mh);
+ offPm = QPixmap(mw, mh);
+
+ double range = maxValue() - minValue();
+ int h1 = mh - lrint((maxValue() - redScale) * mh / range);
+ int h2 = mh - lrint((maxValue() - yellowScale) * mh / range);
+
+ QColor yellowRed;
+ yellowRed.setHsv(QColor(Qt::yellow).hue()-8,
+ QColor(Qt::yellow).saturation(),
+ QColor(Qt::yellow).value());
+ QColor yellRedRed;
+ yellRedRed.setHsv(QColor(Qt::yellow).hue()-16,
+ QColor(Qt::yellow).saturation(),
+ QColor(Qt::yellow).value());
+
+ QLinearGradient linearGrad(QPointF(0, 0), QPointF(0, mh));
+ linearGrad.setColorAt(0, Qt::red);
+ linearGrad.setColorAt(1-(double)(h1-5)/(double)mh, yellRedRed);
+ linearGrad.setColorAt(1-(double)(h1-6)/(double)mh, yellowRed);
+ linearGrad.setColorAt(1-(double)h2/(double)mh, Qt::yellow);
+ linearGrad.setColorAt(1, Qt::green);
+
+ QColor darkYellowRed;
+ darkYellowRed.setHsv(QColor(Qt::darkYellow).hue()-8,
+ QColor(Qt::darkYellow).saturation(),
+ QColor(Qt::darkYellow).value());
+ QColor darkYellRedRed;
+ darkYellRedRed.setHsv(QColor(Qt::darkYellow).hue()-16,
+ QColor(Qt::darkYellow).saturation(),
+ QColor(Qt::darkYellow).value());
+ QLinearGradient linearDarkGrad(QPointF(0, 0), QPointF(0, mh));
+ linearDarkGrad.setColorAt(0, Qt::darkRed);
+ linearDarkGrad.setColorAt(1-(double)(h1-5)/(double)mh, darkYellRedRed);
+ linearDarkGrad.setColorAt(1-(double)(h1-6)/(double)mh, darkYellowRed);
+ linearDarkGrad.setColorAt(1-(double)h2/(double)mh, Qt::darkYellow);
+ linearDarkGrad.setColorAt(1, Qt::darkGreen);
+
+ QPainter p;
+ p.begin(&onPm);
+ p.fillRect(0, 0, mw, mh, linearGrad);
+ p.end();
+ p.begin(&offPm);
+ p.fillRect(0, 0, mw, mh, linearDarkGrad);
+ p.end();
+ }
+
+//---------------------------------------------------------
+// paintEvent
+//---------------------------------------------------------
+
+void MeterSlider::paintEvent(QPaintEvent* ev)
+ {
+ int pixel = height() - sliderSize().height();
+ double range = maxValue() - minValue();
+ int ppos = int(pixel * (_value - minValue()) / range);
+ if (_invert)
+ ppos = pixel - ppos;
+
+ QPainter p(this);
+ p.setRenderHint(QPainter::Antialiasing, false);
+
+ int h = height();
+ int kh = sliderSize().height();
+
+ //---------------------------------------------------
+ // draw meter
+ //---------------------------------------------------
+
+ int mw = _meterWidth / _channel;
+ int x = 20;
+ int y1 = kh / 2;
+ int y3 = h - y1;
+
+ int mh = h - kh;
+ p.setPen(QPen(Qt::white, 2));
+
+ for (int i = 0; i < _channel; ++i) {
+ int h = mh - (lrint(fast_log10(meterval[i]) * -20.0f * mh / range));
+ if (h < 0)
+ h = 0;
+ else if (h > mh)
+ h = mh;
+
+ p.drawPixmap(x, y1+mh-h, mw, h, onPm, 0, y1+mh-h, mw, h);
+ p.drawPixmap(x, y1, mw, mh-h, offPm, 0, y1, mw, mh-h);
+
+ //---------------------------------------------------
+ // draw peak line
+ //---------------------------------------------------
+
+ h = mh - (lrint(fast_log10(meterPeak[i]) * -20.0f * mh / range));
+ if (h > mh)
+ h = mh;
+ if (h > 0)
+ p.drawLine(x, y3-h, x+mw, y3-h);
+
+ x += mw;
+ }
+
+ // optimize common case:
+ if (ev->rect() == QRect(20, kh/2, _meterWidth-1, mh))
+ return;
+
+ QColor sc(isEnabled() ? _scaleColor : Qt::gray);
+ QColor svc(isEnabled() ? _scaleValueColor : Qt::gray);
+ p.setBrush(svc);
+
+ //---------------------------------------------------
+ // draw scale
+ //---------------------------------------------------
+
+ int y2 = h - (ppos + y1);
+ p.fillRect(x, y1, _scaleWidth, y2-y1, sc);
+ p.fillRect(x, y2, _scaleWidth, y3-y2, svc);
+
+ //---------------------------------------------------
+ // draw tick marks
+ //---------------------------------------------------
+
+ QFont f(p.font());
+ f.setPointSize(6);
+ p.setFont(f);
+ p.setPen(QPen(Qt::darkGray, 2));
+ QFontMetrics fm(f);
+ int xt = 20 - fm.width("00") - 5;
+
+ QString s;
+ for (int i = 10; i < 70; i += 10) {
+ h = y1 + lrint(i * mh / range);
+ s.setNum(i - 10);
+ p.drawText(xt, h - 3, s);
+ p.drawLine(15, h, 20, h);
+ }
+
+ //---------------------------------------------------
+ // draw slider
+ //---------------------------------------------------
+
+ x += _scaleWidth/2;
+ p.setPen(QPen(svc, 0));
+ p.translate(QPointF(x, y2));
+ p.setRenderHint(QPainter::Antialiasing, true);
+ p.drawPath(*points);
+ }
+
+//---------------------------------------------------------
+// mousePressEvent
+//---------------------------------------------------------
+
+void MeterSlider::mousePressEvent(QMouseEvent* ev)
+ {
+ if (ev->pos().x() < _meterWidth) {
+ emit meterClicked();
+ return;
+ }
+ VolSlider::mousePressEvent(ev);
+ }
+}
+
diff --git a/muse2/awl/mslider.h b/muse2/awl/mslider.h
new file mode 100644
index 00000000..4ae888b1
--- /dev/null
+++ b/muse2/awl/mslider.h
@@ -0,0 +1,68 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AWLMSLIDER_H__
+#define __AWLMSLIDER_H__
+
+#include "volslider.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// MeterSlider
+// volume slider with meter display
+//---------------------------------------------------------
+
+class MeterSlider : public VolSlider
+ {
+ Q_PROPERTY(int meterWidth READ meterWidth WRITE setMeterWidth)
+ Q_PROPERTY(int channel READ channel WRITE setChannel)
+ Q_OBJECT
+
+ int _channel;
+ std::vector<double> meterval;
+ std::vector<double> meterPeak;
+ int yellowScale, redScale;
+ int _meterWidth;
+ QPixmap onPm, offPm; // cached pixmap values
+
+ virtual void mousePressEvent(QMouseEvent*);
+ virtual void paintEvent(QPaintEvent*);
+ virtual void resizeEvent(QResizeEvent*);
+
+ signals:
+ void meterClicked();
+
+ public slots:
+ void resetPeaks();
+ void setMeterVal(int channel, double value, double peak);
+
+ public:
+ MeterSlider(QWidget* parent = 0);
+ void setChannel(int n);
+ int channel() const { return _channel; }
+ int meterWidth() const { return _meterWidth; }
+ void setMeterWidth(int v) { _meterWidth = v; }
+ virtual QSize sizeHint() const;
+ };
+}
+
+#endif
+
diff --git a/muse2/awl/panentry.cpp b/muse2/awl/panentry.cpp
new file mode 100644
index 00000000..0cc098c2
--- /dev/null
+++ b/muse2/awl/panentry.cpp
@@ -0,0 +1,35 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "panentry.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// PanEntry
+//---------------------------------------------------------
+
+PanEntry::PanEntry(QWidget* parent)
+ : FloatEntry(parent)
+ {
+ setRange(-1.0, 1.0);
+ }
+}
+
diff --git a/muse2/awl/panentry.h b/muse2/awl/panentry.h
new file mode 100644
index 00000000..01689580
--- /dev/null
+++ b/muse2/awl/panentry.h
@@ -0,0 +1,40 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AWLPANENTRY_H__
+#define __AWLPANENTRY_H__
+
+#include "floatentry.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// PanEntry
+//---------------------------------------------------------
+
+class PanEntry : public FloatEntry {
+ Q_OBJECT
+
+ public:
+ PanEntry(QWidget*);
+ };
+}
+
+#endif
diff --git a/muse2/awl/panknob.cpp b/muse2/awl/panknob.cpp
new file mode 100644
index 00000000..083aa2e0
--- /dev/null
+++ b/muse2/awl/panknob.cpp
@@ -0,0 +1,38 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "panknob.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// PanKnob
+//---------------------------------------------------------
+
+PanKnob::PanKnob(QWidget* parent)
+ : Knob(parent)
+ {
+ setCenter(true);
+ setRange(-1.0f, 1.0f);
+ setLineStep(0.01f);
+ setPageStep(0.1f);
+ }
+}
+
diff --git a/muse2/awl/panknob.h b/muse2/awl/panknob.h
new file mode 100644
index 00000000..d8bf2d87
--- /dev/null
+++ b/muse2/awl/panknob.h
@@ -0,0 +1,46 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AWLPANKNOB_H__
+#define __AWLPANKNOB_H__
+
+#include "knob.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// PanKnob
+//! Pan Knob entry widget
+//
+//! This widget implements a centered floating point
+//! knob used to adjust the pan position in an audio
+//! mixer.
+//---------------------------------------------------------
+
+class PanKnob : public Knob {
+ Q_OBJECT
+
+ public:
+ PanKnob(QWidget* parent = 0);
+ };
+}
+
+#endif
+
diff --git a/muse2/awl/pitchedit.cpp b/muse2/awl/pitchedit.cpp
new file mode 100644
index 00000000..18136074
--- /dev/null
+++ b/muse2/awl/pitchedit.cpp
@@ -0,0 +1,89 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "pitchedit.h"
+#include "utils.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// PitchEdit
+//---------------------------------------------------------
+
+PitchEdit::PitchEdit(QWidget* parent)
+ : QSpinBox(parent)
+ {
+ setRange(0, 127);
+ deltaMode = false;
+ }
+
+//---------------------------------------------------------
+// keyPressEvent
+//---------------------------------------------------------
+
+void PitchEdit::keyPressEvent(QKeyEvent* ev)
+ {
+ if (ev->key() == Qt::Key_Return)
+ emit returnPressed();
+ else if (ev->key() == Qt::Key_Escape)
+ emit escapePressed();
+ }
+
+//---------------------------------------------------------
+// mapValueToText
+//---------------------------------------------------------
+
+QString PitchEdit::mapValueToText(int v)
+ {
+ if (deltaMode) {
+ QString s;
+ s.setNum(v);
+ return s;
+ }
+ else
+ return pitch2string(v);
+ }
+
+//---------------------------------------------------------
+// mapTextToValue
+//---------------------------------------------------------
+
+int PitchEdit::mapTextToValue(bool* ok)
+ {
+printf("AwlPitchEdit: mapTextToValue: not impl.\n");
+ if (ok)
+ *ok = false;
+ return 0;
+ }
+
+//---------------------------------------------------------
+// setDeltaMode
+//---------------------------------------------------------
+
+void PitchEdit::setDeltaMode(bool val)
+ {
+ deltaMode = val;
+ if (deltaMode)
+ setRange(-127, 127);
+ else
+ setRange(0, 127);
+ }
+}
+
diff --git a/muse2/awl/pitchedit.h b/muse2/awl/pitchedit.h
new file mode 100644
index 00000000..dd0ba4c7
--- /dev/null
+++ b/muse2/awl/pitchedit.h
@@ -0,0 +1,50 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AWLPITCHEDIT_H__
+#define __AWLPITCHEDIT_H__
+
+namespace Awl {
+
+//---------------------------------------------------------
+// PitchEdit
+//---------------------------------------------------------
+
+class PitchEdit : public QSpinBox {
+ Q_OBJECT
+
+ bool deltaMode;
+
+ protected:
+ virtual QString mapValueToText(int v);
+ virtual int mapTextToValue(bool* ok);
+ virtual void keyPressEvent(QKeyEvent*);
+
+ signals:
+ void returnPressed();
+ void escapePressed();
+
+ public:
+ PitchEdit(QWidget* parent);
+ void setDeltaMode(bool);
+ };
+}
+
+#endif
diff --git a/muse2/awl/pitchlabel.cpp b/muse2/awl/pitchlabel.cpp
new file mode 100644
index 00000000..1d7149f6
--- /dev/null
+++ b/muse2/awl/pitchlabel.cpp
@@ -0,0 +1,106 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "pitchedit.h"
+#include "pitchlabel.h"
+#include "utils.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// PitchLabel
+//---------------------------------------------------------
+
+PitchLabel::PitchLabel()
+ {
+ _pitchMode = true;
+ _value = -1;
+ setFrameStyle(WinPanel | Sunken);
+ setLineWidth(2);
+ setMidLineWidth(3);
+ setValue(0);
+ int fw = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
+ setIndent(fw);
+ }
+
+//---------------------------------------------------------
+// setPitchMode
+//---------------------------------------------------------
+
+void PitchLabel::setPitchMode(bool val)
+ {
+ _pitchMode = val;
+ }
+
+//---------------------------------------------------------
+// sizeHint
+//---------------------------------------------------------
+
+QSize PitchLabel::sizeHint() const
+ {
+ QFontMetrics fm(font());
+ int fw = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
+ int h = fm.height() + fw * 2;
+// int w = 2 + fm.width(QString("A#8")) + fw * 4;
+ int w = 2 + fm.width(QString("-9999")) + fw * 4; // must display 14Bit controller values
+ return QSize(w, h).expandedTo(QApplication::globalStrut());
+ }
+
+//---------------------------------------------------------
+// setValue
+//---------------------------------------------------------
+
+void PitchLabel::setValue(int val)
+ {
+ if (val == _value)
+ return;
+ _value = val;
+ QString s;
+ if (_pitchMode)
+ s = pitch2string(_value);
+ else
+ s.sprintf("%d", _value);
+ setText(s);
+ }
+
+//---------------------------------------------------------
+// setInt
+//---------------------------------------------------------
+
+void PitchLabel::setInt(int val)
+ {
+ if (_pitchMode)
+ setPitchMode(false);
+ setValue(val);
+ }
+
+//---------------------------------------------------------
+// setPitch
+//---------------------------------------------------------
+
+void PitchLabel::setPitch(int val)
+ {
+ if (!_pitchMode) {
+ setPitchMode(true);
+ }
+ setValue(val);
+ }
+}
+
diff --git a/muse2/awl/pitchlabel.h b/muse2/awl/pitchlabel.h
new file mode 100644
index 00000000..36a3cbfa
--- /dev/null
+++ b/muse2/awl/pitchlabel.h
@@ -0,0 +1,51 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AWLPITCHLABEL_H__
+#define __AWLPITCHLABEL_H__
+
+namespace Awl {
+
+//---------------------------------------------------------
+// PitchLabel
+//---------------------------------------------------------
+
+class PitchLabel : public QLabel {
+ bool _pitchMode;
+ int _value;
+ Q_OBJECT
+
+ protected:
+ QSize sizeHint() const;
+
+ public slots:
+ void setValue(int);
+ void setInt(int);
+ void setPitch(int);
+
+ public:
+ PitchLabel();
+ int value() const { return _value; }
+ void setPitchMode(bool val);
+ bool pitchMode() const { return _pitchMode; }
+ };
+}
+
+#endif
diff --git a/muse2/awl/posedit.cpp b/muse2/awl/posedit.cpp
new file mode 100644
index 00000000..4f8b19b2
--- /dev/null
+++ b/muse2/awl/posedit.cpp
@@ -0,0 +1,441 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "al/al.h"
+#include "awl.h"
+#include "posedit.h"
+#include "al/sig.h"
+
+namespace Awl {
+
+ using AL::mtcType;
+ using AL::sigmap;
+
+//---------------------------------------------------------
+// PosEdit
+//---------------------------------------------------------
+
+PosEdit::PosEdit(QWidget* parent)
+ : QAbstractSpinBox(parent)
+ {
+ initialized = false;
+ setReadOnly(false);
+ setSmpte(false);
+ }
+
+void* PosEdit::operator new(size_t n)
+ {
+ void* p = new char[n];
+ memset(p, 0, n);
+ return p;
+ }
+
+PosEdit::~PosEdit()
+ {
+ }
+
+QSize PosEdit::sizeHint() const
+ {
+ QFontMetrics fm(font());
+ int fw = style()->pixelMetric(QStyle::PM_SpinBoxFrameWidth);
+ int h = fm.height() + fw * 2;
+ int w = fw * 4 + 10; // HACK: 10 = spinbox up/down arrows
+ if (_smpte)
+ w += 2 + fm.width('9') * 9 + fm.width(':') * 3 + fw * 4;
+ else
+ w += 2 + fm.width('9') * 9 + fm.width('.') * 2 + fw * 4;
+ return QSize(w, h).expandedTo(QApplication::globalStrut());
+ }
+
+//---------------------------------------------------------
+// event
+// filter Tab and Backtab key events
+//---------------------------------------------------------
+
+bool PosEdit::event(QEvent* event)
+ {
+ if (event->type() == QEvent::KeyPress) {
+ QKeyEvent* ke = static_cast<QKeyEvent*>(event);
+ int segment = curSegment();
+ if (ke->key() == Qt::Key_Backtab) {
+ if (_smpte) {
+ if (segment == 3) {
+ lineEdit()->setSelection(7, 2);
+ return true;
+ }
+ else if (segment == 2) {
+ lineEdit()->setSelection(4, 2);
+ return true;
+ }
+ else if (segment == 1) {
+ lineEdit()->setSelection(0, 3);
+ return true;
+ }
+ }
+ else {
+ if (segment == 2) {
+ lineEdit()->setSelection(5, 2);
+ return true;
+ }
+ if (segment == 1) {
+ lineEdit()->setSelection(0, 4);
+ return true;
+ }
+ }
+ }
+ if (ke->key() == Qt::Key_Tab) {
+ if (_smpte) {
+ if (segment == 0) {
+ lineEdit()->setSelection(4, 2);
+ return true;
+ }
+ else if (segment == 1) {
+ lineEdit()->setSelection(7, 2);
+ return true;
+ }
+ else if (segment == 2) {
+ lineEdit()->setSelection(10, 2);
+ return true;
+ }
+ }
+ else {
+ if (segment == 0) {
+ lineEdit()->setSelection(5, 2);
+ return true;
+ }
+ if (segment == 1) {
+ lineEdit()->setSelection(8, 3);
+ return true;
+ }
+ }
+ }
+ }
+ else if (event->type() == QEvent::FocusIn) {
+ QFocusEvent* fe = static_cast<QFocusEvent*>(event);
+ QAbstractSpinBox::focusInEvent(fe);
+ int segment = curSegment();
+ switch(segment) {
+ case 0: lineEdit()->setSelection(0,4); break;
+ case 1: lineEdit()->setSelection(5,2); break;
+ case 2: lineEdit()->setSelection(8,3); break;
+ }
+ return true;
+ }
+ return QAbstractSpinBox::event(event);
+ }
+
+//---------------------------------------------------------
+// setSmpte
+//---------------------------------------------------------
+
+void PosEdit::setSmpte(bool f)
+ {
+ _smpte = f;
+ if (_smpte)
+ lineEdit()->setInputMask("999:99:99:99");
+ else
+ lineEdit()->setInputMask("9999.99.999");
+ updateValue();
+ }
+
+//---------------------------------------------------------
+// setValue
+//---------------------------------------------------------
+
+void PosEdit::setValue(const Pos& time)
+ {
+ _pos = time;
+ updateValue();
+ }
+
+void PosEdit::setValue(const QString& s)
+ {
+ Pos time(s);
+ setValue(time);
+ }
+
+void PosEdit::setValue(int t)
+ {
+ Pos time(t);
+ setValue(time);
+ }
+
+//---------------------------------------------------------
+// updateValue
+//---------------------------------------------------------
+
+void PosEdit::updateValue()
+ {
+ char buffer[64];
+ if (_smpte) {
+ int minute, sec, frame, subframe;
+ _pos.msf(&minute, &sec, &frame, &subframe);
+ sprintf(buffer, "%03d:%02d:%02d:%02d", minute, sec, frame, subframe);
+ }
+ else {
+ int bar, beat;
+ int tick;
+ _pos.mbt(&bar, &beat, &tick);
+ sprintf(buffer, "%04d.%02d.%03d", bar+1, beat+1, tick);
+ }
+ lineEdit()->setText(buffer);
+ }
+
+//---------------------------------------------------------
+// stepEnables
+//---------------------------------------------------------
+
+QAbstractSpinBox::StepEnabled PosEdit::stepEnabled() const
+ {
+ int segment = curSegment();
+ QAbstractSpinBox::StepEnabled en = QAbstractSpinBox::StepUpEnabled | QAbstractSpinBox::StepDownEnabled;
+
+ if (_smpte) {
+ int minute, sec, frame, subframe;
+ _pos.msf(&minute, &sec, &frame, &subframe);
+ switch(segment) {
+ case 0:
+ if (minute == 0)
+ en &= ~QAbstractSpinBox::StepDownEnabled;
+ break;
+ case 1:
+ if (sec == 0)
+ en &= ~QAbstractSpinBox::StepDownEnabled;
+ else if (sec == 59)
+ en &= ~QAbstractSpinBox::StepUpEnabled;
+ break;
+ case 2:
+ if (frame == 0)
+ en &= ~QAbstractSpinBox::StepDownEnabled;
+ else if (frame == 23)
+ en &= ~QAbstractSpinBox::StepUpEnabled;
+ break;
+ case 3:
+ if (subframe == 0)
+ en &= ~QAbstractSpinBox::StepDownEnabled;
+ else if (subframe == 99)
+ en &= ~QAbstractSpinBox::StepUpEnabled;
+ break;
+ }
+ }
+ else {
+ int bar, beat;
+ unsigned tick;
+ AL::sigmap.tickValues(_pos.tick(), &bar, &beat, &tick);
+ unsigned tb = AL::sigmap.ticksBeat(_pos.tick());
+ unsigned tm = AL::sigmap.ticksMeasure(_pos.tick());
+ int bm = tm / tb;
+
+ switch (segment) {
+ case 0:
+ if (bar == 0)
+ en &= ~QAbstractSpinBox::StepDownEnabled;
+ break;
+ case 1:
+ if (beat == 0)
+ en &= ~QAbstractSpinBox::StepDownEnabled;
+ else {
+ if (beat >= (bm-1))
+ en &= ~QAbstractSpinBox::StepUpEnabled;
+ }
+ break;
+ case 2:
+ if (tick == 0)
+ en &= ~QAbstractSpinBox::StepDownEnabled;
+ else {
+ if (tick >= (tb-1))
+ en &= ~QAbstractSpinBox::StepUpEnabled;
+ }
+ break;
+ }
+ }
+ return en;
+ }
+
+//---------------------------------------------------------
+// fixup
+//---------------------------------------------------------
+
+void PosEdit::fixup(QString& input) const
+ {
+ printf("fixup <%s>\n", input.toLatin1().data());
+ }
+
+//---------------------------------------------------------
+// validate
+//---------------------------------------------------------
+
+QValidator::State PosEdit::validate(QString&,int&) const
+ {
+ // TODO
+// printf("validate\n");
+ return QValidator::Acceptable;
+ }
+
+//---------------------------------------------------------
+// curSegment
+//---------------------------------------------------------
+
+int PosEdit::curSegment() const
+ {
+ QLineEdit* le = lineEdit();
+ int pos = le->cursorPosition();
+ int segment = -1;
+
+ if (_smpte) {
+ if (pos >= 0 && pos <= 3)
+ segment = 0;
+ else if (pos >= 4 && pos <= 6)
+ segment = 1;
+ else if (pos >= 7 && pos <= 9)
+ segment = 2;
+ else if (pos >= 10)
+ segment = 3;
+ }
+ else {
+ if (pos >= 0 && pos <= 4)
+ segment = 0;
+ else if (pos >= 5 && pos <= 7)
+ segment = 1;
+ else if (pos >= 8)
+ segment = 2;
+ else
+ printf("curSegment = -1, pos %d\n", pos);
+ }
+ return segment;
+ }
+
+//---------------------------------------------------------
+// stepBy
+//---------------------------------------------------------
+
+void PosEdit::stepBy(int steps)
+ {
+ int segment = curSegment();
+ int selPos;
+ int selLen;
+
+ bool changed = false;
+
+ if (_smpte) {
+ int minute, sec, frame, subframe;
+ _pos.msf(&minute, &sec, &frame, &subframe);
+ switch(segment) {
+ case 0:
+ minute += steps;
+ if (minute < 0)
+ minute = 0;
+ selPos = 0;
+ selLen = 3;
+ break;
+ case 1:
+ sec += steps;
+ if (sec < 0)
+ sec = 0;
+ if (sec > 59)
+ sec = 59;
+ selPos = 4;
+ selLen = 2;
+ break;
+ case 2:
+ frame += steps;
+ if (frame < 0)
+ frame = 0;
+ if (frame > 24) //TD frame type?
+ frame = 24;
+ selPos = 7;
+ selLen = 2;
+ break;
+ case 3:
+ subframe += steps;
+ if (subframe < 0)
+ subframe = 0;
+ if (subframe > 99)
+ subframe = 99;
+ selPos = 10;
+ selLen = 2;
+ break;
+ default:
+ return;
+ }
+ Pos newPos(minute, sec, frame, subframe);
+ if (!(newPos == _pos)) {
+ changed = true;
+ _pos = newPos;
+ }
+ }
+ else {
+ int bar, beat, tick;
+ _pos.mbt(&bar, &beat, &tick);
+
+ int tb = AL::sigmap.ticksBeat(_pos.tick());
+ unsigned tm = AL::sigmap.ticksMeasure(_pos.tick());
+ int bm = tm / tb;
+
+ switch(segment) {
+ case 0:
+ bar += steps;
+ if (bar < 0)
+ bar = 0;
+ selPos = 0;
+ selLen = 4;
+ break;
+ case 1:
+ beat += steps;
+ if (beat < 0)
+ beat = 0;
+ else if (beat >= bm)
+ beat = bm - 1;
+ selPos = 5;
+ selLen = 2;
+ break;
+ case 2:
+ tick += steps;
+ if (tick < 0)
+ tick = 0;
+ else if (tick >= tb)
+ tick = tb -1;
+ selPos = 8;
+ selLen = 3;
+ break;
+ default:
+ return;
+ }
+ Pos newPos(bar, beat, tick);
+ if (!(newPos == _pos)) {
+ changed = true;
+ _pos = newPos;
+ }
+ }
+ if (changed) {
+ updateValue();
+ emit valueChanged(_pos);
+ }
+ lineEdit()->setSelection(selPos, selLen);
+ }
+
+ void PosEdit::paintEvent(QPaintEvent* event) {
+ if (!initialized)
+ updateValue();
+ initialized = true;
+ QAbstractSpinBox::paintEvent(event);
+ }
+}
+
diff --git a/muse2/awl/posedit.h b/muse2/awl/posedit.h
new file mode 100644
index 00000000..effa0537
--- /dev/null
+++ b/muse2/awl/posedit.h
@@ -0,0 +1,72 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __POSEDIT_H__
+#define __POSEDIT_H__
+
+#include "al/pos.h"
+
+namespace Awl {
+
+ using AL::Pos;
+
+//---------------------------------------------------------
+// PosEdit
+//---------------------------------------------------------
+
+class PosEdit : public QAbstractSpinBox
+ {
+ Q_OBJECT
+ Q_PROPERTY(bool smpte READ smpte WRITE setSmpte)
+
+ bool _smpte;
+ Pos _pos;
+ bool initialized;
+
+ virtual void paintEvent(QPaintEvent* event);
+ virtual void stepBy(int steps);
+ virtual StepEnabled stepEnabled() const;
+ virtual void fixup(QString& input) const;
+ virtual QValidator::State validate(QString&, int&) const;
+ void updateValue();
+ int curSegment() const;
+ virtual bool event(QEvent*);
+
+ signals:
+ void valueChanged(const Pos&);
+
+ public slots:
+ void setValue(const Pos& time);
+ void setValue(int t);
+ void setValue(const QString& s);
+
+ public:
+ PosEdit(QWidget* parent = 0);
+ ~PosEdit();
+ QSize sizeHint() const;
+
+ Pos pos() const { return _pos; }
+ void setSmpte(bool);
+ bool smpte() const { return _smpte; }
+ void* operator new(size_t);
+ };
+}
+
+#endif
diff --git a/muse2/awl/poslabel.cpp b/muse2/awl/poslabel.cpp
new file mode 100644
index 00000000..638508fd
--- /dev/null
+++ b/muse2/awl/poslabel.cpp
@@ -0,0 +1,100 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "poslabel.h"
+#include "al/pos.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// PosLabel
+//---------------------------------------------------------
+
+PosLabel::PosLabel(QWidget* parent)
+ : QLabel(parent)
+ {
+ _smpte = false;
+ setFrameStyle(WinPanel | Sunken);
+ setLineWidth(2);
+ setMidLineWidth(3);
+ int fw = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
+ setIndent(fw);
+ updateValue();
+ }
+
+//---------------------------------------------------------
+// sizeHint
+//---------------------------------------------------------
+
+QSize PosLabel::sizeHint() const
+ {
+ QFontMetrics fm(font());
+ int fw = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
+ int h = fm.height() + fw * 2;
+ int w;
+ if (_smpte)
+ w = 2 + fm.width('9') * 9 + fm.width(':') * 3 + fw * 4;
+ else
+ w = 2 + fm.width('9') * 9 + fm.width('.') * 2 + fw * 4;
+ return QSize(w, h).expandedTo(QApplication::globalStrut());
+ }
+
+//---------------------------------------------------------
+// updateValue
+//---------------------------------------------------------
+
+void PosLabel::updateValue()
+ {
+ QString s;
+ if (_smpte) {
+ int min, sec, frame, subframe;
+ pos.msf(&min, &sec, &frame, &subframe);
+ s.sprintf("%03d:%02d:%02d:%02d", min, sec, frame, subframe);
+ }
+ else {
+ int measure, beat, tick;
+ pos.mbt(&measure, &beat, &tick);
+ s.sprintf("%04d.%02d.%03u", measure+1, beat+1, tick);
+ }
+ setText(s);
+ }
+
+//---------------------------------------------------------
+// setValue
+//---------------------------------------------------------
+
+void PosLabel::setValue(const AL::Pos& val, bool enable)
+ {
+ setEnabled(enable);
+ pos = val;
+ updateValue();
+ }
+
+//---------------------------------------------------------
+// setSmpte
+//---------------------------------------------------------
+
+void PosLabel::setSmpte(bool val)
+ {
+ _smpte = val;
+ updateValue();
+ }
+}
+
diff --git a/muse2/awl/poslabel.h b/muse2/awl/poslabel.h
new file mode 100644
index 00000000..68139efe
--- /dev/null
+++ b/muse2/awl/poslabel.h
@@ -0,0 +1,56 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AWLPOSLABEL_H__
+#define __AWLPOSLABEL_H__
+
+#include "al/pos.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// PosLabel
+//---------------------------------------------------------
+
+class PosLabel : public QLabel {
+ bool _smpte;
+ AL::Pos pos;
+ Q_OBJECT
+
+ void updateValue();
+
+ protected:
+ QSize sizeHint() const;
+
+ public slots:
+ void setValue(const AL::Pos&, bool);
+
+ public:
+ PosLabel(QWidget* parent = 0);
+ AL::Pos value() const { return pos; }
+
+ void setSmpte(bool);
+ bool smpte() const { return _smpte; }
+ };
+
+}
+
+#endif
+
diff --git a/muse2/awl/sigedit.cpp b/muse2/awl/sigedit.cpp
new file mode 100644
index 00000000..6493ad6c
--- /dev/null
+++ b/muse2/awl/sigedit.cpp
@@ -0,0 +1,224 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "al/al.h"
+#include "awl.h"
+#include "sigedit.h"
+#include "al/sig.h"
+
+namespace Awl {
+
+ using AL::sigmap;
+
+//---------------------------------------------------------
+// SigEdit
+//---------------------------------------------------------
+
+SigEdit::SigEdit(QWidget* parent)
+ : QAbstractSpinBox(parent)
+ {
+ initialized = false;
+ setReadOnly(false);
+ setMinimumWidth(100); //TD: sizeHint
+ lineEdit()->setInputMask("99/99");
+ }
+
+SigEdit::~SigEdit()
+ {
+ }
+
+//---------------------------------------------------------
+// event
+// filter Tab and Backtab key events
+//---------------------------------------------------------
+
+bool SigEdit::event(QEvent* event)
+ {
+ if (event->type() == QEvent::KeyPress) {
+ QKeyEvent* ke = static_cast<QKeyEvent*>(event);
+ int segment = curSegment();
+ if (ke->key() == Qt::Key_Backtab) {
+ if (segment == 2) {
+ lineEdit()->setSelection(5, 2);
+ return true;
+ }
+ if (segment == 1) {
+ lineEdit()->setSelection(0, 4);
+ return true;
+ }
+ }
+ if (ke->key() == Qt::Key_Tab) {
+ if (segment == 0) {
+ lineEdit()->setSelection(5, 2);
+ return true;
+ }
+ if (segment == 1) {
+ lineEdit()->setSelection(8, 3);
+ return true;
+ }
+ }
+ }
+ else if (event->type() == QEvent::FocusIn) {
+ QFocusEvent* fe = static_cast<QFocusEvent*>(event);
+ QAbstractSpinBox::focusInEvent(fe);
+ int segment = curSegment();
+ switch(segment) {
+ case 0: lineEdit()->setSelection(0,4); break;
+ case 1: lineEdit()->setSelection(5,2); break;
+ case 2: lineEdit()->setSelection(8,3); break;
+ }
+ return true;
+ }
+ return QAbstractSpinBox::event(event);
+ }
+
+//---------------------------------------------------------
+// setValue
+//---------------------------------------------------------
+
+void SigEdit::setValue(const AL::TimeSignature& s)
+ {
+ _sig = s;
+ updateValue();
+ }
+
+//---------------------------------------------------------
+// updateValue
+//---------------------------------------------------------
+
+void SigEdit::updateValue()
+ {
+ char buffer[64];
+ sprintf(buffer, "%d/%d", _sig.z, _sig.n);
+ lineEdit()->setText(buffer);
+ }
+
+//---------------------------------------------------------
+// stepEnables
+//---------------------------------------------------------
+
+QAbstractSpinBox::StepEnabled SigEdit::stepEnabled() const
+ {
+ int segment = curSegment();
+ QAbstractSpinBox::StepEnabled en = QAbstractSpinBox::StepUpEnabled | QAbstractSpinBox::StepDownEnabled;
+
+ switch (segment) {
+ case 0:
+ if (_sig.z == 1)
+ en &= ~QAbstractSpinBox::StepDownEnabled;
+ break;
+ case 1:
+ if (_sig.n == 1)
+ en &= ~QAbstractSpinBox::StepDownEnabled;
+ break;
+ }
+ return en;
+ }
+
+//---------------------------------------------------------
+// fixup
+//---------------------------------------------------------
+
+void SigEdit::fixup(QString& input) const
+ {
+ printf("fixup <%s>\n", input.toLatin1().data());
+ }
+
+//---------------------------------------------------------
+// validate
+//---------------------------------------------------------
+
+QValidator::State SigEdit::validate(QString&,int&) const
+ {
+ // TODO
+ // printf("validate\n");
+ return QValidator::Acceptable;
+ }
+
+//---------------------------------------------------------
+// curSegment
+//---------------------------------------------------------
+
+int SigEdit::curSegment() const
+ {
+ QLineEdit* le = lineEdit();
+ int pos = le->cursorPosition();
+ int segment = -1;
+
+ if (pos >= 0 && pos <= 4)
+ segment = 0;
+ else if (pos >= 5 && pos <= 7)
+ segment = 1;
+ else if (pos >= 8)
+ segment = 2;
+ else
+ printf("curSegment = -1, pos %d\n", pos);
+ return segment;
+ }
+
+//---------------------------------------------------------
+// stepBy
+//---------------------------------------------------------
+
+void SigEdit::stepBy(int steps)
+ {
+ int segment = curSegment();
+ int selPos;
+ int selLen;
+
+ bool changed = false;
+ AL::TimeSignature osig(_sig);
+
+ switch(segment) {
+ case 0:
+ _sig.z += steps;
+ if (_sig.z < 1)
+ _sig.z = 1;
+ selPos = 0;
+ selLen = 2;
+ break;
+ case 1:
+ _sig.n += steps;
+ if (_sig.n < 1)
+ _sig.n = 1;
+ selPos = 3;
+ selLen = 2;
+ break;
+ default:
+ return;
+ }
+ if (osig.z != _sig.z || osig.n != _sig.n) {
+ changed = true;
+ }
+ if (changed) {
+ updateValue();
+ emit valueChanged(_sig);
+ }
+ lineEdit()->setSelection(selPos, selLen);
+ }
+
+ void SigEdit::paintEvent(QPaintEvent* event) {
+ if (!initialized)
+ updateValue();
+ initialized = true;
+ QAbstractSpinBox::paintEvent(event);
+ }
+}
+
diff --git a/muse2/awl/sigedit.h b/muse2/awl/sigedit.h
new file mode 100644
index 00000000..35e762ca
--- /dev/null
+++ b/muse2/awl/sigedit.h
@@ -0,0 +1,66 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __SIGEDIT_H__
+#define __SIGEDIT_H__
+
+#include "al/sig.h"
+
+namespace AL {
+ class TimeSignature;
+ };
+
+namespace Awl {
+
+//---------------------------------------------------------
+// SigEdit
+//---------------------------------------------------------
+
+class SigEdit : public QAbstractSpinBox
+ {
+ Q_OBJECT
+
+ AL::TimeSignature _sig;
+ bool initialized;
+
+ virtual void paintEvent(QPaintEvent* event);
+ virtual void stepBy(int steps);
+ virtual StepEnabled stepEnabled() const;
+ virtual void fixup(QString& input) const;
+ virtual QValidator::State validate(QString&, int&) const;
+ void updateValue();
+ int curSegment() const;
+ virtual bool event(QEvent*);
+
+ signals:
+ void valueChanged(const AL::TimeSignature&);
+
+ public slots:
+ void setValue(const AL::TimeSignature&);
+
+ public:
+ SigEdit(QWidget* parent = 0);
+ ~SigEdit();
+
+ AL::TimeSignature sig() const { return _sig; }
+ };
+}
+
+#endif
diff --git a/muse2/awl/slider.cpp b/muse2/awl/slider.cpp
new file mode 100644
index 00000000..7686e850
--- /dev/null
+++ b/muse2/awl/slider.cpp
@@ -0,0 +1,251 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "slider.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// Slider
+//---------------------------------------------------------
+
+Slider::Slider(QWidget* parent)
+ : AbstractSlider(parent), orient(Qt::Vertical), _sliderSize(14,14)
+ {
+ init();
+ }
+
+//---------------------------------------------------------
+// Slider
+//---------------------------------------------------------
+
+Slider::Slider(Qt::Orientation orientation, QWidget* parent)
+ : AbstractSlider(parent), orient(orientation), _sliderSize(14,14)
+ {
+ init();
+ }
+
+//---------------------------------------------------------
+// Slider
+//---------------------------------------------------------
+
+void Slider::init()
+ {
+ if (orient == Qt::Vertical)
+ setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
+ else
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ dragMode = false;
+ points = 0;
+ updateKnob();
+ }
+
+//---------------------------------------------------------
+// sizeHint
+//---------------------------------------------------------
+
+QSize Slider::sizeHint() const
+ {
+ int w = _sliderSize.width() + scaleWidth();
+ return orient == Qt::Vertical ? QSize(w, 200) : QSize(200, w);
+ }
+
+//---------------------------------------------------------
+// Slider
+//---------------------------------------------------------
+
+Slider::~Slider()
+ {
+ if (points)
+ delete points;
+ }
+
+//---------------------------------------------------------
+// setOrientation
+//---------------------------------------------------------
+
+void Slider::setOrientation(Qt::Orientation o)
+ {
+ orient = o;
+ updateKnob();
+ update();
+ }
+
+//---------------------------------------------------------
+// updateKnob
+//---------------------------------------------------------
+
+void Slider::updateKnob()
+ {
+ if (points)
+ delete points;
+ points = new QPainterPath;
+ int kh = _sliderSize.height();
+ int kw = _sliderSize.width();
+ points->moveTo(0.0, 0.0);
+ if (orient == Qt::Vertical) {
+ int kh = _sliderSize.height();
+ int kh2 = kh / 2;
+ points->lineTo(kw, -kh2);
+ points->lineTo(kw, kh2);
+ }
+ else {
+ int kw2 = kw/2;
+ points->lineTo(-kw2, kh);
+ points->lineTo(kw2, kh);
+ }
+ points->lineTo(0.0, 0.0);
+ }
+
+//---------------------------------------------------------
+// setInvertedAppearance
+//---------------------------------------------------------
+
+void Slider::setInvertedAppearance(bool val)
+ {
+ AbstractSlider::setInvertedAppearance(val);
+ update();
+ }
+
+//---------------------------------------------------------
+// setSliderSize
+//---------------------------------------------------------
+
+void Slider::setSliderSize(const QSize& s)
+ {
+ _sliderSize = s;
+ update();
+ }
+
+//---------------------------------------------------------
+// mousePressEvent
+//---------------------------------------------------------
+
+void Slider::mousePressEvent(QMouseEvent* ev)
+ {
+ startDrag = ev->pos();
+// if (points->boundingRect().toRect().contains(startDrag)) {
+ emit sliderPressed(_id);
+ dragMode = true;
+ int pixel = (orient == Qt::Vertical) ? height() - _sliderSize.height() : width() - _sliderSize.width();
+ dragppos = int(pixel * (_value - minValue()) / (maxValue() - minValue()));
+ if (_invert)
+ dragppos = pixel - dragppos;
+// }
+ }
+
+//---------------------------------------------------------
+// mouseReleaseEvent
+//---------------------------------------------------------
+
+void Slider::mouseReleaseEvent(QMouseEvent*)
+ {
+ if (dragMode) {
+ emit sliderReleased(_id);
+ dragMode = false;
+ }
+ }
+
+//---------------------------------------------------------
+// mouseMoveEvent
+//---------------------------------------------------------
+
+void Slider::mouseMoveEvent(QMouseEvent* ev)
+ {
+ if (!dragMode)
+ return;
+ int delta = startDrag.y() - ev->y();
+
+// if (_invert)
+// delta = -delta;
+ if (orient == Qt::Horizontal)
+ delta = -delta;
+ int ppos = dragppos + delta;
+ if (ppos < 0)
+ ppos = 0;
+
+ int pixel = (orient == Qt::Vertical) ? height() - _sliderSize.height() : width() - _sliderSize.width();
+ if (ppos > pixel)
+ ppos = pixel;
+ int pos = _invert ? (pixel - ppos) : ppos;
+ _value = (pos * (maxValue() - minValue()) / pixel) + minValue() - 0.000001;
+ update();
+ valueChange();
+ }
+
+//---------------------------------------------------------
+// paint
+// r - phys coord system
+//---------------------------------------------------------
+
+void Slider::paintEvent(QPaintEvent* ev)
+ {
+ int h = height();
+ int w = width();
+ int kw = _sliderSize.width();
+ int kh = _sliderSize.height();
+ int pixel = (orient == Qt::Vertical) ? h - kh : w - kw;
+ double range = maxValue() - minValue();
+ int ppos = int(pixel * (_value - minValue()) / range);
+ if ((orient == Qt::Vertical && _invert) || (orient == Qt::Horizontal && !_invert))
+ ppos = pixel - ppos;
+
+ QRect rr(ev->rect());
+ QPainter p(this);
+
+ QColor sc(isEnabled() ? _scaleColor : Qt::gray);
+ QColor svc(isEnabled() ? _scaleValueColor : Qt::gray);
+ p.setBrush(svc);
+
+ int kh2 = kh/2;
+
+ //---------------------------------------------------
+ // draw scale
+ //---------------------------------------------------
+
+ if (orient == Qt::Vertical) {
+ int xm = (w - _scaleWidth - _sliderSize.height()) / 2;
+ int y1 = kh2;
+ int y2 = h - (ppos + y1);
+ int y3 = h - y1;
+ p.fillRect(xm, y1, _scaleWidth, y2-y1, _invert ? svc : sc);
+ p.fillRect(xm, y2, _scaleWidth, y3-y2, _invert ? sc : svc);
+ p.translate(QPointF(xm + _scaleWidth/2, y2));
+ }
+ else {
+ int ym = (h - _scaleWidth - _sliderSize.height()) / 2;
+ int x1 = kh2;
+ int x2 = w - (ppos + x1);
+ int x3 = w - x1;
+ p.fillRect(x1, ym, x2-x1, _scaleWidth, _invert ? sc : svc);
+ p.fillRect(x2, ym, x3-x2, _scaleWidth, _invert ? svc : sc);
+ p.translate(QPointF(x2, ym + _scaleWidth/2));
+ }
+
+ //---------------------------------------------------
+ // draw slider
+ //---------------------------------------------------
+
+ p.setRenderHint(QPainter::Antialiasing, true);
+ p.setPen(QPen(svc, 0));
+ p.drawPath(*points);
+ }
+}
+
diff --git a/muse2/awl/slider.h b/muse2/awl/slider.h
new file mode 100644
index 00000000..e8e38ba2
--- /dev/null
+++ b/muse2/awl/slider.h
@@ -0,0 +1,81 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AWLSLIDER_H__
+#define __AWLSLIDER_H__
+
+#include "aslider.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// Slider
+//
+//! Base class of all slider type input widgets.
+//
+//! Inherits from AwlKnob
+//!
+//---------------------------------------------------------
+
+class Slider : public AbstractSlider {
+ Q_OBJECT
+
+ Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation)
+ Q_PROPERTY(QSize sliderSize READ sliderSize WRITE setSliderSize)
+
+ Qt::Orientation orient;
+ QSize _sliderSize;
+
+ QPoint startDrag;
+ bool dragMode;
+ int dragppos;
+
+ virtual void mouseReleaseEvent(QMouseEvent*);
+ virtual void mouseMoveEvent(QMouseEvent*);
+ virtual void paintEvent(QPaintEvent*);
+ void init();
+ void updateKnob();
+
+ protected:
+ QPainterPath* points;
+ virtual void mousePressEvent(QMouseEvent*);
+
+ signals:
+ void sliderPressed(int);
+ void sliderReleased(int);
+
+ public:
+ Slider(QWidget* parent = 0);
+ Slider(Qt::Orientation orientation, QWidget* parent = 0);
+ ~Slider();
+
+ virtual void setOrientation(Qt::Orientation);
+ Qt::Orientation orientation() const { return orient; }
+
+ QSize sliderSize() const { return _sliderSize; }
+ void setSliderSize(const QSize& s);
+
+ virtual void setInvertedAppearance(bool val);
+ virtual QSize sizeHint() const;
+ };
+}
+
+#endif
+
diff --git a/muse2/awl/tcanvas.cpp b/muse2/awl/tcanvas.cpp
new file mode 100644
index 00000000..6ec4f68f
--- /dev/null
+++ b/muse2/awl/tcanvas.cpp
@@ -0,0 +1,1871 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "tcanvas.h"
+#include "al/al.h"
+#include "al/sig.h"
+#include "al/tempo.h"
+#include "../muse/gconfig.h"
+#include "../muse/icons.h"
+
+#include "metronom.xpm"
+#include "clock.xpm"
+
+#ifdef __APPLE__
+ inline double exp10(double a) { return pow(10.0, a); }
+#endif
+
+static QIcon* clockIcon;
+static QIcon* metronomIcon;
+
+FollowMode TimeCanvas::followMode = FOLLOW_JUMP;
+QPixmap* TimeCanvas::octave;
+QPixmap* TimeCanvas::mk1;
+QPixmap* TimeCanvas::mk2;
+QPixmap* TimeCanvas::mk3;
+QPixmap* TimeCanvas::mk4;
+
+enum DragType {
+ DRAG_RULER,
+ DRAG_CANVASA, DRAG_CANVAS_B,
+ DRAG_PANELA, DRAG_PANELB,
+ DRAG_OTHER
+ };
+
+//---------------------------------------------------------
+// TimeCanvas
+//---------------------------------------------------------
+
+TimeCanvas::TimeCanvas(TimeCanvasType t)
+ : QFrame()
+ {
+ setAttribute(Qt::WA_NoSystemBackground, true);
+
+ _yFit = false;
+ _tool = PointerTool;
+ type = t;
+ _timeType = AL::TICKS;
+ marker = 0;
+ showCursor = false;
+ ctrlHeight = 0;
+ curPitch = -1;
+ mouseInB = false;
+ dragType = DRAG_OTHER;
+ followPos = true;
+
+ // set default color
+ canvasBackgroundColor = QColor(0x71, 0x8d, 0xbe);
+
+ if (clockIcon == 0) {
+ clockIcon = new QIcon(QPixmap(clock_xpm));
+ metronomIcon = new QIcon(QPixmap(metronom_xpm));
+ }
+ button = Qt::NoButton;
+ grid = new QGridLayout;
+ grid->setMargin(0);
+ grid->setSpacing(1);
+ setLayout(grid);
+
+ _widget = new QWidget;
+ _widget->setAttribute(Qt::WA_NoSystemBackground);
+ _widget->setAttribute(Qt::WA_StaticContents);
+ _widget->installEventFilter(this);
+ _widget->setMouseTracking(true);
+ _widget->setAcceptDrops(true);
+
+ // allow to set slider position before slider range
+ // is known:
+
+ pos1.setTick(0);
+ pos2.setTick(INT_MAX);
+
+ hmag = new QSlider(Qt::Horizontal);
+ hmag->setRange(0, 100);
+ _xmagMin = 0.001;
+ _xmagMax = 0.3;
+ _xmag = 0.04;
+ hmag->setValue(xmag2s(_xmag));
+
+ vmag = 0;
+ if (type != TIME_CANVAS_DRUMEDIT) {
+ vmag = new QSlider(Qt::Vertical);
+ vmag->setRange(0, 100);
+ vmag->setPageStep(1);
+ }
+ _ymag = 1.0;
+
+ hbar = new QScrollBar(Qt::Horizontal);
+ hbar->setRange(0, INT_MAX);
+ vbar = new QScrollBar(Qt::Vertical);
+ timeTypeButton = new QToolButton;
+ timeTypeButton->setFixedSize(20, rulerHeight);
+ setTimeType1(AL::TICKS);
+ yRange = 0;
+
+ switch(type) {
+ case TIME_CANVAS_PIANOROLL:
+ _ymagMin = 0.5;
+ _ymagMax = 3.0;
+ vmag->setValue(lrint((_ymag-_ymagMin)*100.0/(_ymagMax-_ymagMin)));
+ initPianoroll();
+ break;
+ case TIME_CANVAS_DRUMEDIT:
+ _ymagMin = 1.0;
+ _ymagMax = 1.0;
+ yRange = drumHeight * 128;
+ break;
+ case TIME_CANVAS_WAVEEDIT:
+ _xmagMin = 0.001;
+ _xmagMax = 100.0;
+ _xmag = 0.04;
+ _ymagMin = 1.0;
+ _ymagMax = 10.0;
+ _ymag = 1.0;
+ break;
+ default:
+ _ymagMin = 1.0;
+ _ymagMax = 1.0;
+ break;
+ }
+ updateGeometry();
+ if (type == TIME_CANVAS_PIANOROLL || type == TIME_CANVAS_DRUMEDIT
+ || type == TIME_CANVAS_WAVEEDIT) {
+ addCtrlButton = new QPushButton(tr("Ctrl"), _widget);
+ addCtrlButton->setGeometry(1, 1, rPanelA.width()-4, rulerHeight-4);
+ addCtrlButton->setToolTip(tr("Add Controller View"));
+ connect(addCtrlButton, SIGNAL(clicked()), SLOT(addCtrlClicked()));
+ }
+
+ grid->addWidget(_widget, 0, 0, 3, 2);
+ grid->addWidget(hbar, 3, 0, Qt::AlignVCenter);
+ grid->addWidget(hmag, 3, 1, Qt::AlignVCenter);
+ grid->addWidget(timeTypeButton, 0, 2);
+ grid->addWidget(vbar, 1, 2, Qt::AlignHCenter);
+ if (vmag)
+ grid->addWidget(vmag, 2, 2, Qt::AlignHCenter);
+
+ grid->setColumnStretch(0, 100);
+ grid->setRowStretch(1, 100);
+
+ _raster = 0;
+ updateScrollBars();
+ connect(hbar, SIGNAL(valueChanged(int)), SLOT(moveX(int)));
+ connect(vbar, SIGNAL(valueChanged(int)), SLOT(moveY(int)));
+ connect(hmag, SIGNAL(valueChanged(int)), SLOT(scaleX(int)));
+ if (vmag)
+ connect(vmag, SIGNAL(valueChanged(int)), SLOT(scaleY(int)));
+ connect(timeTypeButton, SIGNAL(clicked()), SLOT(toggleTimeType()));
+ }
+
+//---------------------------------------------------------
+// resizeController
+//---------------------------------------------------------
+
+void TimeCanvas::resizeController(int h)
+ {
+ if (h == ctrlHeight)
+ return;
+ int updateH = h > ctrlHeight ? h : ctrlHeight;
+ ctrlHeight = h;
+ updateGeometry();
+ updateScrollBars();
+ widget()->update(0, widget()->height() - updateH, widget()->width(), updateH);
+ }
+
+//---------------------------------------------------------
+// eventFilter
+//---------------------------------------------------------
+
+bool TimeCanvas::eventFilter(QObject* obj, QEvent* event)
+ {
+ if (obj != _widget)
+ return QFrame::eventFilter(obj, event);
+
+ switch(event->type()) {
+ case QEvent::Paint:
+ {
+ QPainter p(_widget);
+ canvasPaintEvent(((QPaintEvent*)event)->rect(), p);
+ }
+ return true;
+
+ case QEvent::Resize:
+ updateGeometry();
+ updateScrollBars();
+ layout();
+ return false;
+
+ case QEvent::MouseButtonDblClick:
+ {
+ QMouseEvent* me = (QMouseEvent*)event;
+ QPoint p(me->pos());
+ button = me->button();
+ keyState = me->modifiers();
+ mouseDoubleClick(me);
+ }
+ return true;
+
+ case QEvent::MouseButtonPress:
+ {
+ QMouseEvent* me = (QMouseEvent*)event;
+ keyState = me->modifiers();
+ button = me->button();
+ QPoint p(me->pos());
+ int x = p.x() - rRuler.x();
+ bool shift = keyState & Qt::ShiftModifier;
+
+ if (rRuler.contains(p)) {
+ dragType = DRAG_RULER;
+ if (shift) {
+ AL::Pos pos(pix2pos(x));
+ if (button == Qt::LeftButton)
+ emit addMarker(pos);
+ else if (button == Qt::RightButton)
+ emit removeMarker(pos);
+ return true;
+ }
+ }
+ else {
+ dragType = DRAG_OTHER;
+ mousePress(me);
+ }
+ }
+ // go on with MouseMove
+
+ case QEvent::MouseMove:
+ {
+ QMouseEvent* me = (QMouseEvent*)event;
+ keyState = me->modifiers();
+ button = me->buttons();
+ QPoint p(me->pos());
+ AL::Pos pos(pix2pos(p.x()-rCanvasA.x()));
+
+ if (dragType == DRAG_OTHER) {
+ if (button == 0 && (rPanelB.contains(p) || rCanvasB.contains(p))) {
+ if (!mouseInB) {
+ mouseInB = true;
+ enterB();
+ }
+ }
+ else {
+ if (button == 0 && mouseInB) {
+ mouseInB = false;
+ leaveB();
+ }
+ }
+
+ if (showCursor && p.x() < rCanvasA.x()) {
+ showCursor = false;
+ widget()->update(rRuler);
+ emit cursorPos(cursor, showCursor);
+ }
+
+ if (p.x() >= rCanvasA.x() && (cursor != pos)) {
+ int x1 = pos2pix(cursor) + rCanvasA.x();
+ int x2 = pos2pix(pos) + rCanvasA.x();
+ QRect r1(x1-1, 0, 2, rRuler.height());
+ QRect r2(x2-1, 0, 2, rRuler.height());
+ widget()->update(rRuler & (r1 | r2));
+ cursor = pos;
+ showCursor = true;
+ emit cursorPos(cursor, showCursor);
+ }
+
+ if (rRuler.contains(p)) {
+ int b = me->buttons();
+ if (b == 0)
+ return true;
+ int i = 0;
+ if (b & Qt::MidButton)
+ i = 1;
+ else if (b & Qt::RightButton)
+ i = 2;
+ if (keyState & Qt::ShiftModifier)
+ emit addMarker(i);
+ emit posChanged(i, pos);
+ }
+ else {
+ mouseMove(p);
+ }
+ }
+ else if (dragType == DRAG_RULER) {
+ int b = me->buttons();
+ if (b == 0)
+ return true;
+ int i = 0;
+ if (b & Qt::MidButton)
+ i = 1;
+ else if (b & Qt::RightButton)
+ i = 2;
+ if (keyState & Qt::ShiftModifier)
+ emit addMarker(i);
+ emit posChanged(i, pos);
+ }
+ }
+ return true;
+
+ case QEvent::MouseButtonRelease:
+ {
+ QMouseEvent* me = (QMouseEvent*)event;
+ button = Qt::NoButton;
+ keyState = me->modifiers();
+ mouseRelease(me);
+ dragType = DRAG_OTHER;
+ }
+ return true;
+
+ case QEvent::DragEnter:
+ dragEnter((QDragEnterEvent*)event);
+ return true;
+
+ case QEvent::Drop:
+ drop((QDropEvent*)event);
+ return true;
+
+ case QEvent::DragMove:
+ dragMove((QDragMoveEvent*)event);
+ return true;
+
+ case QEvent::DragLeave:
+ dragLeave((QDragLeaveEvent*)event);
+ return true;
+
+ case QEvent::Leave:
+ {
+ emit cursorPos(cursor, false);
+ showCursor = false;
+ emit pitchChanged(-1);
+ curPitch = -1;
+ QRect r(rRuler);
+ if (!rPanelA.isEmpty())
+ r |= rPanelA;
+ widget()->update(r);
+
+ if (mouseInB) {
+ mouseInB = false;
+ // button = ((QMouseEvent*)event)->buttons();
+ leaveB();
+ }
+ }
+ return false;
+
+ case QEvent::Wheel:
+ {
+ QWheelEvent* e = (QWheelEvent*)event;
+ if (e->orientation() != Qt::Vertical)
+ return true;
+ if ((e->modifiers() & Qt::ControlModifier) || (e->modifiers() & Qt::ShiftModifier)) {
+ //
+ // xmag
+ //
+ int oldx = e->x() - rCanvasA.x();
+ AL::Pos pos(pix2pos(oldx));
+ int step = e->delta() / 120;
+ if (step > 0) {
+ for (int i = 0; i< step; ++i)
+ _xmag *= 1.1;
+ }
+ else {
+ for (int i = 0; i < -step; ++i)
+ _xmag *= 0.9;
+ }
+ if (_xmag < _xmagMin)
+ _xmag = _xmagMin;
+ else if (_xmag > _xmagMax)
+ _xmag = _xmagMax;
+ hmag->setValue(xmag2s(_xmag));
+ int newx = pos2pix(pos);
+ updateScrollBars();
+ hbar->setValue(wpos.x() + (newx - oldx));
+ updateRulerMag();
+ magChanged();
+ _widget->update();
+ }
+ else {
+ //
+ // scroll
+ //
+ int step = qMin(QApplication::wheelScrollLines() * vbar->singleStep(), vbar->pageStep());
+ int offset = e->delta() * step / 120;
+ if (vbar->invertedControls())
+ offset = -offset;
+ if (qAbs(offset) < 1)
+ return true;
+ vbar->setValue(vbar->value() + offset);
+ }
+ }
+ return true;
+ default:
+// printf("event %d missed\n", event->type());
+ break;
+ }
+ return false;
+ }
+
+
+
+void TimeCanvas::keyPressEvent(QKeyEvent *e)
+{
+ if (e->key() == Qt::Key_Up || e->key() == Qt::Key_Down ||
+ e->key() == Qt::Key_Left || e->key() == Qt::Key_Right)
+ keyboardNavigate(e);
+}
+
+//---------------------------------------------------------
+// moveX
+//---------------------------------------------------------
+
+void TimeCanvas::moveX(int x)
+ {
+ int dx = wpos.x() - x;
+ wpos.setX(x);
+
+ int wh = _widget->height();
+
+ if (type == TIME_CANVAS_PIANOROLL || type == TIME_CANVAS_DRUMEDIT
+ || TIME_CANVAS_WAVEEDIT) {
+ _widget->scroll(dx, 0, QRect(rCanvasA.x(), 0, rCanvasA.width(), wh));
+
+ //HACK:
+ // update controller names
+ int w = 100 + ((dx > 0) ? dx : 0);
+ _widget->update(rCanvasB.x(), rCanvasB.y(), w, rCanvasB.height());
+
+ //HACK:
+ // repaint rounded line end (splitter handle for controller
+ // canvas)
+ int x = rCanvasB.x() + rCanvasB.width() - 1;
+ w = 1;
+ if (dx < 0) {
+ x += dx;
+ w -= dx;
+ }
+ _widget->update(x, rCanvasB.y(), w, rCanvasB.height());
+ }
+ else
+ _widget->scroll(dx, 0);
+ emit contentsMoving(wpos.x(), wpos.y());
+ }
+
+//---------------------------------------------------------
+// moveY
+//---------------------------------------------------------
+
+void TimeCanvas::moveY(int y)
+ {
+ int dy = wpos.y() - y;
+ if (dy == 0)
+ return;
+ wpos.setY(y);
+
+ // dont move ruler:
+
+ int ww = _widget->width();
+ int wh = _widget->height();
+
+ QRect r(0, rulerHeight, ww, wh - rulerHeight - ctrlHeight);
+
+ _widget->scroll(0, dy, r);
+ emit contentsMoving(wpos.x(), wpos.y());
+ }
+
+//---------------------------------------------------------
+// setYPos
+//---------------------------------------------------------
+
+void TimeCanvas::setYPos(int y)
+ {
+ setWPos(QPoint(wpos.x(), y));
+ }
+
+//---------------------------------------------------------
+// setWPos
+//---------------------------------------------------------
+
+void TimeCanvas::setWPos(const QPoint& p)
+ {
+ if (wpos != p) {
+ wpos = p;
+ hbar->setValue(wpos.x());
+ vbar->setValue(wpos.y());
+ _widget->update();
+// QCoreApplication::flush();
+ }
+ }
+
+//---------------------------------------------------------
+// paintClockRuler
+//---------------------------------------------------------
+
+void TimeCanvas::paintClockRuler(QPainter& p, const QRect& r)
+ {
+ int x1 = r.x();
+ int x2 = x1 + r.width();
+
+ int y1 = r.y();
+ int rh = r.height();
+ if (y1 < rulerHeight) {
+ rh -= rulerHeight - y1;
+ y1 = rulerHeight;
+ }
+ int y2 = y1 + rh;
+
+ //---------------------------------------------------
+ // draw Marker
+ //---------------------------------------------------
+
+ int y = rulerHeight - 16;
+ p.setPen(Qt::black);
+ p.setFont(_font3);
+ QRect tr(r);
+ tr.setHeight(12);
+
+ if (marker) {
+ for (AL::iMarker m = marker->begin(); m != marker->end(); ++m) {
+ int xp = mapx(int(m->second.frame()));
+ if (xp > x2)
+ break;
+ AL::iMarker mm = m;
+ ++mm;
+ int xe = x2;
+ if (mm != marker->end()) {
+ xe = mapx(mm->first);
+ }
+ QRect tr(xp, 0, x2 - xp, 11);
+ if (m->second.current()) {
+ p.fillRect(tr, Qt::white);
+ }
+ if (r.intersects(tr)) {
+ int x2;
+ AL::iMarker mm = m;
+ ++mm;
+ if (mm != marker->end())
+ x2 = mapx(mm->first);
+ else
+ x2 = xp+200;
+ QRect r = QRect(xp+10, 0, x2-xp, 12);
+ p.drawPixmap(xp, 0, *flagIconS);
+ p.drawText(r, Qt::AlignLeft|Qt::AlignVCenter, m->second.name());
+ }
+ }
+ }
+
+ p.setPen(Qt::black);
+ if (showCursor) {
+ int xp = pos2pix(cursor);
+ if (xp >= x1 && xp < x2)
+ p.drawLine(xp, 0, xp, rulerHeight);
+ }
+
+ AL::Pos p1(pix2pos(x1));
+ AL::Pos p2(pix2pos(x2));
+
+ int sec1 = p1.frame() / AL::sampleRate;
+ int sec2 = (p2.frame() + AL::sampleRate - 1) / AL::sampleRate;
+
+ int sw = lrint(AL::sampleRate * _xmag);
+
+ if (sw > 20) {
+ for (int sec = sec1; sec < sec2; ++sec) {
+ int min = sec / 60;
+ int sr = sec % 60;
+
+ int yy;
+ QString s;
+ if (sr == 0) {
+ p.setFont(_font2);
+ s.sprintf("%d:00", min);
+ yy = y;
+ }
+ else {
+ p.setFont(_font1);
+ s.sprintf("%02d", sr);
+ yy = y + 7;
+ }
+ int xp = pos2pix(AL::Pos(sec * AL::sampleRate, AL::FRAMES));
+// printf(" sec %d min %d sr %d xp %d\n", sec, min, sr, xp);
+ p.setPen(Qt::black);
+ p.drawLine(xp, yy, xp, rulerHeight);
+ p.drawText(xp + 2, rulerHeight - 4, s);
+ p.setPen(sr == 0 ? Qt::lightGray : Qt::gray);
+ p.drawLine(xp, y1, xp, y2);
+ }
+ }
+ else {
+ int min1 = sec1/60;
+ int min2 = (sec2+59)/60;
+ for (int min = min1; min < min2; ++min) {
+ QString s;
+ p.setFont(_font2);
+ s.sprintf("%d", min);
+ int xp = pos2pix(AL::Pos(min * AL::sampleRate * 60, AL::FRAMES));
+ p.setPen(Qt::black);
+ p.drawLine(xp, y, xp, rulerHeight);
+ p.drawText(xp + 2, rulerHeight - 4, s);
+ p.setPen(Qt::lightGray);
+ p.drawLine(xp, y1, xp, y2);
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// updateRulerMag
+//---------------------------------------------------------
+
+void TimeCanvas::updateRulerMag()
+ {
+ int bar1, beat, tick;
+ pos1.mbt(&bar1, &beat, &tick);
+ AL::Pos stick(bar1, 0, 0);
+ AL::Pos ntick = AL::Pos(bar1 + 1, 0, 0);
+ int tpix = pos2pix(ntick) - pos2pix(stick);
+ metronomeRulerMag = 0;
+ if (tpix < 64)
+ metronomeRulerMag = 1;
+ if (tpix < 32)
+ metronomeRulerMag = 2;
+ if (tpix <= 16)
+ metronomeRulerMag = 3;
+ if (tpix < 8)
+ metronomeRulerMag = 4;
+ if (tpix <= 4)
+ metronomeRulerMag = 5;
+ if (tpix <= 2)
+ metronomeRulerMag = 6;
+ }
+
+//---------------------------------------------------------
+// paintMetronomRuler
+//---------------------------------------------------------
+
+void TimeCanvas::paintMetronomRuler(QPainter& p, const QRect& r)
+ {
+ static const int mag[7] = {
+ 1, 1, 2, 5, 10, 20, 50
+ };
+
+ int x = r.x();
+ int w = r.width();
+ int y = rulerHeight - 16;
+
+ p.setFont(_font3);
+
+ int h = 14;
+ int y1 = r.y();
+ int rh = r.height();
+ if (y1 < rulerHeight) {
+ rh -= rulerHeight - y1;
+ y1 = rulerHeight;
+ }
+ int y2 = y1 + rh;
+
+ if (x < (MAP_OFFSET - wpos.x()))
+ x = MAP_OFFSET - wpos.x();
+ AL::Pos pos1 = pix2pos(x);
+ AL::Pos pos2 = pix2pos(x+w);
+
+ if (marker) {
+ AL::iMarker start = marker->lower_bound(pos1.tick());
+ if (start != marker->begin())
+ --start;
+ AL::iMarker end = marker->lower_bound(pos2.tick());
+ for (AL::iMarker m = start; m != end; ++m) {
+ AL::Pos pm1(m->second);
+ AL::iMarker m2 = m;
+ ++m2;
+ AL::Pos pm2(pos2);
+ if (m2 != marker->end())
+ pm2 = m2->second;
+
+ int x1 = pos2pix(pm1);
+ int x2 = pos2pix(pm2);
+
+ if (pos[0] >= pm1 && (m2 == marker->end() || pos[0] < pm2))
+ p.fillRect(x1, 0, x2 - x1, 11, Qt::white);
+
+ QRect r = QRect(x1 + 10, 0, x2 - x1, 12);
+ p.drawPixmap(x1, 0, *flagIconS);
+ p.drawText(r, Qt::AlignLeft|Qt::AlignVCenter, m->second.name());
+ }
+ }
+
+ //---------------------------------------------------
+ // draw raster
+ //---------------------------------------------------
+
+ int bar1, bar2, beat, tick;
+ pos1.mbt(&bar1, &beat, &tick);
+ pos2.mbt(&bar2, &beat, &tick);
+
+ int n = mag[metronomeRulerMag];
+
+ bar1 = (bar1 / n) * n; // round down
+ if (bar1 && n >= 2)
+ bar1 -= 1;
+ bar2 = ((bar2 + n - 1) / n) * n; // round up
+
+ for (int bar = bar1; bar <= bar2;) {
+ AL::Pos stick(bar, 0, 0);
+ if (metronomeRulerMag) {
+ p.setFont(_font2);
+ int x = pos2pix(stick);
+ QString s;
+ s.setNum(bar + 1);
+
+ p.setPen(Qt::black);
+ p.drawLine(x, y, x, y + h);
+ QRect r = QRect(x+2, y, 1000, h);
+ p.drawText(r, Qt::AlignLeft | Qt::AlignVCenter, s);
+ p.setPen(Qt::lightGray);
+ if (x > 0)
+ p.drawLine(x, y1, x, y2);
+ }
+ else {
+ AL::TimeSignature sig = stick.timesig();
+ int z = sig.z;
+ for (int beat = 0; beat < z; beat++) {
+ AL::Pos xx(bar, beat, 0);
+ int xp = pos2pix(xx);
+ if (xp < 0)
+ continue;
+ QString s;
+ QRect r(xp+2, y + 1, 1000, h);
+ int y3;
+ int num;
+ if (beat == 0) {
+ num = bar + 1;
+ y3 = y + 2;
+ p.setFont(_font2);
+ }
+ else {
+ num = beat + 1;
+ y3 = y + 8;
+ p.setFont(_font1);
+ r.moveTop(r.top() + 1);
+ }
+ s.setNum(num);
+ p.setPen(Qt::black);
+ p.drawLine(xp, y3, xp, y+h);
+ p.drawText(r, Qt::AlignLeft | Qt::AlignVCenter, s);
+ p.setPen(beat == 0 ? Qt::lightGray : Qt::gray);
+ if (xp > 0)
+ p.drawLine(xp, y1, xp, y2);
+ }
+ }
+ if (bar == 0 && n >= 2)
+ bar += (n-1);
+ else
+ bar += n;
+ }
+ //
+ // draw mouse cursor marker
+ //
+ p.setPen(Qt::black);
+ if (showCursor) {
+ int xp = pos2pix(cursor);
+ if (xp >= x && xp < x+w)
+ p.drawLine(xp, 0, xp, rulerHeight-1);
+ }
+
+ }
+
+//---------------------------------------------------------
+// tempoChanged
+//---------------------------------------------------------
+
+void TimeCanvas::tempoChanged()
+ {
+ widget()->update(rCanvasA.x(), 0, rCanvasA.width(), widget()->height());
+ }
+
+//---------------------------------------------------------
+// canvasPaintEvent
+//---------------------------------------------------------
+
+void TimeCanvas::canvasPaintEvent(const QRect& r, QPainter& p)
+ {
+ if (r.intersects(rButton)) {
+ p.fillRect(rButton, QColor(0xe0, 0xe0, 0xe0));
+ p.setPen(QPen(Qt::black, 2));
+ int y = rButton.y() + rButton.height() - 1;
+ p.drawLine(rButton.x(), y, rButton.width(), y);
+ }
+ p.setRenderHint(QPainter::TextAntialiasing, true);
+
+ QRect par = r & rPanelA;
+ if (!(par.isEmpty() || rPanelA.isEmpty())) {
+ if (type == TIME_CANVAS_DRUMEDIT) {
+ paintDrumList(p, par);
+ }
+ else if (type == TIME_CANVAS_PIANOROLL) {
+ paintPiano(p, par);
+ }
+ else if (type == TIME_CANVAS_WAVEEDIT) {
+ p.fillRect(par, QColor(0xe0, 0xe0, 0xe0));
+ }
+ }
+
+ QRect pbr(r & rPanelB);
+ QRect hor(r & (rRuler | rCanvasA | rCanvasB));
+ QRect car(r & rCanvasA);
+ QRect cbr(r & rCanvasB);
+
+ bool drawPanelB = !(pbr.isEmpty() || rPanelB.isEmpty());
+ bool drawRuler = !(hor.isEmpty() || (rRuler.isEmpty() && rCanvasA.isEmpty() && rCanvasB.isEmpty()));
+ bool drawCanvasA = !(car.isEmpty() || rCanvasA.isEmpty());
+ bool drawCanvasB = !(cbr.isEmpty() || rCanvasB.isEmpty());
+
+ //
+ // draw canvas background
+ //
+
+ p.setClipRect(r);
+ p.setBrushOrigin(QPoint(car.x() + wpos.x(), car.y() + wpos.y()));
+ if (drawCanvasA) {
+ if (canvasBackgroundPixmap.isNull()) {
+ if (type == TIME_CANVAS_DRUMEDIT || type == TIME_CANVAS_PIANOROLL
+ || type == TIME_CANVAS_WAVEEDIT) {
+ QRect rr(car);
+ // paint inactive area different
+ // (darker)
+ QColor c = canvasBackgroundColor.darker(150);
+ int x1 = pos2pix(partPos1) + rCanvasA.x();
+ if (rr.x() < x1) {
+ QRect r(rr.x(), rr.y(), x1-rr.x(), rr.height());
+ p.fillRect(r, c);
+ rr.adjust(x1-rr.x(), 0, 0, 0);
+ }
+ int x2 = pos2pix(partPos2) + rCanvasA.x();
+ int xx2 = rr.x() + rr.width();
+ if (xx2 > x2) {
+ if (x2 < rr.x())
+ x2 = rr.x();
+ QRect r(x2, rr.y(), xx2-x2, rr.height());
+ p.fillRect(r, c);
+ rr.adjust(0, 0, -(xx2-x2), 0);
+ }
+ if (!rr.isEmpty()) {
+ p.fillRect(rr, canvasBackgroundColor);
+ }
+ }
+ else
+ p.fillRect(car, canvasBackgroundColor);
+ }
+ else {
+ p.drawTiledPixmap(car, canvasBackgroundPixmap,
+ car.topLeft() + QPoint(wpos));
+ }
+ }
+
+ if (drawCanvasB)
+ p.fillRect(cbr, canvasBackgroundColor);
+
+ //---------------------------------------------------
+ // draw Ruler
+ //---------------------------------------------------
+
+ if (drawRuler) {
+ QRect rrr(r & rRuler);
+ if (!rrr.isEmpty())
+ p.fillRect(rrr, QColor(0xe0, 0xe0, 0xe0));
+ int x1 = hor.x();
+ int x2 = x1 + hor.width();
+ int y1 = rulerHeight - 17;
+ int y2 = rulerHeight - 1;
+
+ p.setPen(QPen(Qt::black, 1));
+ p.drawLine(x1, y1, x2, y1);
+ p.setPen(QPen(Qt::black, 2));
+ p.drawLine(x1, y2, x2, y2);
+
+ QPoint off(rRuler.topLeft());
+ p.translate(off);
+ if (_timeType == AL::TICKS)
+ paintMetronomRuler(p, hor.translated(-off));
+ else
+ paintClockRuler(p, hor.translated(-off));
+ p.translate(-off);
+ }
+
+ if (drawCanvasA) {
+ p.setClipRect(car);
+ paintCanvas(p, car);
+ }
+ p.setRenderHint(QPainter::Antialiasing, false);
+ if (drawPanelB) {
+ p.setClipRect(pbr);
+ QPoint off(rPanelB.topLeft());
+ p.translate(off);
+ paintControllerPanel(p, pbr.translated(-off));
+ p.translate(-off);
+ }
+ if (drawCanvasB) {
+ p.setClipRect(cbr);
+ QPoint off(rCanvasB.topLeft());
+ p.translate(off);
+ paintControllerCanvas(p, cbr.translated(-off));
+ p.translate(-off);
+ }
+ //---------------------------------------------------
+ // draw marker
+ //---------------------------------------------------
+
+ int y1 = r.y();
+ int y2 = y1 + r.height();
+ if (drawRuler) {
+ p.setClipRect(hor);
+ int w = r.width();
+ int x = r.x();
+ int y = rulerHeight - 16;
+ QColor lcColors[3] = { Qt::red, Qt::blue, Qt::blue };
+
+ for (int i = 0; i < 3; ++i) {
+ p.setPen(lcColors[i]);
+ int xp = pos2pix(pos[i]) + rRuler.x();
+ QPixmap* pm = markIcon[i];
+ int pw = (pm->width() + 1) / 2;
+ int x1 = x - pw;
+ int x2 = x + w + pw;
+ if (xp >= x1 && xp < x2) {
+ p.drawPixmap(xp - pw, y-2, *pm);
+ p.drawLine(xp, y1, xp, y2);
+ }
+ }
+ }
+ if (marker) {
+ int yy1 = y1;
+ if (yy1 < rCanvasA.x())
+ yy1 = rCanvasA.x();
+ p.setPen(Qt::green);
+ AL::iMarker start = marker->lower_bound(pos1.tick());
+ if (start != marker->begin())
+ --start;
+ AL::iMarker end = marker->lower_bound(pos2.tick());
+ if (end != marker->end())
+ ++end;
+ for (AL::iMarker m = start; m != end; ++m) {
+ AL::Pos pm(m->second);
+ int x = pos2pix(pm) + rRuler.x();
+ p.drawLine(x, yy1, x, y2);
+ }
+ }
+ }
+
+//---------------------------------------------------------
+// paintCanvas
+//---------------------------------------------------------
+
+void TimeCanvas::paintCanvas(QPainter& p, const QRect& cr)
+ {
+ QPoint off(rCanvasA.topLeft());
+
+ if (type == TIME_CANVAS_PIANOROLL) {
+ paintPianorollHorizontalGrid(p, cr);
+ p.setRenderHint(QPainter::Antialiasing, true);
+ }
+ else if (type == TIME_CANVAS_DRUMEDIT) {
+ paintDrumeditHorizontalGrid(p, cr);
+ p.setRenderHint(QPainter::Antialiasing, true);
+ }
+ else
+ off = QPoint(rCanvasA.x(), rCanvasA.y() - wpos.y());
+ p.translate(off);
+ paint(p, cr.translated(-off));
+ p.resetMatrix();
+ }
+
+//---------------------------------------------------------
+// setLocatorPos
+//---------------------------------------------------------
+
+void TimeCanvas::setLocatorPos(int idx, const AL::Pos& val, bool follow)
+ {
+ if (pos[idx] == val)
+ return;
+ QFontMetrics fm(_font2);
+ int fw = fm.width("123") + 2;
+ int w = qMax(markIcon[idx]->width() + 2, fw);
+ int h = widget()->height();
+
+ int x = pos2pix(val);
+ if (idx == 0 && follow && followPos && followMode != FOLLOW_NO) {
+ int scroll = 0;
+ if (followMode == FOLLOW_JUMP) {
+ int x2 = rRuler.width() - 20;
+ if (x2 < 0)
+ x2 = rRuler.width();
+ if (x > x2) {
+ int x1 = 20;
+ if (x1 >= rRuler.width())
+ x1 = 0;
+ scroll = x - x1;
+ }
+ else if (x < 0) {
+ scroll = x - MAP_OFFSET;
+ }
+ }
+ else if (followMode == FOLLOW_CONTINUOUS) {
+ int x1 = rRuler.width() / 2;
+ if (x != x1) {
+ scroll = x - (rRuler.width() / 2);
+ }
+ }
+ if (scroll) {
+ moveX(wpos.x() + scroll);
+ hbar->setValue(wpos.x());
+ }
+ }
+
+ int offset = rRuler.x() - (w/2);
+ int x1 = pos2pix(pos[idx]);
+ int x2 = pos2pix(val);
+ QRect oR(x1 + offset, 0, w, h);
+ QRect nR(x2 + offset, 0, w, h);
+ pos[idx] = val;
+ widget()->update(oR | nR);
+ }
+
+//---------------------------------------------------------
+// setMag
+//---------------------------------------------------------
+
+void TimeCanvas::setMag(double x, double y)
+ {
+ if (_xmag == x && _ymag == y)
+ return;
+ _xmag = x;
+ _ymag = y;
+ if (vmag)
+ vmag->setValue(lrint((_ymag-_ymagMin)*100.0/(_ymagMax-_ymagMin)));
+ hmag->setValue(xmag2s(_xmag));
+ updateScrollBars();
+ updateRulerMag();
+ magChanged();
+ _widget->update();
+ }
+
+//---------------------------------------------------------
+// scaleX
+//---------------------------------------------------------
+
+void TimeCanvas::scaleX(int val)
+ {
+ _xmag = s2xmag(val);
+ updateScrollBars();
+ updateRulerMag();
+ magChanged();
+ _widget->update();
+ }
+
+//---------------------------------------------------------
+// scaleY
+//---------------------------------------------------------
+
+void TimeCanvas::scaleY(int val)
+ {
+ int y = lrint(wpos.y() / _ymag);
+ _ymag = (_ymagMax - _ymagMin) / 100.0 * val + _ymagMin;
+ y = lrint(y * _ymag);
+ wpos.setY(y);
+ updateScrollBars();
+ magChanged();
+ _widget->update();
+ }
+
+//---------------------------------------------------------
+// setRaster
+// r = 1 - no raster
+// 0 - measure raster
+// > 1 - tick raster
+//---------------------------------------------------------
+
+void TimeCanvas::setRaster(int r)
+ {
+ if (_raster != r) {
+ _raster = r;
+ _widget->update();
+ }
+ }
+
+//---------------------------------------------------------
+// setTimeRange
+//---------------------------------------------------------
+
+void TimeCanvas::setTimeRange(const AL::Pos& p1, const AL::Pos& p2)
+ {
+ if (pos1 == p1 && pos2 == p2)
+ return;
+ pos1 = p1;
+ pos2 = p2;
+ updateScrollBars();
+ widget()->update();
+ }
+
+//---------------------------------------------------------
+// setEndPos
+//---------------------------------------------------------
+
+void TimeCanvas::setEndPos(const AL::Pos& p2)
+ {
+ if (pos2 == p2)
+ return;
+ pos2 = p2;
+ updateScrollBars();
+ widget()->update();
+ }
+
+//---------------------------------------------------------
+// updateScrollBars
+//---------------------------------------------------------
+
+void TimeCanvas::updateScrollBars()
+ {
+ hbar->blockSignals(true);
+ vbar->blockSignals(true);
+
+ int ymax = lrint(yRange * _ymag) - rCanvasA.height();
+ if (ymax < 0)
+ ymax = 0;
+ vbar->setRange(0, ymax);
+ vbar->setPageStep(rCanvasA.height());
+
+ int xmin = lrint(pos1.time(_timeType) * _xmag);
+ unsigned x2 = pos2.time(_timeType);
+ int xmax = lrint(x2 * _xmag) - rCanvasA.width();
+ if (xmax - xmin < 0)
+ xmax = xmin;
+ hbar->setRange(xmin, xmax);
+ hbar->setPageStep(rCanvasA.width());
+ wpos.setX(hbar->value());
+ wpos.setY(vbar->value());
+
+ hbar->blockSignals(false);
+ vbar->blockSignals(false);
+ }
+
+//---------------------------------------------------------
+// setTimeType1
+//---------------------------------------------------------
+
+void TimeCanvas::setTimeType1(AL::TType t)
+ {
+ double conv = 1.0;
+ if (t == AL::TICKS) {
+ timeTypeButton->setIcon(*metronomIcon);
+ if (_timeType == AL::FRAMES)
+ conv = AL::sampleRate / double(AL::division * 120 / 60);
+ }
+ else {
+ timeTypeButton->setIcon(*clockIcon);
+ if (_timeType == AL::TICKS)
+ conv = double(AL::division * 120 / 60) / double(AL::sampleRate);
+ }
+ _timeType = t;
+ _xmag *= conv;
+ _xmagMax *= conv;
+ _xmagMin *= conv;
+
+ updateRulerMag();
+ magChanged();
+ }
+
+//---------------------------------------------------------
+// setTimeType
+//---------------------------------------------------------
+
+void TimeCanvas::setTimeType(AL::TType t)
+ {
+ setTimeType1(t);
+ updateScrollBars();
+ timeTypeChanged();
+ widget()->update();
+ }
+
+//---------------------------------------------------------
+// toggleTimeType
+//---------------------------------------------------------
+
+void TimeCanvas::toggleTimeType()
+ {
+ if (_timeType == AL::TICKS)
+ setTimeType(AL::FRAMES);
+ else
+ setTimeType(AL::TICKS);
+ }
+
+//---------------------------------------------------------
+// setMarkerList
+//---------------------------------------------------------
+
+void TimeCanvas::setMarkerList(AL::MarkerList* ml)
+ {
+ if (marker == ml)
+ return;
+ marker = ml;
+ widget()->update();
+ }
+
+//---------------------------------------------------------
+// pix2pos
+//---------------------------------------------------------
+
+AL::Pos TimeCanvas::pix2pos(int x) const
+ {
+ int val = lrint((x + wpos.x() - MAP_OFFSET)/_xmag);
+ if (val < 0)
+ val = 0;
+ return AL::Pos(val, _timeType);
+ }
+
+//---------------------------------------------------------
+// pos2pix
+//---------------------------------------------------------
+
+int TimeCanvas::pos2pix(const AL::Pos& p) const
+ {
+ return lrint(p.time(_timeType) * _xmag) + MAP_OFFSET - wpos.x();
+ }
+
+//---------------------------------------------------------
+// mapx
+//---------------------------------------------------------
+
+int TimeCanvas::mapx(int x) const
+ {
+ return lrint(x * _xmag) + MAP_OFFSET - wpos.x();
+ }
+
+//---------------------------------------------------------
+// mapxDev
+//---------------------------------------------------------
+
+int TimeCanvas::mapxDev(int x) const
+ {
+ int val = lrint((x + wpos.x() - MAP_OFFSET)/_xmag);
+ if (val < 0)
+ val = 0;
+ return val;
+ }
+
+//---------------------------------------------------------
+// setCorderWidget
+//---------------------------------------------------------
+
+void TimeCanvas::setCornerWidget(QWidget* w)
+ {
+ grid->addWidget(w, 3, 2);
+ }
+
+//---------------------------------------------------------
+// initPianoroll
+//---------------------------------------------------------
+
+/*
+ 0 1 2 3 4 5 6 7 8 9 10
+ c-2 c-1 C0 C1 C2 C3 C4 C5 C6 C7 C8 - G8
+
+ Grid ve:
+
+ +------------+ ------------------------------
+ 11 | |
+ | b | 7
+ +------+ |
+ 10 | a# +-----+ ..............................
+ +------+ a |
+ 9 | | 6
+ +------+ |
+ 8 | g# +-----+ ..............................
+ +------+ g |
+ 7 | | 5
+ +------+ |
+ 6 | f# +-----+ ..............................
+ +------+ f |
+ 5 | | 4
+ | |
+ +------------+ ------------------------------
+ 4 | |
+ | e | 3
+ +------+ |
+ 3 | d# +-----+ ..............................
+ +------+ d |
+ 2 | | 2
+ +------+ |
+ 1 | c# +-----+ ..............................
+ +------+ c |
+ | | 1
+ 0 | |
+ +------------+ ------------------------------
+ */
+
+void TimeCanvas::initPianoroll()
+ {
+ static const char *oct_xpm[] = {
+ // w h colors
+ "40 91 2 1",
+ ". c #f0f0f0",
+ "# c #000000",
+ // x
+ "####################################### ",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", // 10
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", //------------------------
+ "#######################................#",
+ "########################...............#",
+ "########################...............#",
+ "####################################### ", // 7
+ "########################...............#",
+ "########################...............#",
+ "#######################................#", //------------------------
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", // 6
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", //------------------------
+ "#######################................#",
+ "########################...............#",
+ "########################...............#", // 7
+ "####################################### ",
+ "########################...............#",
+ "########################...............#",
+ "#######################................#", //------------------------
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", // 6
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", //------------------------
+ "#######################................#",
+ "########################...............#",
+ "########################...............#", // 7
+ "####################################### ",
+ "########################...............#",
+ "########################...............#",
+ "#######################................#", //------------------------
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", // 10
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ "####################################### ", //----------------------
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", // 9
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", //------------------------
+ "#######################................#",
+ "########################...............#",
+ "########################...............#",
+ "####################################### ", // 7
+ "########################...............#",
+ "########################...............#",
+ "#######################................#", //------------------------
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", // 6
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", //--------------------------
+ "#######################................#",
+ "########################...............#",
+ "########################...............#", // 7
+ "####################################### ",
+ "########################...............#",
+ "########################...............#",
+ "#######################................#", //------------------------
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", // 10
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ };
+
+ static const char *mk1_xpm[] = {
+ "40 13 2 1",
+ ". c #ff0000",
+ "# c none",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ "#######################................#",
+ "########################...............#",
+ "########################...............#",
+ "####################################### ",
+ };
+
+ static const char *mk2_xpm[] = {
+ "40 13 2 1",
+ ". c #ff0000",
+ "# c none",
+ "########################...............#",
+ "########################...............#",
+ "#######################................#", //------------------------
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", // 6
+ ".......................................#",
+ ".......................................#",
+ ".......................................#", //--------------------------
+ "#######################................#",
+ "########################...............#",
+ "########################...............#", // 7
+ "####################################### ",
+ };
+
+ static const char *mk3_xpm[] = {
+ "40 13 2 1",
+ ". c #ff0000",
+ "# c none",
+ "########################...............#",
+ "########################...............#",
+ "#######################................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ ".......................................#",
+ "########################################",
+ };
+
+ static const char *mk4_xpm[] = {
+ "40 13 2 1",
+ "# c #ff0000",
+ ". c none",
+ "........................................",
+ "........................................",
+ "........................................",
+ "#######################.................",
+ "########################................",
+ "########################................",
+ "########################................",
+ "########################................",
+ "########################................",
+ "#######################.................",
+ "........................................",
+ "........................................",
+ "........................................",
+ };
+
+ if (octave == 0) {
+ octave = new QPixmap(oct_xpm);
+ mk1 = new QPixmap(mk1_xpm);
+ mk2 = new QPixmap(mk2_xpm);
+ mk3 = new QPixmap(mk3_xpm);
+ mk4 = new QPixmap(mk4_xpm);
+ }
+ yRange = keyHeight * 75;
+ }
+
+//---------------------------------------------------------
+// pitch2y
+// y = 0 == origin of rCanvasA
+//---------------------------------------------------------
+
+int TimeCanvas::pitch2y(int pitch) const
+ {
+ int y;
+ if (type == TIME_CANVAS_DRUMEDIT)
+ y = pitch * drumHeight;
+ else {
+ static int tt[] = {
+ 12, 19, 25, 32, 38, 51, 58, 64, 71, 77, 84, 90
+ };
+ y = (75 * keyHeight) - (tt[pitch % 12] + (7 * keyHeight) * (pitch / 12));
+ if (y < 0)
+ y = 0;
+ }
+ return lrint(y - wpos.y() / _ymag);
+ }
+
+//---------------------------------------------------------
+// y2pitch
+// y = 0 == origin of rCanvasA
+//---------------------------------------------------------
+
+int TimeCanvas::y2pitch(int y) const
+ {
+ y = lrint((y + wpos.y()) / _ymag);
+ int pitch;
+ if (type == TIME_CANVAS_DRUMEDIT)
+ pitch = y / drumHeight;
+ else {
+ const int total = (10 * 7 + 5) * keyHeight; // 75 Ganztonschritte
+ y = total - y;
+ int oct = (y / (7 * keyHeight)) * 12;
+ char kt[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7,
+ 8, 8, 8, 8, 8, 8, 8,
+ 9, 9, 9, 9, 9, 9,
+ 10, 10, 10, 10, 10, 10, 10,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 11
+ };
+ pitch = kt[y % 91] + oct;
+ if (pitch < 0 || pitch > 127)
+ pitch = -1;
+ }
+ return pitch;
+ }
+
+//---------------------------------------------------------
+// paintPiano
+//---------------------------------------------------------
+
+void TimeCanvas::paintPiano(QPainter& p, QRect r)
+ {
+ int d = int(_ymag)+1;
+ qreal x = qreal(r.x());
+ qreal y = (r.y()-rulerHeight-d) / _ymag;
+ if (y < 0.0)
+ y = 0.0;
+ qreal h = (r.height()+d) / _ymag;
+ QPointF offset(x, wpos.y() / _ymag + keyHeight * 2 + y);
+
+ p.translate(0.0, qreal(rulerHeight));
+ p.scale(1.0, _ymag);
+ p.drawTiledPixmap(QRectF(x, y, qreal(r.width()), h), *octave, offset);
+
+ if (curPitch != -1) {
+ int y = pitch2y(curPitch);
+ QPixmap* pm;
+ switch(curPitch % 12) {
+ case 0:
+ case 5:
+ pm = mk3;
+ break;
+ case 2:
+ case 7:
+ case 9:
+ pm = mk2;
+ break;
+ case 4:
+ case 11:
+ pm = mk1;
+ break;
+ default:
+ pm = mk4;
+ break;
+ }
+ p.drawPixmap(0, y, *pm);
+ }
+ p.resetMatrix();
+ }
+
+//---------------------------------------------------------
+// paintPianorollHorizontalGrid
+//---------------------------------------------------------
+
+void TimeCanvas::paintPianorollHorizontalGrid(QPainter& p, QRect r)
+ {
+ qreal offset = rulerHeight - wpos.y();
+ qreal kh = keyHeight * _ymag;
+
+ int x1 = r.x();
+ int x2 = x1 + r.width();
+ if (x1 < pianoWidth)
+ x1 = pianoWidth;
+ qreal y = kh + offset;
+ qreal y1 = r.y() - _ymag;
+ qreal y2 = y1 + r.height() + _ymag;
+ for (int key = 1; key < 75; ++key, y += kh) {
+ if (y < y1)
+ continue;
+ if (y > y2)
+ break;
+ switch (key % 7) {
+ case 2:
+ case 5:
+ p.setPen(QPen(Qt::lightGray));
+ break;
+ default:
+ p.setPen(QPen(Qt::gray));
+ break;
+ }
+ p.drawLine(QLineF(x1, y, x2, y));
+ }
+ }
+
+//---------------------------------------------------------
+// paintDrumeditHorizontalGrid
+//---------------------------------------------------------
+
+void TimeCanvas::paintDrumeditHorizontalGrid(QPainter& p, QRect r)
+ {
+ int offset = rulerHeight - wpos.y();
+
+ p.setPen(QPen(Qt::lightGray));
+ int x1 = r.x();
+ int x2 = x1 + r.width();
+ if (x1 < drumWidth)
+ x1 = drumWidth;
+
+ p.setPen(QPen(Qt::lightGray));
+
+ int y = offset;
+ int y1 = r.y();
+ int y2 = y1 + r.height();
+ for (int i = 0; i < 128; ++i, y += drumHeight) {
+ if (y < y1)
+ continue;
+ if (y > y2)
+ break;
+ p.drawLine(QLine(x1, y, x2, y));
+ }
+ }
+
+//---------------------------------------------------------
+// addCtrlClicked
+//---------------------------------------------------------
+
+void TimeCanvas::addCtrlClicked()
+ {
+ addController();
+ }
+
+//---------------------------------------------------------
+// updateGeometry
+//---------------------------------------------------------
+
+void TimeCanvas::updateGeometry()
+ {
+ int wh = _widget->height();
+ int ww = _widget->width();
+ if (wh < ctrlHeight)
+ ctrlHeight = wh;
+
+ int x1 = 0;
+ if (type == TIME_CANVAS_PIANOROLL)
+ x1 = pianoWidth;
+ else if (type == TIME_CANVAS_DRUMEDIT)
+ x1 = drumWidth;
+ else if (type == TIME_CANVAS_WAVEEDIT)
+ x1 = waveWidth;
+ int y2 = wh - ctrlHeight;
+
+ rPanelA.setRect(0, rulerHeight, x1, wh - rulerHeight - ctrlHeight);
+ rPanelB.setRect(0, y2, x1, ctrlHeight);
+
+ int cw = ww - x1;
+ rRuler.setRect( x1, 0, cw, rulerHeight);
+ rCanvasA.setRect(x1, rulerHeight, cw, wh - rulerHeight - ctrlHeight);
+ rCanvasB.setRect(x1, y2, cw, ctrlHeight);
+
+ rButton.setRect(0, 0, rCanvasA.x(), rPanelA.y());
+
+ if (yRange > 0 && _yFit) {
+ _ymagMin = double(rCanvasA.height()) / double(yRange);
+ if (_ymag < _ymagMin)
+ _ymag = _ymagMin;
+ if (vmag)
+ vmag->setValue(lrint((_ymag-_ymagMin)*100.0/(_ymagMax-_ymagMin)));
+ }
+ }
+
+//---------------------------------------------------------
+// setTool
+//---------------------------------------------------------
+
+void TimeCanvas::setTool(int t)
+ {
+ if (_tool == Tool(t))
+ return;
+ _tool = Tool(t);
+ emit toolChanged(_tool);
+ setCursor();
+ }
+
+//---------------------------------------------------------
+// setCursor
+//---------------------------------------------------------
+
+void TimeCanvas::setCursor()
+ {
+ switch(_tool) {
+ case PencilTool:
+ widget()->setCursor(QCursor(QPixmap(":/xpm/pencil.xpm"), 4, 15));
+ break;
+ case RubberTool:
+ widget()->setCursor(QCursor(QPixmap(":/xpm/delete.xpm"), 4, 15));
+ break;
+ case GlueTool:
+ widget()->setCursor(QCursor(QPixmap(":/xpm/glue.xpm"), 4, 15));
+ break;
+ case CutTool:
+ widget()->setCursor(QCursor(QPixmap(":/xpm/cut.xpm"), 4, 15));
+ break;
+ case MuteTool:
+ widget()->setCursor(QCursor(QPixmap(":/xpm/editmute.xmp"), 4, 15));
+ break;
+ default:
+ widget()->setCursor(QCursor(Qt::ArrowCursor));
+ break;
+ }
+ }
+
+//---------------------------------------------------------
+// setCanvasBackground
+//---------------------------------------------------------
+
+void TimeCanvas::setCanvasBackground(const QColor& color)
+ {
+ canvasBackgroundPixmap = QPixmap();
+ canvasBackgroundColor = color;
+ widget()->update();
+ }
+
+//---------------------------------------------------------
+// setCanvasBackground
+//---------------------------------------------------------
+
+void TimeCanvas::setCanvasBackground(const QPixmap& pm)
+ {
+ canvasBackgroundPixmap = pm;
+ widget()->update();
+ }
+
+//---------------------------------------------------------
+// setYMagRange
+//---------------------------------------------------------
+
+void TimeCanvas::setYMagRange(double min, double max)
+ {
+ _ymagMin = min;
+ _ymagMax = max;
+ if (vmag)
+ vmag->setValue(lrint((_ymag-_ymagMin)*100.0/(_ymagMax-_ymagMin)));
+ }
+
+//---------------------------------------------------------
+// setVSize
+//---------------------------------------------------------
+
+void TimeCanvas::setVSize(int val)
+ {
+ if (yRange == val)
+ return;
+ yRange = val;
+ if (_yFit) {
+ _ymagMin = double(rCanvasA.height()) / double(yRange);
+ if (_ymag < _ymagMin)
+ _ymag = _ymagMin;
+ if (vmag)
+ vmag->setValue(lrint((_ymag-_ymagMin)*100.0/(_ymagMax-_ymagMin)));
+ }
+ updateScrollBars();
+ }
+
+//---------------------------------------------------------
+// s2xmag
+// nonlinear xmag behaviour, feels better
+//---------------------------------------------------------
+
+double TimeCanvas::s2xmag(int val)
+ {
+ val = 100 - val;
+ double f = 1.0 - log10(val * val + 1) * 0.25;
+ return (_xmagMax - _xmagMin) * f + _xmagMin;
+ }
+
+//---------------------------------------------------------
+// xmag2s
+//---------------------------------------------------------
+
+int TimeCanvas::xmag2s(double m)
+ {
+ m -= _xmagMin;
+ m /= (_xmagMax - _xmagMin);
+ double val = sqrt(exp10((1.0 - m) * 4.0)-1.0);
+ return lrint(100.0 - val);
+ }
+
+//---------------------------------------------------------
+// setPart
+//---------------------------------------------------------
+
+void TimeCanvas::setPart(const AL::Pos& p1, const AL::Pos& p2)
+ {
+ partPos1 = p1;
+ partPos2 = p2;
+ widget()->update();
+ }
+
+//---------------------------------------------------------
+// setFont1
+//---------------------------------------------------------
+
+void TimeCanvas::setFont1(const QFont& f)
+ {
+ _font1 = f;
+ printf("TimeCanvas::setFont1\n");
+ }
+
+//---------------------------------------------------------
+// setFont2
+//---------------------------------------------------------
+
+void TimeCanvas::setFont2(const QFont& f)
+ {
+ _font2 = f;
+ }
+
+//---------------------------------------------------------
+// setFont3
+//---------------------------------------------------------
+
+void TimeCanvas::setFont3(const QFont& f)
+ {
+ _font3 = f;
+ }
+
diff --git a/muse2/awl/tcanvas.h b/muse2/awl/tcanvas.h
new file mode 100644
index 00000000..09b26b1d
--- /dev/null
+++ b/muse2/awl/tcanvas.h
@@ -0,0 +1,293 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __TCANVAS_H__
+#define __TCANVAS_H__
+
+#include "al/pos.h"
+#include "al/marker.h"
+
+#define MAP_OFFSET 20
+
+enum TimeCanvasType {
+ TIME_CANVAS, TIME_CANVAS_PIANOROLL, TIME_CANVAS_DRUMEDIT,
+ TIME_CANVAS_WAVEEDIT
+ };
+
+enum Tool {
+ PointerTool=1, PencilTool=2, RubberTool=4, CutTool=8,
+ GlueTool=16, QuantTool=32, DrawTool=64, MuteTool=128
+ };
+
+enum FollowMode {
+ FOLLOW_NO, FOLLOW_JUMP, FOLLOW_CONTINUOUS
+ };
+
+static const int rulerHeight = 28;
+static const int pianoWidth = 40;
+static const int waveWidth = 40;
+static const int drumWidth = 120;
+static const int drumHeight = 18;
+static const int keyHeight = 13;
+
+//---------------------------------------------------------
+// TimeCanvas
+//
+// Layout:
+// Button Ruler
+// panelA canvasA
+// panelB canvasB
+//
+// Pianoroll:
+// panelA -> keyboard
+//
+// Drumeditor:
+// panelA -> instrument list
+//
+//---------------------------------------------------------
+
+class TimeCanvas : public QFrame {
+ Q_OBJECT
+
+ Q_PROPERTY(QFont font1 READ font1 WRITE setFont1)
+ Q_PROPERTY(QFont font2 READ font2 WRITE setFont2)
+ Q_PROPERTY(QFont font3 READ font3 WRITE setFont3)
+
+ // I could not find out how to set the size of a font property with
+ // style sheets. As a workaround here are special "size" properties
+ // which could be set with style sheet command
+ // TimeCanvas { qproperty-fontSize1: 6 }
+
+ Q_PROPERTY(int fontSize1 READ fontSize1 WRITE setFontSize1 STORED false)
+ Q_PROPERTY(int fontSize2 READ fontSize2 WRITE setFontSize2 STORED false)
+ Q_PROPERTY(int fontSize3 READ fontSize3 WRITE setFontSize3 STORED false)
+
+ QFont _font1;
+ QFont _font2;
+ QFont _font3;
+
+ int yRange;
+ bool _yFit;
+ AL::Pos pos1; // time scroll range
+ AL::Pos pos2;
+
+ int metronomeRulerMag;
+
+ double _xmagMin, _xmagMax;
+ double _ymagMin, _ymagMax;
+
+ AL::TType _timeType;
+ AL::MarkerList* marker;
+ QScrollBar* hbar;
+ QScrollBar* vbar;
+ QSlider* vmag;
+ QSlider* hmag;
+ QToolButton* timeTypeButton;
+ QGridLayout* grid;
+ QColor canvasBackgroundColor;
+ QPixmap canvasBackgroundPixmap;
+ int dragType;
+ bool followPos;
+
+ //
+ // pianoroll variables
+ //
+ static QPixmap* octave;
+ static QPixmap* mk1;
+ static QPixmap* mk2;
+ static QPixmap* mk3;
+ static QPixmap* mk4;
+ QPushButton* addCtrlButton;
+
+ bool mouseInB;
+
+ void updateScrollBars();
+ void canvasPaintEvent(const QRect&, QPainter&);
+ void paintCanvas(QPainter&, const QRect&);
+ void paintMetronomRuler(QPainter&, const QRect&);
+ void paintClockRuler(QPainter&, const QRect&);
+ void initPianoroll();
+ void paintPiano(QPainter&, QRect);
+ void paintPianorollHorizontalGrid(QPainter&, QRect);
+ void paintDrumeditHorizontalGrid(QPainter&, QRect);
+ void updateGeometry();
+ double s2xmag(int val);
+ int xmag2s(double m);
+ void updateRulerMag();
+
+ protected:
+ TimeCanvasType type;
+ Tool _tool;
+ QRect rButton, rPanelA, rPanelB, rRuler, rCanvasA, rCanvasB;
+ AL::Pos pos[3];
+ bool showCursor;
+ AL::Pos cursor;
+
+ QWidget* _widget;
+
+ AL::Pos partPos1; // active time range for midi editors
+ AL::Pos partPos2;
+
+ QPoint wpos; // "widget" position
+ double _xmag, _ymag;
+
+ int ctrlHeight;
+ int curPitch;
+
+ int _raster;
+ int button;
+ Qt::KeyboardModifiers keyState;
+
+ bool eventFilter(QObject*, QEvent*);
+
+ virtual void paint(QPainter&, QRect) = 0;
+ virtual void mousePress(QMouseEvent*) {}
+ virtual void mouseMove(QPoint) {}
+ virtual void mouseRelease(QMouseEvent*) {}
+ virtual void mouseDoubleClick(QMouseEvent*) {}
+ virtual void paintDrumList(QPainter&, QRect) {}
+ virtual void layout() {}
+ virtual void enterB() {}
+ virtual void leaveB() {}
+
+ virtual void setCursor();
+
+ virtual void timeTypeChanged() {}
+ virtual void magChanged() {}
+
+ virtual void paintControllerCanvas(QPainter&, QRect) {}
+ virtual void paintControllerPanel(QPainter&, QRect) {}
+
+ virtual void dragEnter(QDragEnterEvent*) {}
+ virtual void drop(QDropEvent*) {}
+ virtual void dragMove(QDragMoveEvent*) {}
+ virtual void dragLeave(QDragLeaveEvent*) {}
+
+ virtual void addController() {}
+
+ virtual void keyPressEvent(QKeyEvent *e);
+ virtual void keyboardNavigate(QKeyEvent *) {}
+
+ // map logical coordinates to physical coordinates (pixel)
+ int mapx(int x) const;
+ int mapy(int y) const { return lrint(y * _ymag) - wpos.y(); }
+ int rmapx(int x) const { return lrint(x * _xmag); }
+ int rmapy(int y) const { return lrint(y * _ymag); }
+ QPoint map(const QPoint& p) const {
+ return QPoint(mapx(p.x()), mapy(p.y()));
+ }
+ QPoint rmap(const QPoint& p) const {
+ return QPoint(rmapx(p.x()), rmapy(p.y()));
+ }
+
+ // map physical coordinates (pixel) to logical coordinates
+ int mapxDev(int x) const;
+ int rmapxDev(int x) const { return lrint(x / _xmag); }
+ int mapyDev(int y) const {
+ int val = lrint((y + wpos.y()) / _ymag);
+ return val < 0 ? 0 : val;
+ }
+ QPoint mapDev(const QPoint& p) const {
+ return QPoint(mapxDev(p.x()), mapyDev(p.y()));
+ }
+
+ virtual int y2pitch(int y) const;
+ virtual int pitch2y(int pitch) const;
+ void setTimeType1(AL::TType t);
+ void setPart(const AL::Pos& p1, const AL::Pos& p2);
+
+ private slots:
+ void moveX(int);
+ void scaleX(int);
+ void scaleY(int);
+ void toggleTimeType();
+ void addCtrlClicked();
+
+ signals:
+ void posChanged(int, const AL::Pos&); // emitted from ruler
+ void cursorPos(const AL::Pos&, bool);
+ void contentsMoving(int, int);
+ void addMarker(const AL::Pos&);
+ void removeMarker(const AL::Pos&);
+ void pitchChanged(int);
+ void toolChanged(int);
+
+ public slots:
+ void setLocatorPos(int idx, const AL::Pos&, bool follow);
+ void setVSize(int);
+ virtual void setRaster(int);
+ void setYPos(int);
+ void moveY(int);
+ void setEndPos(const AL::Pos&);
+ void tempoChanged();
+ void setTool(int);
+ void setFollow(bool val) { followPos = val; }
+
+ public:
+ TimeCanvas(TimeCanvasType = TIME_CANVAS);
+ void setTimeRange(const AL::Pos&, const AL::Pos&);
+ void setMag(double, double);
+ double xmag() const { return _xmag; }
+ double ymag() const { return _ymag; }
+
+ void setYMagRange(double, double);
+ void setYFit(bool val) { _yFit = val; }
+
+ QPoint getWPos() const { return wpos; }
+ QWidget* widget() const { return _widget; }
+ void setWPos(const QPoint& p);
+ void setTimeType(AL::TType t);
+ AL::TType timeType() const { return _timeType; }
+ void setMarkerList(AL::MarkerList*);
+ void setCornerWidget(QWidget* w);
+ void resizeController(int);
+ int raster() const { return _raster; }
+
+ AL::Pos pix2pos(int x) const;
+ int pos2pix(const AL::Pos&) const;
+ QScrollBar* verticalScrollBar() const { return vbar; }
+ Tool tool() const { return _tool; }
+ void setCanvasBackground(const QColor& color);
+ void setCanvasBackground(const QPixmap& pm);
+
+ void updateCanvasB() { _widget->update(rCanvasB); }
+ void updateRuler() { _widget->update(rRuler); }
+
+ QFont font1() const { return _font1; }
+ QFont font2() const { return _font2; }
+ QFont font3() const { return _font3; }
+
+ void setFont1(const QFont& f);
+ void setFont2(const QFont& f);
+ void setFont3(const QFont& f);
+
+ int fontSize1() const { return _font1.pointSize(); }
+ int fontSize2() const { return _font2.pointSize(); }
+ int fontSize3() const { return _font3.pointSize(); }
+ void setFontSize1(int val) { _font1.setPointSize(val); }
+ void setFontSize2(int val) { _font2.setPointSize(val); }
+ void setFontSize3(int val) { _font3.setPointSize(val); }
+
+ static FollowMode followMode;
+ friend class CtrlEdit;
+ };
+
+#endif
+
diff --git a/muse2/awl/tempoedit.cpp b/muse2/awl/tempoedit.cpp
new file mode 100644
index 00000000..d7dbac81
--- /dev/null
+++ b/muse2/awl/tempoedit.cpp
@@ -0,0 +1,88 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "tempoedit.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// TempoEdit
+//---------------------------------------------------------
+
+TempoEdit::TempoEdit(QWidget* parent)
+ : QDoubleSpinBox(parent)
+ {
+ curVal = -1.0;
+ setSingleStep(1.0);
+ setRange(30.0, 600.0);
+ connect(this, SIGNAL(valueChanged(double)), SLOT(newValue(double)));
+ }
+
+//---------------------------------------------------------
+// sizeHint
+//---------------------------------------------------------
+
+QSize TempoEdit::sizeHint() const
+ {
+ QFontMetrics fm(font());
+ int fw = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
+ int h = fm.height() + fw * 2;
+ int w = 2 + fm.width(QString("000.00")) + fw * 4 + 30;
+ return QSize(w, h).expandedTo(QApplication::globalStrut());
+ }
+
+//---------------------------------------------------------
+// newValue
+//---------------------------------------------------------
+
+void TempoEdit::newValue(double val)
+ {
+ if (val != curVal) {
+ curVal = val;
+ emit tempoChanged(tempo());
+ }
+ }
+
+//---------------------------------------------------------
+// setTempo
+//---------------------------------------------------------
+
+void TempoEdit::setTempo(int val)
+ {
+ double d = 60000000.0/double(val);
+ if (d != curVal) {
+ curVal = d;
+ blockSignals(true);
+ setValue(d);
+ blockSignals(false);
+ }
+ }
+
+//---------------------------------------------------------
+// tempo
+//---------------------------------------------------------
+
+int TempoEdit::tempo() const
+ {
+ return lrint(60000000.0/value());
+ }
+
+}
+
diff --git a/muse2/awl/tempoedit.h b/muse2/awl/tempoedit.h
new file mode 100644
index 00000000..af06221d
--- /dev/null
+++ b/muse2/awl/tempoedit.h
@@ -0,0 +1,55 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AWLTEMPOEDIT_H__
+#define __AWLTEMPOEDIT_H__
+
+namespace Awl {
+
+//---------------------------------------------------------
+// TempoEdit
+//---------------------------------------------------------
+
+class TempoEdit : public QDoubleSpinBox {
+ Q_OBJECT
+
+ double curVal;
+
+ protected:
+ QSize sizeHint() const;
+
+ private slots:
+ void newValue(double);
+
+ public slots:
+ void setTempo(int);
+
+ signals:
+ void tempoChanged(int);
+
+ public:
+ TempoEdit(QWidget*);
+ int tempo() const;
+ };
+
+}
+
+#endif
+
diff --git a/muse2/awl/tempolabel.cpp b/muse2/awl/tempolabel.cpp
new file mode 100644
index 00000000..3fcdec5c
--- /dev/null
+++ b/muse2/awl/tempolabel.cpp
@@ -0,0 +1,72 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "tempolabel.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// TempoLabel
+//---------------------------------------------------------
+
+TempoLabel::TempoLabel(QWidget* parent)
+ : QLabel(parent)
+ {
+ setFrameStyle(WinPanel | Sunken);
+ setLineWidth(2);
+ setMidLineWidth(3);
+ _value = 1.0;
+ setValue(0.0);
+ setIndent(3);
+ setMinimumSize(sizeHint());
+ }
+
+//---------------------------------------------------------
+// setVal
+//---------------------------------------------------------
+
+void TempoLabel::setValue(int val)
+ {
+ setValue(double(val/1000.0));
+ }
+
+void TempoLabel::setValue(double val)
+ {
+ if (val == _value)
+ return;
+ _value = val;
+ QString s = QString("%1").arg(val, 3, 'f', 2);
+ setText(s);
+ }
+
+//---------------------------------------------------------
+// sizeHint
+//---------------------------------------------------------
+
+QSize TempoLabel::sizeHint() const
+ {
+ QFontMetrics fm(font());
+ int fw = 4;
+ int h = fm.height() + fw * 2;
+ int w = 6 + fm.width(QString("000.00")) + fw * 2; // 6=indent
+ return QSize(w, h).expandedTo(QApplication::globalStrut());
+ }
+}
+
diff --git a/muse2/awl/tempolabel.h b/muse2/awl/tempolabel.h
new file mode 100644
index 00000000..cf30444e
--- /dev/null
+++ b/muse2/awl/tempolabel.h
@@ -0,0 +1,48 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AWLTEMPOLABEL_H__
+#define __AWLTEMPOLABEL_H__
+
+namespace Awl {
+
+//---------------------------------------------------------
+// TempoLabel
+//---------------------------------------------------------
+
+class TempoLabel : public QLabel {
+ double _value;
+
+ Q_OBJECT
+
+ protected:
+ QSize sizeHint() const;
+
+ public slots:
+ void setValue(int);
+ void setValue(double);
+
+ public:
+ TempoLabel(QWidget*);
+ };
+}
+
+#endif
+
diff --git a/muse2/awl/utils.cpp b/muse2/awl/utils.cpp
new file mode 100644
index 00000000..030ae538
--- /dev/null
+++ b/muse2/awl/utils.cpp
@@ -0,0 +1,50 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include <QString>
+
+#include "utils.h"
+
+static const char* vall[] = {
+ "c","c#","d","d#","e","f","f#","g","g#","a","a#","h"
+ };
+static const char* valu[] = {
+ "C","C#","D","D#","E","F","F#","G","G#","A","A#","H"
+ };
+
+namespace Awl {
+
+//---------------------------------------------------------
+// pitch2string
+//---------------------------------------------------------
+
+QString pitch2string(int v)
+ {
+ if (v < 0 || v > 127)
+ return QString("----");
+ int octave = (v / 12) - 2;
+ QString o;
+ o.sprintf("%d", octave);
+ int i = v % 12;
+ QString s(octave < 0 ? valu[i] : vall[i]);
+ return s + o;
+ }
+}
+
diff --git a/muse2/awl/utils.h b/muse2/awl/utils.h
new file mode 100644
index 00000000..f354a399
--- /dev/null
+++ b/muse2/awl/utils.h
@@ -0,0 +1,31 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AWLUTILS_H__
+#define __AWLUTILS_H__
+
+class QString;
+
+namespace Awl {
+ extern QString pitch2string(int);
+ }
+
+#endif
+
diff --git a/muse2/awl/volentry.cpp b/muse2/awl/volentry.cpp
new file mode 100644
index 00000000..23b38720
--- /dev/null
+++ b/muse2/awl/volentry.cpp
@@ -0,0 +1,37 @@
+//=============================================================================
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "fastlog.h"
+#include "volentry.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// VolEntry
+//---------------------------------------------------------
+
+VolEntry::VolEntry(QWidget* parent)
+ : FloatEntry(parent)
+ {
+ setRange(-60.0f, 10.0f);
+ setSpecialText(tr("off"));
+ setPrecision(0);
+ setLog(true);
+ }
+}
+
diff --git a/muse2/awl/volentry.h b/muse2/awl/volentry.h
new file mode 100644
index 00000000..0b51b945
--- /dev/null
+++ b/muse2/awl/volentry.h
@@ -0,0 +1,41 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AWLVOLENTRY_H__
+#define __AWLVOLENTRY_H__
+
+#include "floatentry.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// VolEntry
+//---------------------------------------------------------
+
+class VolEntry : public FloatEntry {
+ Q_OBJECT
+
+ public:
+ VolEntry(QWidget* parent);
+ };
+
+}
+
+#endif
diff --git a/muse2/awl/volknob.cpp b/muse2/awl/volknob.cpp
new file mode 100644
index 00000000..da9a1e63
--- /dev/null
+++ b/muse2/awl/volknob.cpp
@@ -0,0 +1,39 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "fastlog.h"
+#include "volknob.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// VolKnob
+//---------------------------------------------------------
+
+VolKnob::VolKnob(QWidget* parent)
+ : Knob(parent)
+ {
+ setLog(true);
+ setRange(-60.0f, 10.0f);
+ _lineStep = .8f;
+ _pageStep = 3.0f;
+ }
+}
+
diff --git a/muse2/awl/volknob.h b/muse2/awl/volknob.h
new file mode 100644
index 00000000..7cec4335
--- /dev/null
+++ b/muse2/awl/volknob.h
@@ -0,0 +1,46 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AWLVOLKNOB_H__
+#define __AWLVOLKNOB_H__
+
+#include "knob.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// VolKnob
+//! Volume Knob entry widget
+//
+//! This widget implements knob with a logarithmic
+//! floating point scale used to adjust the volume
+//! in an audio mixer.
+//---------------------------------------------------------
+
+class VolKnob : public Knob {
+ Q_OBJECT
+
+ public:
+ VolKnob(QWidget* parent = 0);
+ };
+}
+
+#endif
+
diff --git a/muse2/awl/volslider.cpp b/muse2/awl/volslider.cpp
new file mode 100644
index 00000000..59f1b8cf
--- /dev/null
+++ b/muse2/awl/volslider.cpp
@@ -0,0 +1,85 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#include "fastlog.h"
+#include "volslider.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// VolSlider
+//---------------------------------------------------------
+
+VolSlider::VolSlider(QWidget* parent)
+ : Slider(parent)
+ {
+ setLog(true);
+ setRange(-60.0f, 10.0f);
+ setScaleWidth(7);
+ setLineStep(.8f);
+ setPageStep(3.0f);
+ }
+
+//---------------------------------------------------------
+// mouseDoubleClickEvent
+//---------------------------------------------------------
+
+void VolSlider::mouseDoubleClickEvent(QMouseEvent* ev)
+ {
+ if (ev->button() == Qt::RightButton)
+ _value = 0.0;
+ else
+ _value = _minValue;
+ valueChange();
+ update();
+ }
+
+
+//---------------------------------------------------------
+// setValue
+//---------------------------------------------------------
+
+void VolSlider::setValue(double val)
+ {
+ if (_log) {
+ if (val == 0.0f)
+ _value = _minValue;
+ else {
+ _value = fast_log10(val) * 20.0f;
+ if (_value < _minValue)
+ _value = _minValue;
+ }
+ }
+ else
+ _value = val;
+ update();
+ }
+
+//---------------------------------------------------------
+// value
+//---------------------------------------------------------
+
+double VolSlider::value() const
+ {
+ return _log ? (_value <= _minValue) ? 0.0f : pow(10.0, _value*0.05f)
+ : _value;
+ }
+
+}
diff --git a/muse2/awl/volslider.h b/muse2/awl/volslider.h
new file mode 100644
index 00000000..22b4000f
--- /dev/null
+++ b/muse2/awl/volslider.h
@@ -0,0 +1,57 @@
+//=============================================================================
+// Awl
+// Audio Widget Library
+// $Id:$
+//
+// Copyright (C) 2002-2006 by Werner Schweer and others
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//=============================================================================
+
+#ifndef __AWLVOLSLIDER_H__
+#define __AWLVOLSLIDER_H__
+
+#include "slider.h"
+
+namespace Awl {
+
+//---------------------------------------------------------
+// VolSlider
+//! Volume Slider entry widget
+//
+//! This widget implements a slider with a logarithmic
+//! floating point scale used to adjust the volume
+//! in an audio mixer.
+//! Internal value represents gain as a logarythmic
+//! dB value.
+//---------------------------------------------------------
+
+class VolSlider : public Slider {
+ Q_OBJECT
+
+ protected:
+ virtual void mouseDoubleClickEvent(QMouseEvent*);
+
+ public slots:
+ virtual void setValue(double v);
+
+ public:
+ VolSlider(QWidget* parent = 0);
+
+ virtual double value() const;
+ };
+
+}
+
+#endif
+