diff options
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 + |