| @@ -34,7 +34,11 @@ c++/carla-backend/doxygen/ | |||
| c++/carla-includes/vst/ | |||
| c++/jackmeter/cadence_jackmeter | |||
| c++/*/*-build-*-Debug/ | |||
| c++/*/*-build-*-Release/ | |||
| src/resources_rc.py | |||
| resources/qrc_resources.cpp | |||
| # incoming | |||
| @@ -46,7 +50,4 @@ c++/carla-backend/carla_backend_lv2.cpp | |||
| c++/carla-backend/carla_backend_vst.cpp | |||
| c++/carla-bridge/qt-plugin/ | |||
| c++/flmixer/ | |||
| c++/xycontroller/ | |||
| c++/widgets/ledbutton.* | |||
| c++/widgets/pixmapdial.* | |||
| c++/widgets/pixmapkeyboard.* | |||
| @@ -6,26 +6,23 @@ | |||
| CXX ?= g++ | |||
| STRIP ?= strip | |||
| PKGCONFIG ?= pkg-config | |||
| BASE_FLAGS = -O2 -ffast-math -fomit-frame-pointer -fPIC -mtune=generic -msse -mfpmath=sse -Wall | |||
| BUILD_FLAGS = $(BASE_FLAGS) -std=c++0x $(CXXFLAGS) | |||
| BUILD_FLAGS += $(shell $(PKGCONFIG) --cflags QtCore QtGui jack) | |||
| BUILD_FLAGS += $(shell pkg-config --cflags QtCore QtGui jack) | |||
| BUILD_FLAGS += -DNDEBUG -DQT_NO_DEBUG -DQT_NO_DEBUG_STREAM -DQT_NO_DEBUG_OUTPUT | |||
| LINK_FLAGS = $(LDFLAGS) | |||
| LINK_FLAGS += $(shell $(PKGCONFIG) --libs QtCore QtGui jack) | |||
| LINK_FLAGS += $(shell pkg-config --libs QtCore QtGui jack) | |||
| OBJS = jackmeter.o \ | |||
| ../widgets/digitalpeakmeter.o | |||
| HAVE_JACKSESSION = $(shell pkg-config --atleast-version=0.121.0 jack && echo true) | |||
| ifeq ($(HAVE_JACKSESSION),true) | |||
| ifeq ($(shell pkg-config --atleast-version=0.121.0 jack && echo true),true) | |||
| BUILD_FLAGS += -DHAVE_JACKSESSION | |||
| endif | |||
| OBJS = jackmeter.o \ | |||
| ../widgets/digitalpeakmeter.o | |||
| # -------------------------------------------------------------- | |||
| all: cadence_jackmeter | |||
| @@ -0,0 +1,245 @@ | |||
| /* | |||
| * Pixmap Dial, a custom Qt4 widget | |||
| * Copyright (C) 2011-2012 Filipe Coelho <falktx@gmail.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or modify | |||
| * it under the terms of the GNU General Public License as published by | |||
| * the Free Software Foundation; either version 2 of the License, or | |||
| * any later version. | |||
| * | |||
| * 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. | |||
| * | |||
| * For a full copy of the GNU General Public License see the COPYING file | |||
| */ | |||
| #include "pixmapdial.h" | |||
| #include <QtCore/QTimer> | |||
| #include <QtGui/QPainter> | |||
| PixmapDial::PixmapDial(QWidget* parent): | |||
| QDial(parent) | |||
| { | |||
| m_pixmap.load(":/bitmaps/dial_01d.png"); | |||
| m_pixmap_n_str = "01"; | |||
| m_custom_paint = CUSTOM_PAINT_NULL; | |||
| m_hovered = false; | |||
| m_hover_step = HOVER_MIN; | |||
| if (m_pixmap.width() > m_pixmap.height()) | |||
| m_orientation = HORIZONTAL; | |||
| else | |||
| m_orientation = VERTICAL; | |||
| m_label = ""; | |||
| m_label_pos = QPointF(0.0, 0.0); | |||
| m_label_width = 0; | |||
| m_label_height = 0; | |||
| m_label_gradient = QLinearGradient(0, 0, 0, 1); | |||
| if (palette().window().color().lightness() > 100) | |||
| { | |||
| // Light background | |||
| QColor c = palette().dark().color(); | |||
| m_color1 = c; | |||
| m_color2 = QColor(c.red(), c.green(), c.blue(), 0); | |||
| m_colorT[0] = palette().buttonText().color(); | |||
| m_colorT[1] = palette().mid().color(); | |||
| } | |||
| else | |||
| { | |||
| // Dark background | |||
| m_color1 = QColor(0, 0, 0, 255); | |||
| m_color2 = QColor(0, 0, 0, 0); | |||
| m_colorT[0] = Qt::white; | |||
| m_colorT[1] = Qt::darkGray; | |||
| } | |||
| updateSizes(); | |||
| } | |||
| int PixmapDial::getSize() const | |||
| { | |||
| return p_size; | |||
| } | |||
| void PixmapDial::setCustomPaint(CustomPaint paint) | |||
| { | |||
| m_custom_paint = paint; | |||
| update(); | |||
| } | |||
| void PixmapDial::setEnabled(bool enabled) | |||
| { | |||
| if (isEnabled() != enabled) | |||
| { | |||
| m_pixmap.load(QString(":/dial_%1%2.png").arg(m_pixmap_n_str).arg(enabled ? "" : "d")); | |||
| updateSizes(); | |||
| update(); | |||
| } | |||
| QDial::setEnabled(enabled); | |||
| } | |||
| void PixmapDial::setLabel(QString label) | |||
| { | |||
| m_label = label; | |||
| m_label_width = QFontMetrics(font()).width(label); | |||
| m_label_height = QFontMetrics(font()).height(); | |||
| m_label_pos.setX((p_size/2)-(m_label_width/2)); | |||
| m_label_pos.setY(p_size+m_label_height); | |||
| m_label_gradient.setColorAt(0.0, m_color1); | |||
| m_label_gradient.setColorAt(0.6, m_color1); | |||
| m_label_gradient.setColorAt(1.0, m_color2); | |||
| m_label_gradient.setStart(0, p_size/2); | |||
| m_label_gradient.setFinalStop(0, p_size+m_label_height+5); | |||
| m_label_gradient_rect = QRectF(p_size*1/8, p_size/2, p_size*6/8, p_size+m_label_height+5); | |||
| update(); | |||
| } | |||
| void PixmapDial::setPixmap(int pixmap_id) | |||
| { | |||
| if (pixmap_id > 10) | |||
| m_pixmap_n_str = QString::number(pixmap_id); | |||
| else | |||
| m_pixmap_n_str = QString("0%1").arg(pixmap_id); | |||
| m_pixmap.load(QString(":/bitmaps/dial_%1%2.png").arg(m_pixmap_n_str).arg(isEnabled() ? "" : "d")); | |||
| if (m_pixmap.width() > m_pixmap.height()) | |||
| m_orientation = HORIZONTAL; | |||
| else | |||
| m_orientation = VERTICAL; | |||
| updateSizes(); | |||
| update(); | |||
| } | |||
| QSize PixmapDial::minimumSizeHint() const | |||
| { | |||
| return QSize(p_size, p_size); | |||
| } | |||
| QSize PixmapDial::sizeHint() const | |||
| { | |||
| return QSize(p_size, p_size); | |||
| } | |||
| void PixmapDial::updateSizes() | |||
| { | |||
| p_width = m_pixmap.width(); | |||
| p_height = m_pixmap.height(); | |||
| if (p_width < 1) | |||
| p_width = 1; | |||
| if (p_height < 1) | |||
| p_height = 1; | |||
| if (m_orientation == HORIZONTAL) | |||
| { | |||
| p_size = p_height; | |||
| p_count = p_width/p_height; | |||
| } | |||
| else | |||
| { | |||
| p_size = p_width; | |||
| p_count = p_height/p_width; | |||
| } | |||
| setMinimumSize(p_size, p_size + m_label_height + 5); | |||
| setMaximumSize(p_size, p_size + m_label_height + 5); | |||
| } | |||
| void PixmapDial::enterEvent(QEvent* event) | |||
| { | |||
| m_hovered = true; | |||
| if (m_hover_step == HOVER_MIN) | |||
| m_hover_step = HOVER_MIN + 1; | |||
| QDial::enterEvent(event); | |||
| } | |||
| void PixmapDial::leaveEvent(QEvent* event) | |||
| { | |||
| m_hovered = false; | |||
| if (m_hover_step == HOVER_MAX) | |||
| m_hover_step = HOVER_MAX - 1; | |||
| QDial::leaveEvent(event); | |||
| } | |||
| void PixmapDial::paintEvent(QPaintEvent*) | |||
| { | |||
| QPainter painter(this); | |||
| if (! m_label.isEmpty()) | |||
| { | |||
| painter.setPen(m_color2); | |||
| painter.setBrush(m_label_gradient); | |||
| painter.drawRect(m_label_gradient_rect); | |||
| painter.setPen(isEnabled() ? m_colorT[0] : m_colorT[1]); | |||
| painter.drawText(m_label_pos, m_label); | |||
| } | |||
| QRectF target, source; | |||
| if (isEnabled()) | |||
| { | |||
| float current = value()-minimum(); | |||
| float divider = maximum()-minimum(); | |||
| if (divider == 0.0f) | |||
| return; | |||
| target = QRectF(0.0, 0.0, p_size, p_size); | |||
| float value = current/divider; | |||
| int xpos, ypos, per = int((p_count-1) * value); | |||
| if (m_orientation == HORIZONTAL) | |||
| { | |||
| xpos = p_size*per; | |||
| ypos = 0.0; | |||
| } | |||
| else | |||
| { | |||
| xpos = 0.0; | |||
| ypos = p_size*per; | |||
| } | |||
| source = QRectF(xpos, ypos, p_size, p_size); | |||
| painter.drawPixmap(target, m_pixmap, source); | |||
| // Custom knobs (Dry/Wet and Volume) | |||
| // TODO | |||
| // Custom knobs (L and R) | |||
| // TODO | |||
| if (HOVER_MIN > m_hover_step && m_hover_step < HOVER_MAX) | |||
| { | |||
| m_hover_step += m_hovered ? 1 : -1; | |||
| QTimer::singleShot(20, this, SLOT(update())); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| target = QRectF(0.0, 0.0, p_size, p_size); | |||
| source = target; | |||
| painter.drawPixmap(target, m_pixmap, source); | |||
| } | |||
| } | |||
| void PixmapDial::resizeEvent(QResizeEvent* event) | |||
| { | |||
| updateSizes(); | |||
| QDial::resizeEvent(event); | |||
| } | |||
| @@ -0,0 +1,87 @@ | |||
| /* | |||
| * Pixmap Dial, a custom Qt4 widget | |||
| * Copyright (C) 2011-2012 Filipe Coelho <falktx@gmail.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or modify | |||
| * it under the terms of the GNU General Public License as published by | |||
| * the Free Software Foundation; either version 2 of the License, or | |||
| * any later version. | |||
| * | |||
| * 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. | |||
| * | |||
| * For a full copy of the GNU General Public License see the COPYING file | |||
| */ | |||
| #ifndef PIXMAPDIAL_H | |||
| #define PIXMAPDIAL_H | |||
| #include <QtGui/QDial> | |||
| #include <QtGui/QPixmap> | |||
| class PixmapDial : public QDial | |||
| { | |||
| public: | |||
| enum Orientation { | |||
| HORIZONTAL = 0, | |||
| VERTICAL = 1 | |||
| }; | |||
| enum CustomPaint { | |||
| CUSTOM_PAINT_NULL = 0, | |||
| CUSTOM_PAINT_CARLA_WET = 1, | |||
| CUSTOM_PAINT_CARLA_VOL = 2, | |||
| CUSTOM_PAINT_CARLA_L = 3, | |||
| CUSTOM_PAINT_CARLA_R = 4 | |||
| }; | |||
| PixmapDial(QWidget* parent); | |||
| int getSize() const; | |||
| void setCustomPaint(CustomPaint paint); | |||
| void setEnabled(bool enabled); | |||
| void setLabel(QString label); | |||
| void setPixmap(int pixmap_id); | |||
| QSize minimumSizeHint() const; | |||
| QSize sizeHint() const; | |||
| protected: | |||
| void updateSizes(); | |||
| void enterEvent(QEvent* event); | |||
| void leaveEvent(QEvent* event); | |||
| void paintEvent(QPaintEvent* event); | |||
| void resizeEvent(QResizeEvent* event); | |||
| private: | |||
| QPixmap m_pixmap; | |||
| QString m_pixmap_n_str; | |||
| CustomPaint m_custom_paint; | |||
| Orientation m_orientation; | |||
| bool m_hovered; | |||
| int m_hover_step; | |||
| QString m_label; | |||
| QPointF m_label_pos; | |||
| int m_label_width; | |||
| int m_label_height; | |||
| QLinearGradient m_label_gradient; | |||
| QRectF m_label_gradient_rect; | |||
| QColor m_color1; | |||
| QColor m_color2; | |||
| QColor m_colorT[2]; | |||
| int p_width, p_height, p_size, p_count; | |||
| static const int HOVER_MIN = 0; | |||
| static const int HOVER_MAX = 9; | |||
| }; | |||
| #endif // PIXMAPDIAL_H | |||
| @@ -0,0 +1,506 @@ | |||
| /* | |||
| * Pixmap Keyboard, a custom Qt4 widget | |||
| * Copyright (C) 2011-2012 Filipe Coelho <falktx@gmail.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or modify | |||
| * it under the terms of the GNU General Public License as published by | |||
| * the Free Software Foundation; either version 2 of the License, or | |||
| * any later version. | |||
| * | |||
| * 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. | |||
| * | |||
| * For a full copy of the GNU General Public License see the COPYING file | |||
| */ | |||
| #include "pixmapkeyboard.h" | |||
| #include <QtCore/QMap> | |||
| #include <QtCore/QTimer> | |||
| #include <QtGui/QKeyEvent> | |||
| #include <QtGui/QMouseEvent> | |||
| #include <QtGui/QPainter> | |||
| static QMap<int, QRectF> midi_key2rect_map_horizontal; | |||
| static QMap<int, QRectF> midi_key2rect_map_vertical; | |||
| static QMap<int, int> midi_keyboard2key_map; | |||
| static QVector<int> blackNotes; | |||
| void midi_map_init() | |||
| { | |||
| static bool init = false; | |||
| if (init) return; | |||
| init = true; | |||
| // midi_key2rect_map_horizontal ------ | |||
| midi_key2rect_map_horizontal[0] = QRectF(0, 0, 18, 64); // C | |||
| midi_key2rect_map_horizontal[1] = QRectF(13, 0, 11, 42); // C# | |||
| midi_key2rect_map_horizontal[2] = QRectF(18, 0, 25, 64); // D | |||
| midi_key2rect_map_horizontal[3] = QRectF(37, 0, 11, 42); // D# | |||
| midi_key2rect_map_horizontal[4] = QRectF(42, 0, 18, 64); // E | |||
| midi_key2rect_map_horizontal[5] = QRectF(60, 0, 18, 64); // F | |||
| midi_key2rect_map_horizontal[6] = QRectF(73, 0, 11, 42); // F# | |||
| midi_key2rect_map_horizontal[7] = QRectF(78, 0, 25, 64); // G | |||
| midi_key2rect_map_horizontal[8] = QRectF(97, 0, 11, 42); // G# | |||
| midi_key2rect_map_horizontal[9] = QRectF(102, 0, 25, 64); // A | |||
| midi_key2rect_map_horizontal[10] = QRectF(121, 0, 11, 42); // A# | |||
| midi_key2rect_map_horizontal[11] = QRectF(126, 0, 18, 64); // B | |||
| // midi_key2rect_map_vertical -------- | |||
| midi_key2rect_map_vertical[11] = QRectF(0, 0, 64, 18); // B | |||
| midi_key2rect_map_vertical[10] = QRectF(0, 14, 42, 7); // A# | |||
| midi_key2rect_map_vertical[9] = QRectF(0, 18, 64, 24); // A | |||
| midi_key2rect_map_vertical[8] = QRectF(0, 38, 42, 7); // G# | |||
| midi_key2rect_map_vertical[7] = QRectF(0, 42, 64, 24); // G | |||
| midi_key2rect_map_vertical[6] = QRectF(0, 62, 42, 7); // F# | |||
| midi_key2rect_map_vertical[5] = QRectF(0, 66, 64, 18); // F | |||
| midi_key2rect_map_vertical[4] = QRectF(0, 84, 64, 18); // E | |||
| midi_key2rect_map_vertical[3] = QRectF(0, 98, 42, 7); // D# | |||
| midi_key2rect_map_vertical[2] = QRectF(0, 102, 64, 24); // D | |||
| midi_key2rect_map_vertical[1] = QRectF(0, 122, 42, 7); // C# | |||
| midi_key2rect_map_vertical[0] = QRectF(0, 126, 64, 18); // C | |||
| // midi_keyboard2key_map ------------- | |||
| // 3th octave | |||
| midi_keyboard2key_map[Qt::Key_Z] = 48; | |||
| midi_keyboard2key_map[Qt::Key_S] = 49; | |||
| midi_keyboard2key_map[Qt::Key_X] = 50; | |||
| midi_keyboard2key_map[Qt::Key_D] = 51; | |||
| midi_keyboard2key_map[Qt::Key_C] = 52; | |||
| midi_keyboard2key_map[Qt::Key_V] = 53; | |||
| midi_keyboard2key_map[Qt::Key_G] = 54; | |||
| midi_keyboard2key_map[Qt::Key_B] = 55; | |||
| midi_keyboard2key_map[Qt::Key_H] = 56; | |||
| midi_keyboard2key_map[Qt::Key_N] = 57; | |||
| midi_keyboard2key_map[Qt::Key_J] = 58; | |||
| midi_keyboard2key_map[Qt::Key_M] = 59; | |||
| // 4th octave | |||
| midi_keyboard2key_map[Qt::Key_Q] = 60; | |||
| midi_keyboard2key_map[Qt::Key_2] = 61; | |||
| midi_keyboard2key_map[Qt::Key_W] = 62; | |||
| midi_keyboard2key_map[Qt::Key_3] = 63; | |||
| midi_keyboard2key_map[Qt::Key_E] = 64; | |||
| midi_keyboard2key_map[Qt::Key_R] = 65; | |||
| midi_keyboard2key_map[Qt::Key_5] = 66; | |||
| midi_keyboard2key_map[Qt::Key_T] = 67; | |||
| midi_keyboard2key_map[Qt::Key_6] = 68; | |||
| midi_keyboard2key_map[Qt::Key_Y] = 69; | |||
| midi_keyboard2key_map[Qt::Key_7] = 70; | |||
| midi_keyboard2key_map[Qt::Key_U] = 71; | |||
| blackNotes << 1; | |||
| blackNotes << 3; | |||
| blackNotes << 6; | |||
| blackNotes << 8; | |||
| blackNotes << 10; | |||
| } | |||
| PixmapKeyboard::PixmapKeyboard(QWidget* parent): | |||
| QWidget(parent), | |||
| m_font("Monospace", 8, QFont::Normal) | |||
| { | |||
| midi_map_init(); | |||
| m_octaves = 6; | |||
| m_lastMouseNote = -1; | |||
| m_needsUpdate = false; | |||
| setCursor(Qt::PointingHandCursor); | |||
| setMode(HORIZONTAL); | |||
| } | |||
| void PixmapKeyboard::sendNoteOn(int note, bool sendSignal) | |||
| { | |||
| if (note >= 0 && note <= 127 && ! m_enabledKeys.contains(note)) | |||
| { | |||
| m_enabledKeys.append(note); | |||
| if (sendSignal) | |||
| emit noteOn(note); | |||
| m_needsUpdate = true; | |||
| QTimer::singleShot(0, this, SLOT(updateOnce())); | |||
| } | |||
| if (m_enabledKeys.count() == 1) | |||
| emit notesOn(); | |||
| } | |||
| void PixmapKeyboard::sendNoteOff(int note, bool sendSignal) | |||
| { | |||
| if (note >= 0 && note <= 127 && m_enabledKeys.contains(note)) | |||
| { | |||
| m_enabledKeys.removeOne(note); | |||
| if (sendSignal) | |||
| emit noteOff(note); | |||
| m_needsUpdate = true; | |||
| QTimer::singleShot(0, this, SLOT(updateOnce())); | |||
| } | |||
| if (m_enabledKeys.count() == 0) | |||
| emit notesOff(); | |||
| } | |||
| void PixmapKeyboard::setMode(Orientation mode, Color color) | |||
| { | |||
| if (color == COLOR_CLASSIC) | |||
| { | |||
| m_colorStr = "classic"; | |||
| } | |||
| else if (color == COLOR_ORANGE) | |||
| { | |||
| m_colorStr = "orange"; | |||
| } | |||
| else | |||
| { | |||
| qCritical("PixmapKeyboard::setMode(%i, %i) - invalid color", mode, color); | |||
| return setMode(mode); | |||
| } | |||
| if (mode == HORIZONTAL) | |||
| { | |||
| m_midi_map = &midi_key2rect_map_horizontal; | |||
| m_pixmap.load(QString(":/bitmaps/kbd_h_%1.png").arg(m_colorStr)); | |||
| m_pixmap_mode = HORIZONTAL; | |||
| p_width = m_pixmap.width(); | |||
| p_height = m_pixmap.height() / 2; | |||
| } | |||
| else if (mode == VERTICAL) | |||
| { | |||
| m_midi_map = &midi_key2rect_map_vertical; | |||
| m_pixmap.load(QString(":/bitmaps/kbd_v_%1.png").arg(m_colorStr)); | |||
| m_pixmap_mode = VERTICAL; | |||
| p_width = m_pixmap.width() / 2; | |||
| p_height = m_pixmap.height(); | |||
| } | |||
| else | |||
| { | |||
| qCritical("PixmapKeyboard::setMode(%i, %i) - invalid mode", mode, color); | |||
| return setMode(HORIZONTAL); | |||
| } | |||
| setOctaves(m_octaves); | |||
| } | |||
| void PixmapKeyboard::setOctaves(int octaves) | |||
| { | |||
| if (octaves < 1) | |||
| octaves = 1; | |||
| else if (octaves > 6) | |||
| octaves = 6; | |||
| m_octaves = octaves; | |||
| if (m_pixmap_mode == HORIZONTAL) | |||
| { | |||
| setMinimumSize(p_width * m_octaves, p_height); | |||
| setMaximumSize(p_width * m_octaves, p_height); | |||
| } | |||
| else if (m_pixmap_mode == VERTICAL) | |||
| { | |||
| setMinimumSize(p_width, p_height * m_octaves); | |||
| setMaximumSize(p_width, p_height * m_octaves); | |||
| } | |||
| update(); | |||
| } | |||
| void PixmapKeyboard::keyPressEvent(QKeyEvent* event) | |||
| { | |||
| int qKey = event->key(); | |||
| if (midi_keyboard2key_map.keys().contains(qKey)) | |||
| sendNoteOn(midi_keyboard2key_map[qKey]); | |||
| QWidget::keyPressEvent(event); | |||
| } | |||
| void PixmapKeyboard::keyReleaseEvent(QKeyEvent* event) | |||
| { | |||
| int qKey = event->key(); | |||
| if (midi_keyboard2key_map.keys().contains(qKey)) | |||
| sendNoteOff(midi_keyboard2key_map[qKey]); | |||
| QWidget::keyReleaseEvent(event); | |||
| } | |||
| void PixmapKeyboard::mousePressEvent(QMouseEvent* event) | |||
| { | |||
| m_lastMouseNote = -1; | |||
| handleMousePos(event->pos()); | |||
| setFocus(); | |||
| QWidget::mousePressEvent(event); | |||
| } | |||
| void PixmapKeyboard::mouseMoveEvent(QMouseEvent* event) | |||
| { | |||
| handleMousePos(event->pos()); | |||
| QWidget::mousePressEvent(event); | |||
| } | |||
| void PixmapKeyboard::mouseReleaseEvent(QMouseEvent* event) | |||
| { | |||
| if (m_lastMouseNote != -1) | |||
| { | |||
| sendNoteOff(m_lastMouseNote); | |||
| m_lastMouseNote = -1; | |||
| } | |||
| QWidget::mouseReleaseEvent(event); | |||
| } | |||
| void PixmapKeyboard::handleMousePos(const QPoint& pos) | |||
| { | |||
| int note, octave; | |||
| QPointF n_pos; | |||
| if (m_pixmap_mode == HORIZONTAL) | |||
| { | |||
| if (pos.x() < 0 or pos.x() > m_octaves * 144) | |||
| return; | |||
| octave = pos.x() / p_width; | |||
| n_pos = QPointF(pos.x() % p_width, pos.y()); | |||
| } | |||
| else if (m_pixmap_mode == VERTICAL) | |||
| { | |||
| if (pos.y() < 0 or pos.y() > m_octaves * 144) | |||
| return; | |||
| octave = m_octaves - pos.y() / p_height; | |||
| n_pos = QPointF(pos.x(), pos.y() % p_height); | |||
| } | |||
| else | |||
| return; | |||
| octave += 3; | |||
| if ((*m_midi_map)[1].contains(n_pos)) // C# | |||
| note = 1; | |||
| else if ((*m_midi_map)[3].contains(n_pos)) // D# | |||
| note = 3; | |||
| else if ((*m_midi_map)[6].contains(n_pos)) // F# | |||
| note = 6; | |||
| else if ((*m_midi_map)[8].contains(n_pos)) // G# | |||
| note = 8; | |||
| else if ((*m_midi_map)[10].contains(n_pos))// A# | |||
| note = 10; | |||
| else if ((*m_midi_map)[0].contains(n_pos)) // C | |||
| note = 0; | |||
| else if ((*m_midi_map)[2].contains(n_pos)) // D | |||
| note = 2; | |||
| else if ((*m_midi_map)[4].contains(n_pos)) // E | |||
| note = 4; | |||
| else if ((*m_midi_map)[5].contains(n_pos)) // F | |||
| note = 5; | |||
| else if ((*m_midi_map)[7].contains(n_pos)) // G | |||
| note = 7; | |||
| else if ((*m_midi_map)[9].contains(n_pos)) // A | |||
| note = 9; | |||
| else if ((*m_midi_map)[11].contains(n_pos))// B | |||
| note = 11; | |||
| else | |||
| note = -1; | |||
| if (note != -1) | |||
| { | |||
| note += octave * 12; | |||
| if (m_lastMouseNote != note) | |||
| { | |||
| sendNoteOff(m_lastMouseNote); | |||
| sendNoteOn(note); | |||
| } | |||
| } | |||
| else | |||
| sendNoteOff(m_lastMouseNote); | |||
| m_lastMouseNote = note; | |||
| } | |||
| void PixmapKeyboard::paintEvent(QPaintEvent*) | |||
| { | |||
| QPainter painter(this); | |||
| // ------------------------------------------------------------- | |||
| // Paint clean keys (as background) | |||
| for (int octave=0; octave < m_octaves; octave++) | |||
| { | |||
| QRectF target; | |||
| if (m_pixmap_mode == HORIZONTAL) | |||
| target = QRectF(p_width * octave, 0, p_width, p_height); | |||
| else if (m_pixmap_mode == VERTICAL) | |||
| target = QRectF(0, p_height * octave, p_width, p_height); | |||
| else | |||
| return; | |||
| QRectF source = QRectF(0, 0, p_width, p_height); | |||
| painter.drawPixmap(target, m_pixmap, source); | |||
| } | |||
| // ------------------------------------------------------------- | |||
| // Paint (white) pressed keys | |||
| bool paintedWhite = false; | |||
| for (int i=0; i < m_enabledKeys.count(); i++) | |||
| { | |||
| int octave, note = m_enabledKeys[i]; | |||
| QRectF pos = _getRectFromMidiNote(note); | |||
| if (_isNoteBlack(note)) | |||
| continue; | |||
| if (note < 35) | |||
| // cannot paint this note | |||
| continue; | |||
| else if (note < 48) | |||
| octave = 0; | |||
| else if (note < 60) | |||
| octave = 1; | |||
| else if (note < 72) | |||
| octave = 2; | |||
| else if (note < 84) | |||
| octave = 3; | |||
| else if (note < 96) | |||
| octave = 4; | |||
| else if (note < 108) | |||
| octave = 5; | |||
| else | |||
| // cannot paint this note either | |||
| continue; | |||
| if (m_pixmap_mode == VERTICAL) | |||
| octave = m_octaves - octave - 1; | |||
| QRectF target, source; | |||
| if (m_pixmap_mode == HORIZONTAL) | |||
| { | |||
| target = QRectF(pos.x() + (p_width * octave), 0, pos.width(), pos.height()); | |||
| source = QRectF(pos.x(), p_height, pos.width(), pos.height()); | |||
| } | |||
| else if (m_pixmap_mode == VERTICAL) | |||
| { | |||
| target = QRectF(pos.x(), pos.y() + (p_height * octave), pos.width(), pos.height()); | |||
| source = QRectF(p_width, pos.y(), pos.width(), pos.height()); | |||
| } | |||
| else | |||
| return; | |||
| paintedWhite = true; | |||
| painter.drawPixmap(target, m_pixmap, source); | |||
| } | |||
| // ------------------------------------------------------------- | |||
| // Clear white keys border | |||
| if (paintedWhite) | |||
| { | |||
| for (int octave=0; octave < m_octaves; octave++) | |||
| { | |||
| foreach (int note, blackNotes) | |||
| { | |||
| QRectF target, source; | |||
| QRectF pos = _getRectFromMidiNote(note); | |||
| if (m_pixmap_mode == HORIZONTAL) | |||
| { | |||
| target = QRectF(pos.x() + (p_width * octave), 0, pos.width(), pos.height()); | |||
| source = QRectF(pos.x(), 0, pos.width(), pos.height()); | |||
| } | |||
| else if (m_pixmap_mode == VERTICAL) | |||
| { | |||
| target = QRectF(pos.x(), pos.y() + (p_height * octave), pos.width(), pos.height()); | |||
| source = QRectF(0, pos.y(), pos.width(), pos.height()); | |||
| } | |||
| else | |||
| return; | |||
| painter.drawPixmap(target, m_pixmap, source); | |||
| } | |||
| } | |||
| } | |||
| // ------------------------------------------------------------- | |||
| // Paint (black) pressed keys | |||
| for (int i=0; i < m_enabledKeys.count(); i++) | |||
| { | |||
| int octave, note = m_enabledKeys[i]; | |||
| QRectF pos = _getRectFromMidiNote(note); | |||
| if (! _isNoteBlack(note)) | |||
| continue; | |||
| if (note < 35) | |||
| // cannot paint this note | |||
| continue; | |||
| else if (note < 48) | |||
| octave = 0; | |||
| else if (note < 60) | |||
| octave = 1; | |||
| else if (note < 72) | |||
| octave = 2; | |||
| else if (note < 84) | |||
| octave = 3; | |||
| else if (note < 96) | |||
| octave = 4; | |||
| else if (note < 108) | |||
| octave = 5; | |||
| else | |||
| // cannot paint this note either | |||
| continue; | |||
| if (m_pixmap_mode == VERTICAL) | |||
| octave = m_octaves - octave - 1; | |||
| QRectF target, source; | |||
| if (m_pixmap_mode == HORIZONTAL) | |||
| { | |||
| target = QRectF(pos.x() + (p_width * octave), 0, pos.width(), pos.height()); | |||
| source = QRectF(pos.x(), p_height, pos.width(), pos.height()); | |||
| } | |||
| else if (m_pixmap_mode == VERTICAL) | |||
| { | |||
| target = QRectF(pos.x(), pos.y() + (p_height * octave), pos.width(), pos.height()); | |||
| source = QRectF(p_width, pos.y(), pos.width(), pos.height()); | |||
| } | |||
| else | |||
| return; | |||
| painter.drawPixmap(target, m_pixmap, source); | |||
| } | |||
| // Paint C-number note info | |||
| painter.setFont(m_font); | |||
| painter.setPen(Qt::black); | |||
| for (int i=0; i < m_octaves; i++) | |||
| { | |||
| if (m_pixmap_mode == HORIZONTAL) | |||
| painter.drawText(i * 144, 48, 18, 18, Qt::AlignCenter, QString("C%1").arg(i + 2)); | |||
| else if (m_pixmap_mode == VERTICAL) | |||
| painter.drawText(45, (m_octaves * 144) - (i * 144) - 16, 18, 18, Qt::AlignCenter, QString("C%1").arg(i + 2)); | |||
| } | |||
| } | |||
| void PixmapKeyboard::updateOnce() | |||
| { | |||
| if (m_needsUpdate) | |||
| { | |||
| update(); | |||
| m_needsUpdate = false; | |||
| } | |||
| } | |||
| bool PixmapKeyboard::_isNoteBlack(int note) | |||
| { | |||
| int baseNote = note % 12; | |||
| return blackNotes.contains(baseNote); | |||
| } | |||
| QRectF PixmapKeyboard::_getRectFromMidiNote(int note) | |||
| { | |||
| return (*m_midi_map)[note % 12]; | |||
| } | |||
| @@ -0,0 +1,84 @@ | |||
| /* | |||
| * Pixmap Keyboard, a custom Qt4 widget | |||
| * Copyright (C) 2011-2012 Filipe Coelho <falktx@gmail.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or modify | |||
| * it under the terms of the GNU General Public License as published by | |||
| * the Free Software Foundation; either version 2 of the License, or | |||
| * any later version. | |||
| * | |||
| * 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. | |||
| * | |||
| * For a full copy of the GNU General Public License see the COPYING file | |||
| */ | |||
| #ifndef PIXMAPKEYBOARD_H | |||
| #define PIXMAPKEYBOARD_H | |||
| #include <QtGui/QPixmap> | |||
| #include <QtGui/QWidget> | |||
| class PixmapKeyboard : public QWidget | |||
| { | |||
| Q_OBJECT | |||
| public: | |||
| enum Color { | |||
| COLOR_CLASSIC = 0, | |||
| COLOR_ORANGE = 1 | |||
| }; | |||
| enum Orientation { | |||
| HORIZONTAL = 0, | |||
| VERTICAL = 1 | |||
| }; | |||
| PixmapKeyboard(QWidget* parent); | |||
| void sendNoteOn(int note, bool sendSignal=true); | |||
| void sendNoteOff(int note, bool sendSignal=true); | |||
| void setMode(Orientation mode, Color color=COLOR_ORANGE); | |||
| void setOctaves(int octaves); | |||
| signals: | |||
| void noteOn(int); | |||
| void noteOff(int); | |||
| void notesOn(); | |||
| void notesOff(); | |||
| protected: | |||
| void keyPressEvent(QKeyEvent*); | |||
| void keyReleaseEvent(QKeyEvent*); | |||
| void mousePressEvent(QMouseEvent*); | |||
| void mouseMoveEvent(QMouseEvent*); | |||
| void mouseReleaseEvent(QMouseEvent*); | |||
| void handleMousePos(const QPoint&); | |||
| void paintEvent(QPaintEvent*); | |||
| private Q_SLOTS: | |||
| void updateOnce(); | |||
| private: | |||
| QPixmap m_pixmap; | |||
| Orientation m_pixmap_mode; | |||
| QString m_colorStr; | |||
| QFont m_font; | |||
| int m_octaves; | |||
| int m_lastMouseNote; | |||
| int p_width, p_height; | |||
| bool m_needsUpdate; | |||
| QList<int> m_enabledKeys; | |||
| QMap<int, QRectF> *m_midi_map; | |||
| bool _isNoteBlack(int note); | |||
| QRectF _getRectFromMidiNote(int note); | |||
| }; | |||
| #endif // PIXMAPKEYBOARD_H | |||
| @@ -0,0 +1,72 @@ | |||
| #!/usr/bin/make -f | |||
| # Makefile for xycontroller # | |||
| # ------------------------------------ # | |||
| # Created by falkTX | |||
| # | |||
| CXX ?= g++ | |||
| MOC ?= moc | |||
| RCC ?= rcc | |||
| UIC ?= uic | |||
| STRIP ?= strip | |||
| WINDRES ?= windres | |||
| BASE_FLAGS = -O2 -ffast-math -fomit-frame-pointer -fPIC -mtune=generic -msse -mfpmath=sse -Wall -I../widgets | |||
| BUILD_FLAGS = $(BASE_FLAGS) -std=c++0x $(CXXFLAGS) | |||
| BUILD_FLAGS += $(shell pkg-config --cflags QtCore QtGui jack) | |||
| BUILD_FLAGS += -DNDEBUG -DQT_NO_DEBUG -DQT_NO_DEBUG_STREAM -DQT_NO_DEBUG_OUTPUT | |||
| LINK_FLAGS = $(LDFLAGS) | |||
| LINK_FLAGS += $(shell pkg-config --libs QtCore QtGui jack) | |||
| ifeq ($(shell pkg-config --atleast-version=0.121.0 jack && echo true),true) | |||
| BUILD_FLAGS += -DHAVE_JACKSESSION | |||
| endif | |||
| FILES = \ | |||
| xycontroller.moc \ | |||
| ui_xycontroller.h \ | |||
| ../widgets/moc_pixmapkeyboard.cpp \ | |||
| ../../resources/qrc_resources.cpp | |||
| OBJS = xycontroller.o \ | |||
| ../widgets/pixmapdial.o \ | |||
| ../widgets/pixmapkeyboard.o \ | |||
| ../widgets/moc_pixmapkeyboard.o \ | |||
| ../../resources/qrc_resources.o | |||
| # -------------------------------------------------------------- | |||
| all: cadence_xycontroller | |||
| cadence_xycontroller: $(FILES) $(OBJS) | |||
| $(CXX) $(OBJS) $(LINK_FLAGS) -o $@ && strip $@ | |||
| cadence_xycontroller.exe: $(FILES) $(OBJS) icon.o | |||
| $(CXX) $(OBJS) icon.o -static -mwindows $(LINK_FLAGS) -o $@ && strip $@ | |||
| # -------------------------------------------------------------- | |||
| xycontroller.moc: xycontroller.cpp | |||
| $(MOC) $< -o $@ | |||
| ui_xycontroller.h: ../../src/ui/xycontroller.ui | |||
| $(UIC) $< -o $@ | |||
| icon.o: ../../resources/ico/cadence.rc | |||
| $(WINDRES) -i $< -o $@ -O coff | |||
| ../widgets/moc_pixmapkeyboard.cpp: ../widgets/pixmapkeyboard.h | |||
| $(MOC) $< -o $@ | |||
| ../../resources/qrc_resources.cpp: ../../resources/resources.qrc | |||
| $(RCC) -name resources $< -o $@ | |||
| # -------------------------------------------------------------- | |||
| .cpp.o: | |||
| $(CXX) -c $< $(BUILD_FLAGS) -o $@ | |||
| clean: | |||
| rm -f $(FILES) $(OBJS) icon.o cadence_xycontroller* | |||
| @@ -0,0 +1,33 @@ | |||
| # QtCreator project file | |||
| QT = core gui | |||
| CONFIG = debug link_pkgconfig qt resources uic warn_on | |||
| PKGCONFIG = jack | |||
| TARGET = xycontroller | |||
| TEMPLATE = app | |||
| VERSION = 0.5.0 | |||
| DEFINES = HAVE_JACKSESSION | |||
| SOURCES = \ | |||
| ../xycontroller.cpp \ | |||
| ../../widgets/pixmapdial.cpp \ | |||
| ../../widgets/pixmapkeyboard.cpp | |||
| HEADERS = \ | |||
| ../../jack_utils.h \ | |||
| ../../widgets/pixmapdial.h \ | |||
| ../../widgets/pixmapkeyboard.h | |||
| FORMS = \ | |||
| ../../../src/ui/xycontroller.ui | |||
| RESOURCES = \ | |||
| ../../../resources/resources.qrc | |||
| INCLUDEPATH = \ | |||
| ../../widgets | |||
| QMAKE_CXXFLAGS *= -std=c++0x | |||
| @@ -0,0 +1,936 @@ | |||
| /* | |||
| * Simple JACK Audio Meter | |||
| * Copyright (C) 2011-2012 Filipe Coelho <falktx@gmail.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or modify | |||
| * it under the terms of the GNU General Public License as published by | |||
| * the Free Software Foundation; either version 2 of the License, or | |||
| * any later version. | |||
| * | |||
| * 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. | |||
| * | |||
| * For a full copy of the GNU General Public License see the COPYING file | |||
| */ | |||
| #include <QtCore/Qt> | |||
| #ifndef Q_COMPILER_LAMBDA | |||
| # define nullptr (0) | |||
| #endif | |||
| #define VERSION "0.5.0" | |||
| //#include "../jack_utils.h" | |||
| #include "ui_xycontroller.h" | |||
| //#include <QtCore/QMutex> | |||
| #include <QtCore/QSettings> | |||
| #include <QtCore/QTimer> | |||
| #include <QtGui/QApplication> | |||
| #include <QtGui/QGraphicsItem> | |||
| #include <QtGui/QGraphicsScene> | |||
| #include <QtGui/QGraphicsSceneEvent> | |||
| #include <QtGui/QKeyEvent> | |||
| #include <QtGui/QMainWindow> | |||
| #include <QtGui/QMessageBox> | |||
| // ------------------------------- | |||
| class Queue { | |||
| public: | |||
| Queue(int size_) : | |||
| size(size_) | |||
| { | |||
| } | |||
| ~Queue() | |||
| { | |||
| } | |||
| void put_nowait(int, int, int) | |||
| { | |||
| //const QMutexLocker m(&mutex); | |||
| } | |||
| private: | |||
| const int size; | |||
| //QMutex mutex; | |||
| }; | |||
| qreal abs_q(const qreal value) | |||
| { | |||
| if (value < 1.0) | |||
| return -value; | |||
| return value; | |||
| } | |||
| #if 0 | |||
| jack_client_t* jack_client = nullptr; | |||
| jack_port_t* jack_midi_in_port = nullptr; | |||
| jack_port_t* jack_midi_out_port = nullptr; | |||
| #endif | |||
| Queue jack_midi_in_data = Queue(512); | |||
| Queue jack_midi_out_data = Queue(512); | |||
| QVector<QString> MIDI_CC_LIST; | |||
| void MIDI_CC_LIST__init() | |||
| { | |||
| //MIDI_CC_LIST << "0x00 Bank Select"; | |||
| MIDI_CC_LIST << "0x01 Modulation"; | |||
| MIDI_CC_LIST << "0x02 Breath"; | |||
| MIDI_CC_LIST << "0x03 (Undefined)"; | |||
| MIDI_CC_LIST << "0x04 Foot"; | |||
| MIDI_CC_LIST << "0x05 Portamento"; | |||
| //MIDI_CC_LIST << "0x06 (Data Entry MSB)"; | |||
| MIDI_CC_LIST << "0x07 Volume"; | |||
| MIDI_CC_LIST << "0x08 Balance"; | |||
| MIDI_CC_LIST << "0x09 (Undefined)"; | |||
| MIDI_CC_LIST << "0x0A Pan"; | |||
| MIDI_CC_LIST << "0x0B Expression"; | |||
| MIDI_CC_LIST << "0x0C FX Control 1"; | |||
| MIDI_CC_LIST << "0x0D FX Control 2"; | |||
| MIDI_CC_LIST << "0x0E (Undefined)"; | |||
| MIDI_CC_LIST << "0x0F (Undefined)"; | |||
| MIDI_CC_LIST << "0x10 General Purpose 1"; | |||
| MIDI_CC_LIST << "0x11 General Purpose 2"; | |||
| MIDI_CC_LIST << "0x12 General Purpose 3"; | |||
| MIDI_CC_LIST << "0x13 General Purpose 4"; | |||
| MIDI_CC_LIST << "0x14 (Undefined)"; | |||
| MIDI_CC_LIST << "0x15 (Undefined)"; | |||
| MIDI_CC_LIST << "0x16 (Undefined)"; | |||
| MIDI_CC_LIST << "0x17 (Undefined)"; | |||
| MIDI_CC_LIST << "0x18 (Undefined)"; | |||
| MIDI_CC_LIST << "0x19 (Undefined)"; | |||
| MIDI_CC_LIST << "0x1A (Undefined)"; | |||
| MIDI_CC_LIST << "0x1B (Undefined)"; | |||
| MIDI_CC_LIST << "0x1C (Undefined)"; | |||
| MIDI_CC_LIST << "0x1D (Undefined)"; | |||
| MIDI_CC_LIST << "0x1E (Undefined)"; | |||
| MIDI_CC_LIST << "0x1F (Undefined)"; | |||
| //MIDI_CC_LIST << "0x20 *Bank Select"; | |||
| //MIDI_CC_LIST << "0x21 *Modulation"; | |||
| //MIDI_CC_LIST << "0x22 *Breath"; | |||
| //MIDI_CC_LIST << "0x23 *(Undefined)"; | |||
| //MIDI_CC_LIST << "0x24 *Foot"; | |||
| //MIDI_CC_LIST << "0x25 *Portamento"; | |||
| //MIDI_CC_LIST << "0x26 *(Data Entry MSB)"; | |||
| //MIDI_CC_LIST << "0x27 *Volume"; | |||
| //MIDI_CC_LIST << "0x28 *Balance"; | |||
| //MIDI_CC_LIST << "0x29 *(Undefined)"; | |||
| //MIDI_CC_LIST << "0x2A *Pan"; | |||
| //MIDI_CC_LIST << "0x2B *Expression"; | |||
| //MIDI_CC_LIST << "0x2C *FX *Control 1"; | |||
| //MIDI_CC_LIST << "0x2D *FX *Control 2"; | |||
| //MIDI_CC_LIST << "0x2E *(Undefined)"; | |||
| //MIDI_CC_LIST << "0x2F *(Undefined)"; | |||
| //MIDI_CC_LIST << "0x30 *General Purpose 1"; | |||
| //MIDI_CC_LIST << "0x31 *General Purpose 2"; | |||
| //MIDI_CC_LIST << "0x32 *General Purpose 3"; | |||
| //MIDI_CC_LIST << "0x33 *General Purpose 4"; | |||
| //MIDI_CC_LIST << "0x34 *(Undefined)"; | |||
| //MIDI_CC_LIST << "0x35 *(Undefined)"; | |||
| //MIDI_CC_LIST << "0x36 *(Undefined)"; | |||
| //MIDI_CC_LIST << "0x37 *(Undefined)"; | |||
| //MIDI_CC_LIST << "0x38 *(Undefined)"; | |||
| //MIDI_CC_LIST << "0x39 *(Undefined)"; | |||
| //MIDI_CC_LIST << "0x3A *(Undefined)"; | |||
| //MIDI_CC_LIST << "0x3B *(Undefined)"; | |||
| //MIDI_CC_LIST << "0x3C *(Undefined)"; | |||
| //MIDI_CC_LIST << "0x3D *(Undefined)"; | |||
| //MIDI_CC_LIST << "0x3E *(Undefined)"; | |||
| //MIDI_CC_LIST << "0x3F *(Undefined)"; | |||
| //MIDI_CC_LIST << "0x40 Damper On/Off"; // <63 off, >64 on | |||
| //MIDI_CC_LIST << "0x41 Portamento On/Off"; // <63 off, >64 on | |||
| //MIDI_CC_LIST << "0x42 Sostenuto On/Off"; // <63 off, >64 on | |||
| //MIDI_CC_LIST << "0x43 Soft Pedal On/Off"; // <63 off, >64 on | |||
| //MIDI_CC_LIST << "0x44 Legato Footswitch"; // <63 Normal, >64 Legato | |||
| //MIDI_CC_LIST << "0x45 Hold 2"; // <63 off, >64 on | |||
| MIDI_CC_LIST << "0x46 Control 1 [Variation]"; | |||
| MIDI_CC_LIST << "0x47 Control 2 [Timbre]"; | |||
| MIDI_CC_LIST << "0x48 Control 3 [Release]"; | |||
| MIDI_CC_LIST << "0x49 Control 4 [Attack]"; | |||
| MIDI_CC_LIST << "0x4A Control 5 [Brightness]"; | |||
| MIDI_CC_LIST << "0x4B Control 6 [Decay]"; | |||
| MIDI_CC_LIST << "0x4C Control 7 [Vib Rate]"; | |||
| MIDI_CC_LIST << "0x4D Control 8 [Vib Depth]"; | |||
| MIDI_CC_LIST << "0x4E Control 9 [Vib Delay]"; | |||
| MIDI_CC_LIST << "0x4F Control 10 [Undefined]"; | |||
| MIDI_CC_LIST << "0x50 General Purpose 5"; | |||
| MIDI_CC_LIST << "0x51 General Purpose 6"; | |||
| MIDI_CC_LIST << "0x52 General Purpose 8"; | |||
| MIDI_CC_LIST << "0x53 General Purpose 9"; | |||
| MIDI_CC_LIST << "0x54 Portamento Control"; | |||
| MIDI_CC_LIST << "0x5B FX 1 Depth [Reverb]"; | |||
| MIDI_CC_LIST << "0x5C FX 2 Depth [Tremolo]"; | |||
| MIDI_CC_LIST << "0x5D FX 3 Depth [Chorus]"; | |||
| MIDI_CC_LIST << "0x5E FX 4 Depth [Detune]"; | |||
| MIDI_CC_LIST << "0x5F FX 5 Depth [Phaser]"; | |||
| } | |||
| // ------------------------------- | |||
| // XY Controller Scene | |||
| class XYGraphicsScene : public QGraphicsScene | |||
| { | |||
| Q_OBJECT | |||
| public: | |||
| XYGraphicsScene(QWidget* parent) : QGraphicsScene(parent), m_parent(parent) | |||
| { | |||
| cc_x = 1; | |||
| cc_y = 2; | |||
| m_mouseLock = false; | |||
| m_smooth = false; | |||
| m_smooth_x = 0; | |||
| m_smooth_y = 0; | |||
| setBackgroundBrush(Qt::black); | |||
| QPen cursorPen(QColor(255, 255, 255), 2); | |||
| QColor cursorBrush(255, 255, 255, 50); | |||
| m_cursor = addEllipse(QRectF(-10, -10, 20, 20), cursorPen, cursorBrush); | |||
| QPen linePen(QColor(200, 200, 200, 100), 1, Qt::DashLine); | |||
| m_lineH = addLine(-9999, 0, 9999, 0, linePen); | |||
| m_lineV = addLine(0, -9999, 0, 9999, linePen); | |||
| p_size = QRectF(-100, -100, 100, 100); | |||
| } | |||
| ~XYGraphicsScene() | |||
| { | |||
| } | |||
| void setControlX(int x) | |||
| { | |||
| cc_x = x; | |||
| } | |||
| void setControlY(int y) | |||
| { | |||
| cc_y = y; | |||
| } | |||
| void setChannels(QList<int> channels) | |||
| { | |||
| m_channels = channels; | |||
| } | |||
| void setPosX(qreal x, bool forward=true) | |||
| { | |||
| if (! m_mouseLock) | |||
| { | |||
| qreal pos_x = x * (p_size.x() + p_size.width()); | |||
| m_cursor->setPos(pos_x, m_cursor->y()); | |||
| m_lineV->setX(pos_x); | |||
| if (forward) | |||
| { | |||
| qreal value = pos_x / (p_size.x() + p_size.width()); | |||
| sendMIDI(&value, nullptr); | |||
| } | |||
| else | |||
| m_smooth_x = pos_x; | |||
| } | |||
| } | |||
| void setPosY(qreal y, bool forward=true) | |||
| { | |||
| if (! m_mouseLock) | |||
| { | |||
| qreal pos_y = y * (p_size.y() + p_size.height()); | |||
| m_cursor->setPos(m_cursor->x(), pos_y); | |||
| m_lineH->setY(pos_y); | |||
| if (forward) | |||
| { | |||
| qreal value = pos_y / (p_size.y() + p_size.height()); | |||
| sendMIDI(nullptr, &value); | |||
| } | |||
| else | |||
| m_smooth_y = pos_y; | |||
| } | |||
| } | |||
| void setSmooth(bool smooth) | |||
| { | |||
| m_smooth = smooth; | |||
| } | |||
| void setSmoothValues(int x, int y) | |||
| { | |||
| m_smooth_x = x * (p_size.x() + p_size.width()); | |||
| m_smooth_y = y * (p_size.y() + p_size.height()); | |||
| } | |||
| void handleCC(int param, int value) | |||
| { | |||
| bool sendUpdate = false; | |||
| qreal xp, yp; | |||
| xp = yp = 0.0; | |||
| if (param == cc_x) | |||
| { | |||
| sendUpdate = true; | |||
| xp = (float(value) / 63) - 1.0; | |||
| yp = m_cursor->y() / (p_size.y() + p_size.height()); | |||
| if (xp < -1.0) | |||
| xp = -1.0; | |||
| else if (xp > 1.0) | |||
| xp = 1.0; | |||
| setPosX(xp, false); | |||
| } | |||
| if (param == cc_y) | |||
| { | |||
| sendUpdate = true; | |||
| xp = m_cursor->x() / (p_size.x() + p_size.width()); | |||
| yp = (float(value) / 63) - 1.0; | |||
| if (yp < -1.0) | |||
| yp = -1.0; | |||
| else if (yp > 1.0) | |||
| yp = 1.0; | |||
| setPosY(yp, false); | |||
| } | |||
| if (sendUpdate) | |||
| emit cursorMoved(xp, yp); | |||
| } | |||
| void updateSize(QSize size) | |||
| { | |||
| p_size.setRect(-(size.width() / 2), -(size.height() / 2), size.width(), size.height()); | |||
| } | |||
| void updateSmooth() | |||
| { | |||
| if (! m_smooth) | |||
| return; | |||
| if (m_cursor->x() != m_smooth_x || m_cursor->y() != m_smooth_y) | |||
| { | |||
| if (abs(m_cursor->x() - m_smooth_x) <= 0.001) | |||
| { | |||
| m_smooth_x = m_cursor->x(); | |||
| return; | |||
| } | |||
| else if (abs(m_cursor->y() - m_smooth_y) <= 0.001) | |||
| { | |||
| m_smooth_y = m_cursor->y(); | |||
| return; | |||
| } | |||
| qreal new_x = (m_smooth_x + m_cursor->x() * 3) / 4; | |||
| qreal new_y = (m_smooth_y + m_cursor->y() * 3) / 4; | |||
| QPointF pos(new_x, new_y); | |||
| m_cursor->setPos(pos); | |||
| m_lineH->setY(pos.y()); | |||
| m_lineV->setX(pos.x()); | |||
| qreal xp = pos.x() / (p_size.x() + p_size.width()); | |||
| qreal yp = pos.y() / (p_size.y() + p_size.height()); | |||
| sendMIDI(&xp, &yp); | |||
| emit cursorMoved(xp, yp); | |||
| } | |||
| } | |||
| protected: | |||
| void handleMousePos(QPointF pos) | |||
| { | |||
| if (! p_size.contains(pos)) | |||
| { | |||
| if (pos.x() < p_size.x()) | |||
| pos.setX(p_size.x()); | |||
| else if (pos.x() > p_size.x() + p_size.width()) | |||
| pos.setX(p_size.x() + p_size.width()); | |||
| if (pos.y() < p_size.y()) | |||
| pos.setY(p_size.y()); | |||
| else if (pos.y() > p_size.y() + p_size.height()) | |||
| pos.setY(p_size.y() + p_size.height()); | |||
| } | |||
| m_smooth_x = pos.x(); | |||
| m_smooth_y = pos.y(); | |||
| if (! m_smooth) | |||
| { | |||
| m_cursor->setPos(pos); | |||
| m_lineH->setY(pos.y()); | |||
| m_lineV->setX(pos.x()); | |||
| qreal xp = pos.x() / (p_size.x() + p_size.width()); | |||
| qreal yp = pos.y() / (p_size.y() + p_size.height()); | |||
| sendMIDI(&xp, &yp); | |||
| emit cursorMoved(xp, yp); | |||
| } | |||
| } | |||
| void sendMIDI(qreal* xp=nullptr, qreal* yp=nullptr) | |||
| { | |||
| qreal rate = qreal(0xff) / 4; | |||
| if (xp != nullptr) | |||
| { | |||
| int value = *xp * rate + rate; | |||
| foreach (const int& channel, m_channels) | |||
| jack_midi_out_data.put_nowait(0xB0 + channel - 1, cc_x, value); | |||
| } | |||
| if (yp != nullptr) | |||
| { | |||
| int value = *yp * rate + rate; | |||
| foreach (const int& channel, m_channels) | |||
| jack_midi_out_data.put_nowait(0xB0 + channel - 1, cc_y, value); | |||
| } | |||
| } | |||
| void keyPressEvent(QKeyEvent* event) | |||
| { | |||
| event->accept(); | |||
| } | |||
| void wheelEvent(QGraphicsSceneWheelEvent* event) | |||
| { | |||
| event->accept(); | |||
| } | |||
| void mousePressEvent(QGraphicsSceneMouseEvent* event) | |||
| { | |||
| m_mouseLock = true; | |||
| handleMousePos(event->scenePos()); | |||
| parent()->setCursor(Qt::CrossCursor); | |||
| QGraphicsScene::mousePressEvent(event); | |||
| } | |||
| void mouseMoveEvent(QGraphicsSceneMouseEvent* event) | |||
| { | |||
| handleMousePos(event->scenePos()); | |||
| QGraphicsScene::mouseMoveEvent(event); | |||
| } | |||
| void mouseReleaseEvent(QGraphicsSceneMouseEvent* event) | |||
| { | |||
| m_mouseLock = false; | |||
| parent()->setCursor(Qt::ArrowCursor); | |||
| QGraphicsScene::mouseReleaseEvent(event); | |||
| } | |||
| QWidget* parent() const | |||
| { | |||
| return m_parent; | |||
| } | |||
| signals: | |||
| void cursorMoved(qreal, qreal); | |||
| private: | |||
| int cc_x; | |||
| int cc_y; | |||
| QList<int> m_channels; | |||
| bool m_mouseLock; | |||
| bool m_smooth; | |||
| int m_smooth_x; | |||
| int m_smooth_y; | |||
| QGraphicsEllipseItem* m_cursor; | |||
| QGraphicsLineItem* m_lineH; | |||
| QGraphicsLineItem* m_lineV; | |||
| QRectF p_size; | |||
| QWidget* const m_parent; | |||
| }; | |||
| // ------------------------------- | |||
| // XY Controller Window | |||
| namespace Ui { | |||
| class XYControllerW; | |||
| } | |||
| class XYControllerW : public QMainWindow | |||
| { | |||
| Q_OBJECT | |||
| public: | |||
| XYControllerW() : | |||
| QMainWindow(nullptr), | |||
| scene(this), | |||
| settings("Cadence", "XY-Controller"), | |||
| ui(new Ui::XYControllerW) | |||
| { | |||
| ui->setupUi(this); | |||
| // ------------------------------------------------------------- | |||
| // Internal stuff | |||
| cc_x = 1; | |||
| cc_y = 2; | |||
| // ------------------------------------------------------------- | |||
| // Set-up GUI stuff | |||
| ui->dial_x->setPixmap(2); | |||
| ui->dial_y->setPixmap(2); | |||
| ui->dial_x->setLabel("X"); | |||
| ui->dial_y->setLabel("Y"); | |||
| ui->keyboard->setOctaves(6); | |||
| ui->graphicsView->setScene(&scene); | |||
| ui->graphicsView->setRenderHints(QPainter::Antialiasing); | |||
| foreach (const QString& MIDI_CC, MIDI_CC_LIST) | |||
| { | |||
| ui->cb_control_x->addItem(MIDI_CC); | |||
| ui->cb_control_y->addItem(MIDI_CC); | |||
| } | |||
| // ------------------------------------------------------------- | |||
| // Load Settings | |||
| loadSettings(); | |||
| // ------------------------------------------------------------- | |||
| // Connect actions to functions | |||
| connect(ui->keyboard, SIGNAL(noteOn(int)), SLOT(noteOn(int))); | |||
| connect(ui->keyboard, SIGNAL(noteOff(int)), SLOT(noteOff(int))); | |||
| connect(ui->cb_smooth, SIGNAL(clicked(bool)), SLOT(setSmooth(bool))); | |||
| connect(ui->dial_x, SIGNAL(valueChanged(int)), SLOT(updateSceneX(int))); | |||
| connect(ui->dial_y, SIGNAL(valueChanged(int)), SLOT(updateSceneY(int))); | |||
| connect(ui->cb_control_x, SIGNAL(currentIndexChanged(QString)), SLOT(checkCC_X(QString))); | |||
| connect(ui->cb_control_y, SIGNAL(currentIndexChanged(QString)), SLOT(checkCC_Y(QString))); | |||
| connect(&scene, SIGNAL(cursorMoved(qreal, qreal)), SLOT(sceneCursorMoved(qreal, qreal))); | |||
| connect(ui->act_ch_01, SIGNAL(triggered(bool)), SLOT(checkChannel(bool))); | |||
| connect(ui->act_ch_02, SIGNAL(triggered(bool)), SLOT(checkChannel(bool))); | |||
| connect(ui->act_ch_03, SIGNAL(triggered(bool)), SLOT(checkChannel(bool))); | |||
| connect(ui->act_ch_04, SIGNAL(triggered(bool)), SLOT(checkChannel(bool))); | |||
| connect(ui->act_ch_05, SIGNAL(triggered(bool)), SLOT(checkChannel(bool))); | |||
| connect(ui->act_ch_06, SIGNAL(triggered(bool)), SLOT(checkChannel(bool))); | |||
| connect(ui->act_ch_07, SIGNAL(triggered(bool)), SLOT(checkChannel(bool))); | |||
| connect(ui->act_ch_08, SIGNAL(triggered(bool)), SLOT(checkChannel(bool))); | |||
| connect(ui->act_ch_09, SIGNAL(triggered(bool)), SLOT(checkChannel(bool))); | |||
| connect(ui->act_ch_10, SIGNAL(triggered(bool)), SLOT(checkChannel(bool))); | |||
| connect(ui->act_ch_11, SIGNAL(triggered(bool)), SLOT(checkChannel(bool))); | |||
| connect(ui->act_ch_12, SIGNAL(triggered(bool)), SLOT(checkChannel(bool))); | |||
| connect(ui->act_ch_13, SIGNAL(triggered(bool)), SLOT(checkChannel(bool))); | |||
| connect(ui->act_ch_14, SIGNAL(triggered(bool)), SLOT(checkChannel(bool))); | |||
| connect(ui->act_ch_15, SIGNAL(triggered(bool)), SLOT(checkChannel(bool))); | |||
| connect(ui->act_ch_16, SIGNAL(triggered(bool)), SLOT(checkChannel(bool))); | |||
| connect(ui->act_ch_all, SIGNAL(triggered()), SLOT(checkChannel_all())); | |||
| connect(ui->act_ch_none, SIGNAL(triggered()), SLOT(checkChannel_none())); | |||
| connect(ui->act_show_keyboard, SIGNAL(triggered(bool)), SLOT(showKeyboard(bool))); | |||
| connect(ui->act_about, SIGNAL(triggered()), SLOT(about())); | |||
| // ------------------------------------------------------------- | |||
| // Final stuff | |||
| m_midiInTimerId = startTimer(50); | |||
| QTimer::singleShot(0, this, SLOT(updateScreen())); | |||
| } | |||
| protected slots: | |||
| void noteOn(int note) | |||
| { | |||
| foreach (const int& channel, m_channels) | |||
| jack_midi_out_data.put_nowait(0x90 + channel - 1, note, 100); | |||
| } | |||
| void noteOff(int note) | |||
| { | |||
| foreach (const int& channel, m_channels) | |||
| jack_midi_out_data.put_nowait(0x80 + channel - 1, note, 0); | |||
| } | |||
| void updateSceneX(int x) | |||
| { | |||
| scene.setPosX(float(x) / 100, bool(sender())); | |||
| } | |||
| void updateSceneY(int y) | |||
| { | |||
| scene.setPosY(float(y) / 100, bool(sender())); | |||
| } | |||
| void checkCC_X(QString text) | |||
| { | |||
| if (! text.isEmpty()) | |||
| { | |||
| bool ok; | |||
| int tmp_cc_x = text.split(" ").at(0).toInt(&ok, 16); | |||
| if (ok) | |||
| { | |||
| cc_x = tmp_cc_x; | |||
| scene.setControlX(cc_x); | |||
| } | |||
| } | |||
| } | |||
| void checkCC_Y(QString text) | |||
| { | |||
| if (! text.isEmpty()) | |||
| { | |||
| bool ok; | |||
| int tmp_cc_y = text.split(" ").at(0).toInt(&ok, 16); | |||
| if (ok) | |||
| { | |||
| cc_y = tmp_cc_y; | |||
| scene.setControlY(cc_y); | |||
| } | |||
| } | |||
| } | |||
| void checkChannel(bool clicked) | |||
| { | |||
| if (! sender()) | |||
| return; | |||
| bool ok; | |||
| int channel = ((QAction*)sender())->text().toInt(&ok); | |||
| if (ok) | |||
| { | |||
| if (clicked && ! m_channels.contains(channel)) | |||
| m_channels.append(channel); | |||
| else if ((! clicked) && m_channels.contains(channel)) | |||
| m_channels.removeOne(channel); | |||
| scene.setChannels(m_channels); | |||
| } | |||
| } | |||
| void checkChannel_all() | |||
| { | |||
| ui->act_ch_01->setChecked(true); | |||
| ui->act_ch_02->setChecked(true); | |||
| ui->act_ch_03->setChecked(true); | |||
| ui->act_ch_04->setChecked(true); | |||
| ui->act_ch_05->setChecked(true); | |||
| ui->act_ch_06->setChecked(true); | |||
| ui->act_ch_07->setChecked(true); | |||
| ui->act_ch_08->setChecked(true); | |||
| ui->act_ch_09->setChecked(true); | |||
| ui->act_ch_10->setChecked(true); | |||
| ui->act_ch_11->setChecked(true); | |||
| ui->act_ch_12->setChecked(true); | |||
| ui->act_ch_13->setChecked(true); | |||
| ui->act_ch_14->setChecked(true); | |||
| ui->act_ch_15->setChecked(true); | |||
| ui->act_ch_16->setChecked(true); | |||
| #ifdef Q_COMPILER_INITIALIZER_LISTS | |||
| m_channels = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; | |||
| #else | |||
| m_channels.clear(); | |||
| for (int i=1; i <= 16; i++) | |||
| m_channels << i; | |||
| #endif | |||
| scene.setChannels(m_channels); | |||
| } | |||
| void checkChannel_none() | |||
| { | |||
| ui->act_ch_01->setChecked(false); | |||
| ui->act_ch_02->setChecked(false); | |||
| ui->act_ch_03->setChecked(false); | |||
| ui->act_ch_04->setChecked(false); | |||
| ui->act_ch_05->setChecked(false); | |||
| ui->act_ch_06->setChecked(false); | |||
| ui->act_ch_07->setChecked(false); | |||
| ui->act_ch_08->setChecked(false); | |||
| ui->act_ch_09->setChecked(false); | |||
| ui->act_ch_10->setChecked(false); | |||
| ui->act_ch_11->setChecked(false); | |||
| ui->act_ch_12->setChecked(false); | |||
| ui->act_ch_13->setChecked(false); | |||
| ui->act_ch_14->setChecked(false); | |||
| ui->act_ch_15->setChecked(false); | |||
| ui->act_ch_16->setChecked(false); | |||
| m_channels.clear(); | |||
| scene.setChannels(m_channels); | |||
| } | |||
| void setSmooth(bool yesno) | |||
| { | |||
| scene.setSmooth(yesno); | |||
| } | |||
| void sceneCursorMoved(qreal xp, qreal yp) | |||
| { | |||
| ui->dial_x->blockSignals(true); | |||
| ui->dial_y->blockSignals(true); | |||
| ui->dial_x->setValue(xp * 100); | |||
| ui->dial_y->setValue(yp * 100); | |||
| ui->dial_x->blockSignals(false); | |||
| ui->dial_y->blockSignals(false); | |||
| } | |||
| void showKeyboard(bool yesno) | |||
| { | |||
| ui->scrollArea->setVisible(yesno); | |||
| QTimer::singleShot(0, this, SLOT(updateScreen())); | |||
| } | |||
| void about() | |||
| { | |||
| QMessageBox::about(this, tr("About XY Controller"), tr("<h3>XY Controller</h3>" | |||
| "<br>Version %1" | |||
| "<br>XY Controller is a simple XY widget that sends and receives data from Jack MIDI.<br>" | |||
| "<br>Copyright (C) 2012 falkTX").arg(VERSION)); | |||
| } | |||
| void updateScreen() | |||
| { | |||
| scene.updateSize(ui->graphicsView->size()); | |||
| ui->graphicsView->centerOn(0, 0); | |||
| int dial_x = ui->dial_x->value(); | |||
| int dial_y = ui->dial_y->value(); | |||
| updateSceneX(dial_x); | |||
| updateSceneY(dial_y); | |||
| scene.setSmoothValues(float(dial_x) / 100, float(dial_y) / 100); | |||
| } | |||
| protected: | |||
| void saveSettings() | |||
| { | |||
| QVariantList varChannelList; | |||
| foreach (const int& channel, m_channels) | |||
| varChannelList << channel; | |||
| settings.setValue("Geometry", saveGeometry()); | |||
| settings.setValue("ShowKeyboard", ui->scrollArea->isVisible()); | |||
| settings.setValue("Smooth", ui->cb_smooth->isChecked()); | |||
| settings.setValue("DialX", ui->dial_x->value()); | |||
| settings.setValue("DialY", ui->dial_y->value()); | |||
| settings.setValue("ControlX", cc_x); | |||
| settings.setValue("ControlY", cc_y); | |||
| settings.setValue("Channels", varChannelList); | |||
| } | |||
| void loadSettings() | |||
| { | |||
| restoreGeometry(settings.value("Geometry").toByteArray()); | |||
| bool showKeyboard = settings.value("ShowKeyboard", false).toBool(); | |||
| ui->act_show_keyboard->setChecked(showKeyboard); | |||
| ui->scrollArea->setVisible(showKeyboard); | |||
| bool smooth = settings.value("Smooth", false).toBool(); | |||
| ui->cb_smooth->setChecked(smooth); | |||
| scene.setSmooth(smooth); | |||
| ui->dial_x->setValue(settings.value("DialX", 50).toInt()); | |||
| ui->dial_y->setValue(settings.value("DialY", 50).toInt()); | |||
| cc_x = settings.value("ControlX", 1).toInt(); | |||
| cc_y = settings.value("ControlY", 2).toInt(); | |||
| scene.setControlX(cc_x); | |||
| scene.setControlY(cc_y); | |||
| m_channels.clear(); | |||
| if (settings.contains("Channels")) | |||
| { | |||
| QVariantList channels = settings.value("Channels").toList(); | |||
| foreach (const QVariant& var, channels) | |||
| { | |||
| bool ok; | |||
| int channel = var.toInt(&ok); | |||
| if (ok) | |||
| m_channels.append(channel); | |||
| } | |||
| } | |||
| else | |||
| #ifdef Q_COMPILER_INITIALIZER_LISTS | |||
| m_channels = { 1 }; | |||
| #else | |||
| m_channels << 1; | |||
| #endif | |||
| scene.setChannels(m_channels); | |||
| for (int i=0; i < MIDI_CC_LIST.size(); i++) | |||
| { | |||
| bool ok; | |||
| int cc = MIDI_CC_LIST[i].split(" ").at(0).toInt(&ok, 16); | |||
| if (ok) | |||
| { | |||
| if (cc_x == cc) | |||
| ui->cb_control_x->setCurrentIndex(i); | |||
| if (cc_y == cc) | |||
| ui->cb_control_y->setCurrentIndex(i); | |||
| } | |||
| } | |||
| if (m_channels.contains(1)) | |||
| ui->act_ch_01->setChecked(true); | |||
| if (m_channels.contains(2)) | |||
| ui->act_ch_02->setChecked(true); | |||
| if (m_channels.contains(3)) | |||
| ui->act_ch_03->setChecked(true); | |||
| if (m_channels.contains(4)) | |||
| ui->act_ch_04->setChecked(true); | |||
| if (m_channels.contains(5)) | |||
| ui->act_ch_05->setChecked(true); | |||
| if (m_channels.contains(6)) | |||
| ui->act_ch_06->setChecked(true); | |||
| if (m_channels.contains(7)) | |||
| ui->act_ch_07->setChecked(true); | |||
| if (m_channels.contains(8)) | |||
| ui->act_ch_08->setChecked(true); | |||
| if (m_channels.contains(9)) | |||
| ui->act_ch_09->setChecked(true); | |||
| if (m_channels.contains(10)) | |||
| ui->act_ch_10->setChecked(true); | |||
| if (m_channels.contains(11)) | |||
| ui->act_ch_11->setChecked(true); | |||
| if (m_channels.contains(12)) | |||
| ui->act_ch_12->setChecked(true); | |||
| if (m_channels.contains(13)) | |||
| ui->act_ch_13->setChecked(true); | |||
| if (m_channels.contains(14)) | |||
| ui->act_ch_14->setChecked(true); | |||
| if (m_channels.contains(15)) | |||
| ui->act_ch_15->setChecked(true); | |||
| if (m_channels.contains(16)) | |||
| ui->act_ch_16->setChecked(true); | |||
| } | |||
| void timerEvent(QTimerEvent* event) | |||
| { | |||
| if (event->timerId() == m_midiInTimerId) | |||
| { | |||
| //if not jack_midi_in_data.empty(): | |||
| //while True: | |||
| //try: | |||
| // data1, data2, data3 = jack_midi_in_data.get_nowait() | |||
| //except QuequeEmpty: | |||
| // break | |||
| //channel = (data1 & 0x0F) + 1 | |||
| //mode = data1 & 0xF0 | |||
| //if channel in self.m_channels: | |||
| // if mode == 0x80: | |||
| // self.keyboard.sendNoteOff(data2, False) | |||
| // elif mode == 0x90: | |||
| // self.keyboard.sendNoteOn(data2, False) | |||
| // elif mode == 0xB0: | |||
| // self.scene.handleCC(data2, data3) | |||
| //jack_midi_in_data.task_done() | |||
| scene.updateSmooth(); | |||
| } | |||
| QMainWindow::timerEvent(event); | |||
| } | |||
| void resizeEvent(QResizeEvent* event) | |||
| { | |||
| updateScreen(); | |||
| QMainWindow::resizeEvent(event); | |||
| } | |||
| void closeEvent(QCloseEvent* event) | |||
| { | |||
| saveSettings(); | |||
| QMainWindow::closeEvent(event); | |||
| } | |||
| private: | |||
| int cc_x; | |||
| int cc_y; | |||
| QList<int> m_channels; | |||
| int m_midiInTimerId; | |||
| XYGraphicsScene scene; | |||
| QSettings settings; | |||
| Ui::XYControllerW* ui; | |||
| }; | |||
| #include "xycontroller.moc" | |||
| // ------------------------------- | |||
| // ------------------------------- | |||
| int main(int argc, char* argv[]) | |||
| { | |||
| MIDI_CC_LIST__init(); | |||
| QApplication app(argc, argv); | |||
| app.setApplicationName("XY-Controller"); | |||
| app.setApplicationVersion(VERSION); | |||
| app.setOrganizationName("Cadence"); | |||
| //app.setWindowIcon(QIcon(":/48x48/xy-controller.png")); | |||
| #if 0 | |||
| // JACK initialization | |||
| jack_status_t jStatus; | |||
| jack_options_t jOptions = static_cast<JackOptions>(JackNoStartServer/*|JackSessionID*/); | |||
| jack_client = jack_client_open("XY-Controller", jOptions, &jStatus); | |||
| if (! jack_client) | |||
| { | |||
| std::string errorString(jack_status_get_error_string(jStatus)); | |||
| QMessageBox::critical(nullptr, app.translate("XY-Controller", "Error"), app.translate("XY-Controller", | |||
| "Could not connect to JACK, possible reasons:\n" | |||
| "%1").arg(QString::fromStdString(errorString))); | |||
| return 1; | |||
| } | |||
| jack_midi_in_port = jack_port_register(jack_client, "midi_in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); | |||
| jack_midi_out_port = jack_port_register(jack_client, "midi_out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); | |||
| //jack_set_process_callback(jClient, process_callback, nullptr); | |||
| //jack_set_port_connect_callback(jClient, port_callback, nullptr); | |||
| //jack_set_session_callback(jClient, session_callback, argv[0]); | |||
| jack_activate(jack_client); | |||
| #endif | |||
| // Show GUI | |||
| XYControllerW gui; | |||
| gui.show(); | |||
| // App-Loop | |||
| int ret = app.exec(); | |||
| #if 0 | |||
| jack_deactivate(jack_client); | |||
| jack_client_close(jack_client); | |||
| #endif | |||
| return ret; | |||
| } | |||