Browse Source

c++ xycontroller now works, fixed some keyboard things too

tags/v0.9.0
falkTX 12 years ago
parent
commit
5ccf0749ad
7 changed files with 613 additions and 394 deletions
  1. +1
    -1
      c++/jackmeter/Makefile
  2. +71
    -63
      c++/widgets/pixmapkeyboard.cpp
  3. +2
    -2
      c++/widgets/pixmapkeyboard.h
  4. +1
    -1
      c++/xycontroller/Makefile
  5. +421
    -232
      c++/xycontroller/xycontroller.cpp
  6. +42
    -40
      src/pixmapkeyboard.py
  7. +75
    -55
      src/xycontroller.py

+ 1
- 1
c++/jackmeter/Makefile View File

@@ -7,7 +7,7 @@
CXX ?= g++ CXX ?= g++
STRIP ?= strip STRIP ?= strip


BASE_FLAGS = -O2 -ffast-math -fomit-frame-pointer -fPIC -mtune=generic -msse -mfpmath=sse -Wall
BASE_FLAGS = -O2 -ffast-math -fomit-frame-pointer -mtune=generic -msse -mfpmath=sse -Wall


BUILD_FLAGS = $(BASE_FLAGS) -std=c++0x $(CXXFLAGS) BUILD_FLAGS = $(BASE_FLAGS) -std=c++0x $(CXXFLAGS)
BUILD_FLAGS += $(shell pkg-config --cflags QtCore QtGui jack) BUILD_FLAGS += $(shell pkg-config --cflags QtCore QtGui jack)


+ 71
- 63
c++/widgets/pixmapkeyboard.cpp View File

@@ -23,16 +23,18 @@
#include <QtGui/QMouseEvent> #include <QtGui/QMouseEvent>
#include <QtGui/QPainter> #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;
QMap<int, QRectF> midi_key2rect_map_horizontal;
QMap<int, QRectF> midi_key2rect_map_vertical;
QMap<int, int> midi_keyboard2key_map;
QVector<int> blackNotes;


void midi_map_init()
static bool pixmapkeyboard_initiated = false;
void pixmapkeyboard_init()
{ {
static bool init = false;
if (init) return;
init = true;
if (pixmapkeyboard_initiated)
return;

pixmapkeyboard_initiated = true;


// midi_key2rect_map_horizontal ------ // midi_key2rect_map_horizontal ------
midi_key2rect_map_horizontal[0] = QRectF(0, 0, 18, 64); // C midi_key2rect_map_horizontal[0] = QRectF(0, 0, 18, 64); // C
@@ -97,11 +99,11 @@ void midi_map_init()
blackNotes << 10; blackNotes << 10;
} }


PixmapKeyboard::PixmapKeyboard(QWidget* parent):
QWidget(parent),
m_font("Monospace", 8, QFont::Normal)
PixmapKeyboard::PixmapKeyboard(QWidget* parent)
: QWidget(parent),
m_font("Monospace", 8, QFont::Normal)
{ {
midi_map_init();
pixmapkeyboard_init();


m_octaves = 6; m_octaves = 6;
m_lastMouseNote = -1; m_lastMouseNote = -1;
@@ -113,7 +115,7 @@ PixmapKeyboard::PixmapKeyboard(QWidget* parent):


void PixmapKeyboard::sendNoteOn(int note, bool sendSignal) void PixmapKeyboard::sendNoteOn(int note, bool sendSignal)
{ {
if (note >= 0 && note <= 127 && ! m_enabledKeys.contains(note))
if (0 <= note && note <= 127 && ! m_enabledKeys.contains(note))
{ {
m_enabledKeys.append(note); m_enabledKeys.append(note);
if (sendSignal) if (sendSignal)
@@ -186,6 +188,8 @@ void PixmapKeyboard::setMode(Orientation mode, Color color)


void PixmapKeyboard::setOctaves(int octaves) void PixmapKeyboard::setOctaves(int octaves)
{ {
Q_ASSERT(octaves >= 1 && octaves <= 6);

if (octaves < 1) if (octaves < 1)
octaves = 1; octaves = 1;
else if (octaves > 6) else if (octaves > 6)
@@ -206,50 +210,6 @@ void PixmapKeyboard::setOctaves(int octaves)
update(); 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) void PixmapKeyboard::handleMousePos(const QPoint& pos)
{ {
int note, octave; int note, octave;
@@ -259,15 +219,17 @@ void PixmapKeyboard::handleMousePos(const QPoint& pos)
{ {
if (pos.x() < 0 or pos.x() > m_octaves * 144) if (pos.x() < 0 or pos.x() > m_octaves * 144)
return; return;
octave = pos.x() / p_width;
n_pos = QPointF(pos.x() % p_width, pos.y());
int posX = pos.x() - 1;
octave = posX / p_width;
n_pos = QPointF(posX % p_width, pos.y());
} }
else if (m_pixmap_mode == VERTICAL) else if (m_pixmap_mode == VERTICAL)
{ {
if (pos.y() < 0 or pos.y() > m_octaves * 144) if (pos.y() < 0 or pos.y() > m_octaves * 144)
return; return;
octave = m_octaves - pos.y() / p_height;
n_pos = QPointF(pos.x(), pos.y() % p_height);
int posY = pos.y() - 1;
octave = m_octaves - posY / p_height;
n_pos = QPointF(pos.x(), posY % p_height);
} }
else else
return; return;
@@ -316,6 +278,52 @@ void PixmapKeyboard::handleMousePos(const QPoint& pos)
m_lastMouseNote = note; m_lastMouseNote = note;
} }


void PixmapKeyboard::keyPressEvent(QKeyEvent* event)
{
if (! event->isAutoRepeat())
{
int qKey = event->key();
if (midi_keyboard2key_map.keys().contains(qKey))
sendNoteOn(midi_keyboard2key_map[qKey]);
}
QWidget::keyPressEvent(event);
}

void PixmapKeyboard::keyReleaseEvent(QKeyEvent* event)
{
if (! event->isAutoRepeat())
{
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::paintEvent(QPaintEvent*) void PixmapKeyboard::paintEvent(QPaintEvent*)
{ {
QPainter painter(this); QPainter painter(this);
@@ -351,7 +359,7 @@ void PixmapKeyboard::paintEvent(QPaintEvent*)
if (_isNoteBlack(note)) if (_isNoteBlack(note))
continue; continue;


if (note < 35)
if (note < 36)
// cannot paint this note // cannot paint this note
continue; continue;
else if (note < 48) else if (note < 48)
@@ -432,7 +440,7 @@ void PixmapKeyboard::paintEvent(QPaintEvent*)
if (! _isNoteBlack(note)) if (! _isNoteBlack(note))
continue; continue;


if (note < 35)
if (note < 36)
// cannot paint this note // cannot paint this note
continue; continue;
else if (note < 48) else if (note < 48)


+ 2
- 2
c++/widgets/pixmapkeyboard.h View File

@@ -51,12 +51,12 @@ signals:
void notesOff(); void notesOff();


protected: protected:
void handleMousePos(const QPoint&);
void keyPressEvent(QKeyEvent*); void keyPressEvent(QKeyEvent*);
void keyReleaseEvent(QKeyEvent*); void keyReleaseEvent(QKeyEvent*);
void mousePressEvent(QMouseEvent*); void mousePressEvent(QMouseEvent*);
void mouseMoveEvent(QMouseEvent*); void mouseMoveEvent(QMouseEvent*);
void mouseReleaseEvent(QMouseEvent*); void mouseReleaseEvent(QMouseEvent*);
void handleMousePos(const QPoint&);
void paintEvent(QPaintEvent*); void paintEvent(QPaintEvent*);


private Q_SLOTS: private Q_SLOTS:
@@ -77,7 +77,7 @@ private:
QList<int> m_enabledKeys; QList<int> m_enabledKeys;
QMap<int, QRectF> *m_midi_map; QMap<int, QRectF> *m_midi_map;


bool _isNoteBlack(int note);
bool _isNoteBlack(int note);
QRectF _getRectFromMidiNote(int note); QRectF _getRectFromMidiNote(int note);
}; };




+ 1
- 1
c++/xycontroller/Makefile View File

@@ -11,7 +11,7 @@ UIC ?= uic
STRIP ?= strip STRIP ?= strip
WINDRES ?= windres WINDRES ?= windres


BASE_FLAGS = -O2 -ffast-math -fomit-frame-pointer -fPIC -mtune=generic -msse -mfpmath=sse -Wall -I../widgets
BASE_FLAGS = -O2 -ffast-math -fomit-frame-pointer -mtune=generic -msse -mfpmath=sse -Wall -I../widgets


BUILD_FLAGS = $(BASE_FLAGS) -std=c++0x $(CXXFLAGS) BUILD_FLAGS = $(BASE_FLAGS) -std=c++0x $(CXXFLAGS)
BUILD_FLAGS += $(shell pkg-config --cflags QtCore QtGui jack) BUILD_FLAGS += $(shell pkg-config --cflags QtCore QtGui jack)


+ 421
- 232
c++/xycontroller/xycontroller.cpp View File

@@ -18,15 +18,15 @@
#include <QtCore/Qt> #include <QtCore/Qt>


#ifndef Q_COMPILER_LAMBDA #ifndef Q_COMPILER_LAMBDA
# define nullptr (0)
# define nullptr (0)
#endif #endif


#define VERSION "0.5.0" #define VERSION "0.5.0"


//#include "../jack_utils.h"
#include "../jack_utils.h"
#include "ui_xycontroller.h" #include "ui_xycontroller.h"


//#include <QtCore/QMutex>
#include <QtCore/QMutex>
#include <QtCore/QSettings> #include <QtCore/QSettings>
#include <QtCore/QTimer> #include <QtCore/QTimer>
#include <QtGui/QApplication> #include <QtGui/QApplication>
@@ -39,39 +39,149 @@


// ------------------------------- // -------------------------------


class Queue {
float abs_f(const float value)
{
return (value < 1.0f) ? -value : value;
}

class Queue
{
public: public:
Queue(int size_) :
size(size_)
Queue()
{ {
index = 0;
empty = true;
full = false;
} }


~Queue()
void copyDataFrom(Queue* queue)
{ {
mutex.lock();
queue->mutex.lock();

// copy data from queue
memcpy(data, queue->data, sizeof(datatype)*MAX_SIZE);
empty = queue->empty;
full = queue->full;

// reset queque
memset(queue->data, 0, sizeof(datatype)*MAX_SIZE);
queue->empty = true;
queue->full = false;

// reset indexes
index = queue->index = 0;

queue->mutex.unlock();
mutex.unlock();
} }


void put_nowait(int, int, int)
bool isEmpty()
{ {
//const QMutexLocker m(&mutex);
return empty;
}

bool isFull()
{
return full;
}

void lock()
{
mutex.lock();
}

void unlock()
{
mutex.unlock();
}

void put(unsigned char d1, unsigned char d2, unsigned char d3, bool lock = true)
{
Q_ASSERT(d1 != 0);

if (full || d1 == 0)
return;

if (lock)
mutex.lock();

for (unsigned short i=0; i < MAX_SIZE; i++)
{
if (data[i].d1 == 0)
{
data[i].d1 = d1;
data[i].d2 = d2;
data[i].d3 = d3;
empty = false;
full = (i == MAX_SIZE-1);
break;
}
}

if (lock)
mutex.unlock();
}

bool get(unsigned char* d1, unsigned char* d2, unsigned char* d3, bool lock = true)
{
Q_ASSERT(d1 && d2 && d3);

if (empty || ! (d1 && d2 && d3))
return false;

if (lock)
mutex.lock();

full = false;

if (data[index].d1 == 0)
{
index = 0;
empty = true;

if (lock)
mutex.lock();

return false;
}

*d1 = data[index].d1;
*d2 = data[index].d2;
*d3 = data[index].d3;

data[index].d1 = data[index].d2 = data[index].d3 = 0;
index++;
empty = false;

if (lock)
mutex.lock();

return true;
} }


private: private:
const int size;
//QMutex mutex;
struct datatype {
unsigned char d1, d2, d3;

datatype()
: d1(0), d2(0), d3(0) {}
};

static const unsigned short MAX_SIZE = 128;
datatype data[MAX_SIZE];
unsigned short index;
bool empty, full;

QMutex mutex;
}; };


float abs_f(const float value)
{
return (value < 1.0f) ? -value : value;
}
jack_client_t* jClient = nullptr;
jack_port_t* jMidiInPort = nullptr;
jack_port_t* jMidiOutPort = nullptr;


#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);
static Queue qMidiInData;
static Queue qMidiOutData;


QVector<QString> MIDI_CC_LIST; QVector<QString> MIDI_CC_LIST;
void MIDI_CC_LIST__init() void MIDI_CC_LIST__init()
@@ -176,19 +286,21 @@ class XYGraphicsScene : public QGraphicsScene
Q_OBJECT Q_OBJECT


public: public:
XYGraphicsScene(QWidget* parent) : QGraphicsScene(parent), m_parent(parent)
XYGraphicsScene(QWidget* parent)
: QGraphicsScene(parent),
m_parent(parent)
{ {
cc_x = 1; cc_x = 1;
cc_y = 2; cc_y = 2;


m_mouseLock = false; m_mouseLock = false;
m_smooth = false;
m_smooth_x = 0;
m_smooth_y = 0;
m_smooth = false;
m_smooth_x = 0.0f;
m_smooth_y = 0.0f;


setBackgroundBrush(Qt::black); setBackgroundBrush(Qt::black);


QPen cursorPen(QColor(255, 255, 255), 2);
QPen cursorPen(QColor(255, 255, 255), 2);
QColor cursorBrush(255, 255, 255, 50); QColor cursorBrush(255, 255, 255, 50);
m_cursor = addEllipse(QRectF(-10, -10, 20, 20), cursorPen, cursorBrush); m_cursor = addEllipse(QRectF(-10, -10, 20, 20), cursorPen, cursorBrush);


@@ -199,10 +311,6 @@ public:
p_size = QRectF(-100, -100, 100, 100); p_size = QRectF(-100, -100, 100, 100);
} }


~XYGraphicsScene()
{
}

void setControlX(int x) void setControlX(int x)
{ {
cc_x = x; cc_x = x;
@@ -218,40 +326,40 @@ public:
m_channels = channels; m_channels = channels;
} }


void setPosX(qreal x, bool forward=true)
void setPosX(float 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 (m_mouseLock)
return;


if (forward)
{
qreal value = pos_x / (p_size.x() + p_size.width());
sendMIDI(&value, nullptr);
}
else
m_smooth_x = pos_x;
float posX = x * (p_size.x() + p_size.width());
m_cursor->setPos(posX, m_cursor->y());
m_lineV->setX(posX);

if (forward)
{
float value = posX / (p_size.x() + p_size.width());
sendMIDI(&value, nullptr);
} }
else
m_smooth_x = posX;
} }


void setPosY(qreal y, bool forward=true)
void setPosY(float 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 (m_mouseLock)
return;


if (forward)
{
qreal value = pos_y / (p_size.y() + p_size.height());
sendMIDI(nullptr, &value);
}
else
m_smooth_y = pos_y;
float posY = y * (p_size.y() + p_size.height());
m_cursor->setPos(m_cursor->x(), posY);
m_lineH->setY(posY);

if (forward)
{
float value = posY / (p_size.y() + p_size.height());
sendMIDI(nullptr, &value);
} }
else
m_smooth_y = posY;
} }


void setSmooth(bool smooth) void setSmooth(bool smooth)
@@ -259,7 +367,7 @@ public:
m_smooth = smooth; m_smooth = smooth;
} }


void setSmoothValues(int x, int y)
void setSmoothValues(float x, float y)
{ {
m_smooth_x = x * (p_size.x() + p_size.width()); m_smooth_x = x * (p_size.x() + p_size.width());
m_smooth_y = y * (p_size.y() + p_size.height()); m_smooth_y = y * (p_size.y() + p_size.height());
@@ -268,20 +376,15 @@ public:
void handleCC(int param, int value) void handleCC(int param, int value)
{ {
bool sendUpdate = false; bool sendUpdate = false;
qreal xp, yp;
xp = yp = 0.0;
float xp, yp;
xp = yp = 0.0f;


if (param == cc_x) if (param == cc_x)
{ {
sendUpdate = true; sendUpdate = true;
xp = (float(value) / 63) - 1.0;
xp = float(value)/63 - 1.0f;
yp = m_cursor->y() / (p_size.y() + p_size.height()); 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); setPosX(xp, false);
} }


@@ -289,23 +392,28 @@ public:
{ {
sendUpdate = true; sendUpdate = true;
xp = m_cursor->x() / (p_size.x() + p_size.width()); 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;
yp = float(value)/63 - 1.0f;


setPosY(yp, false); setPosY(yp, false);
} }


if (xp < -1.0f)
xp = -1.0f;
else if (xp > 1.0f)
xp = 1.0f;

if (yp < -1.0f)
yp = -1.0f;
else if (yp > 1.0f)
yp = 1.0f;

if (sendUpdate) if (sendUpdate)
emit cursorMoved(xp, yp); emit cursorMoved(xp, yp);
} }


void updateSize(QSize size) void updateSize(QSize size)
{ {
p_size.setRect(-(size.width() / 2), -(size.height() / 2), size.width(), size.height());
p_size.setRect(-(float(size.width())/2), -(float(size.height())/2), size.width(), size.height());
} }


void updateSmooth() void updateSmooth()
@@ -313,33 +421,33 @@ public:
if (! m_smooth) if (! m_smooth)
return; return;


if (m_cursor->x() != m_smooth_x || m_cursor->y() != m_smooth_y)
if (m_cursor->x() == m_smooth_x && m_cursor->y() == m_smooth_y)
return;

if (abs_f(m_cursor->x() - m_smooth_x) <= 0.0005f)
{ {
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;
}
m_smooth_x = m_cursor->x();
return;
}
if (abs_f(m_cursor->y() - m_smooth_y) <= 0.0005f)
{
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);
float newX = float(m_smooth_x + m_cursor->x()*7) / 8;
float newY = float(m_smooth_y + m_cursor->y()*7) / 8;
QPointF pos(newX, newY);


m_cursor->setPos(pos);
m_lineH->setY(pos.y());
m_lineV->setX(pos.x());
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());
float xp = pos.x() / (p_size.x() + p_size.width());
float yp = pos.y() / (p_size.y() + p_size.height());


sendMIDI(&xp, &yp);
emit cursorMoved(xp, yp);
}
sendMIDI(&xp, &yp);
emit cursorMoved(xp, yp);
} }


protected: protected:
@@ -367,31 +475,30 @@ protected:
m_lineH->setY(pos.y()); m_lineH->setY(pos.y());
m_lineV->setX(pos.x()); 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());
float xp = pos.x() / (p_size.x() + p_size.width());
float yp = pos.y() / (p_size.y() + p_size.height());


sendMIDI(&xp, &yp); sendMIDI(&xp, &yp);

emit cursorMoved(xp, yp); emit cursorMoved(xp, yp);
} }
} }


void sendMIDI(qreal* xp=nullptr, qreal* yp=nullptr)
void sendMIDI(float* xp=nullptr, float* yp=nullptr)
{ {
qreal rate = qreal(0xff) / 4;
float rate = float(0xff) / 4;


if (xp != nullptr) if (xp != nullptr)
{ {
int value = *xp * rate + rate; int value = *xp * rate + rate;
foreach (const int& channel, m_channels) foreach (const int& channel, m_channels)
jack_midi_out_data.put_nowait(0xB0 + channel - 1, cc_x, value);
qMidiOutData.put(0xB0 + channel - 1, cc_x, value);
} }


if (yp != nullptr) if (yp != nullptr)
{ {
int value = *yp * rate + rate; int value = *yp * rate + rate;
foreach (const int& channel, m_channels) foreach (const int& channel, m_channels)
jack_midi_out_data.put_nowait(0xB0 + channel - 1, cc_y, value);
qMidiOutData.put(0xB0 + channel - 1, cc_y, value);
} }
} }


@@ -426,23 +533,18 @@ protected:
QGraphicsScene::mouseReleaseEvent(event); QGraphicsScene::mouseReleaseEvent(event);
} }


QWidget* parent() const
{
return m_parent;
}

signals: signals:
void cursorMoved(qreal, qreal);
void cursorMoved(float, float);


private: private:
int cc_x; int cc_x;
int cc_y; int cc_y;
QList<int> m_channels; QList<int> m_channels;


bool m_mouseLock;
bool m_smooth;
int m_smooth_x;
int m_smooth_y;
bool m_mouseLock;
bool m_smooth;
float m_smooth_x;
float m_smooth_y;


QGraphicsEllipseItem* m_cursor; QGraphicsEllipseItem* m_cursor;
QGraphicsLineItem* m_lineH; QGraphicsLineItem* m_lineH;
@@ -450,7 +552,12 @@ private:


QRectF p_size; QRectF p_size;


// fake parent
QWidget* const m_parent; QWidget* const m_parent;
QWidget* parent() const
{
return m_parent;
}
}; };


// ------------------------------- // -------------------------------
@@ -465,11 +572,11 @@ class XYControllerW : public QMainWindow
Q_OBJECT Q_OBJECT


public: public:
XYControllerW() :
QMainWindow(nullptr),
scene(this),
settings("Cadence", "XY-Controller"),
ui(new Ui::XYControllerW)
XYControllerW()
: QMainWindow(nullptr),
settings("Cadence", "XY-Controller"),
scene(this),
ui(new Ui::XYControllerW)
{ {
ui->setupUi(this); ui->setupUi(this);


@@ -505,102 +612,114 @@ public:
// ------------------------------------------------------------- // -------------------------------------------------------------
// Connect actions to functions // 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()));
connect(ui->keyboard, SIGNAL(noteOn(int)), SLOT(slot_noteOn(int)));
connect(ui->keyboard, SIGNAL(noteOff(int)), SLOT(slot_noteOff(int)));
connect(ui->cb_smooth, SIGNAL(clicked(bool)), SLOT(slot_setSmooth(bool)));
connect(ui->dial_x, SIGNAL(valueChanged(int)), SLOT(slot_updateSceneX(int)));
connect(ui->dial_y, SIGNAL(valueChanged(int)), SLOT(slot_updateSceneY(int)));
connect(ui->cb_control_x, SIGNAL(currentIndexChanged(QString)), SLOT(slot_checkCC_X(QString)));
connect(ui->cb_control_y, SIGNAL(currentIndexChanged(QString)), SLOT(slot_checkCC_Y(QString)));
connect(&scene, SIGNAL(cursorMoved(float,float)), SLOT(slot_sceneCursorMoved(float,float)));
connect(ui->act_ch_01, SIGNAL(triggered(bool)), SLOT(slot_checkChannel(bool)));
connect(ui->act_ch_02, SIGNAL(triggered(bool)), SLOT(slot_checkChannel(bool)));
connect(ui->act_ch_03, SIGNAL(triggered(bool)), SLOT(slot_checkChannel(bool)));
connect(ui->act_ch_04, SIGNAL(triggered(bool)), SLOT(slot_checkChannel(bool)));
connect(ui->act_ch_05, SIGNAL(triggered(bool)), SLOT(slot_checkChannel(bool)));
connect(ui->act_ch_06, SIGNAL(triggered(bool)), SLOT(slot_checkChannel(bool)));
connect(ui->act_ch_07, SIGNAL(triggered(bool)), SLOT(slot_checkChannel(bool)));
connect(ui->act_ch_08, SIGNAL(triggered(bool)), SLOT(slot_checkChannel(bool)));
connect(ui->act_ch_09, SIGNAL(triggered(bool)), SLOT(slot_checkChannel(bool)));
connect(ui->act_ch_10, SIGNAL(triggered(bool)), SLOT(slot_checkChannel(bool)));
connect(ui->act_ch_11, SIGNAL(triggered(bool)), SLOT(slot_checkChannel(bool)));
connect(ui->act_ch_12, SIGNAL(triggered(bool)), SLOT(slot_checkChannel(bool)));
connect(ui->act_ch_13, SIGNAL(triggered(bool)), SLOT(slot_checkChannel(bool)));
connect(ui->act_ch_14, SIGNAL(triggered(bool)), SLOT(slot_checkChannel(bool)));
connect(ui->act_ch_15, SIGNAL(triggered(bool)), SLOT(slot_checkChannel(bool)));
connect(ui->act_ch_16, SIGNAL(triggered(bool)), SLOT(slot_checkChannel(bool)));
connect(ui->act_ch_all, SIGNAL(triggered()), SLOT(slot_checkChannel_all()));
connect(ui->act_ch_none, SIGNAL(triggered()), SLOT(slot_checkChannel_none()));
connect(ui->act_show_keyboard, SIGNAL(triggered(bool)), SLOT(slot_showKeyboard(bool)));
connect(ui->act_about, SIGNAL(triggered()), SLOT(slot_about()));


// ------------------------------------------------------------- // -------------------------------------------------------------
// Final stuff // Final stuff


m_midiInTimerId = startTimer(50);
QTimer::singleShot(0, this, SLOT(updateScreen()));
m_midiInTimerId = startTimer(30);
QTimer::singleShot(0, this, SLOT(slot_updateScreen()));
}

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();
slot_updateSceneX(dial_x);
slot_updateSceneY(dial_y);
scene.setSmoothValues(float(dial_x) / 100, float(dial_y) / 100);
} }


protected slots: protected slots:
void noteOn(int note)
void slot_noteOn(int note)
{ {
foreach (const int& channel, m_channels) foreach (const int& channel, m_channels)
jack_midi_out_data.put_nowait(0x90 + channel - 1, note, 100);
qMidiOutData.put(0x90 + channel - 1, note, 100);
} }


void noteOff(int note)
void slot_noteOff(int note)
{ {
foreach (const int& channel, m_channels) foreach (const int& channel, m_channels)
jack_midi_out_data.put_nowait(0x80 + channel - 1, note, 0);
qMidiOutData.put(0x80 + channel - 1, note, 0);
} }


void updateSceneX(int x)
void slot_updateSceneX(int x)
{ {
scene.setPosX(float(x) / 100, bool(sender())); scene.setPosX(float(x) / 100, bool(sender()));
} }


void updateSceneY(int y)
void slot_updateSceneY(int y)
{ {
scene.setPosY(float(y) / 100, bool(sender())); scene.setPosY(float(y) / 100, bool(sender()));
} }


void checkCC_X(QString text)
void slot_checkCC_X(QString text)
{ {
if (! text.isEmpty())
{
bool ok;
int tmp_cc_x = text.split(" ").at(0).toInt(&ok, 16);
if (text.isEmpty())
return;


if (ok)
{
cc_x = tmp_cc_x;
scene.setControlX(cc_x);
}
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)
void slot_checkCC_Y(QString text)
{ {
if (! text.isEmpty())
{
bool ok;
int tmp_cc_y = text.split(" ").at(0).toInt(&ok, 16);
if (text.isEmpty())
return;


if (ok)
{
cc_y = tmp_cc_y;
scene.setControlY(cc_y);
}
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)
void slot_checkChannel(bool clicked)
{ {
if (! sender()) if (! sender())
return; return;
@@ -618,7 +737,7 @@ protected slots:
} }
} }


void checkChannel_all()
void slot_checkChannel_all()
{ {
ui->act_ch_01->setChecked(true); ui->act_ch_01->setChecked(true);
ui->act_ch_02->setChecked(true); ui->act_ch_02->setChecked(true);
@@ -648,7 +767,7 @@ protected slots:
scene.setChannels(m_channels); scene.setChannels(m_channels);
} }


void checkChannel_none()
void slot_checkChannel_none()
{ {
ui->act_ch_01->setChecked(false); ui->act_ch_01->setChecked(false);
ui->act_ch_02->setChecked(false); ui->act_ch_02->setChecked(false);
@@ -671,12 +790,12 @@ protected slots:
scene.setChannels(m_channels); scene.setChannels(m_channels);
} }


void setSmooth(bool yesno)
void slot_setSmooth(bool yesno)
{ {
scene.setSmooth(yesno); scene.setSmooth(yesno);
} }


void sceneCursorMoved(qreal xp, qreal yp)
void slot_sceneCursorMoved(float xp, float yp)
{ {
ui->dial_x->blockSignals(true); ui->dial_x->blockSignals(true);
ui->dial_y->blockSignals(true); ui->dial_y->blockSignals(true);
@@ -688,13 +807,13 @@ protected slots:
ui->dial_y->blockSignals(false); ui->dial_y->blockSignals(false);
} }


void showKeyboard(bool yesno)
void slot_showKeyboard(bool yesno)
{ {
ui->scrollArea->setVisible(yesno); ui->scrollArea->setVisible(yesno);
QTimer::singleShot(0, this, SLOT(updateScreen()));
QTimer::singleShot(0, this, SLOT(slot_updateScreen()));
} }


void about()
void slot_about()
{ {
QMessageBox::about(this, tr("About XY Controller"), tr("<h3>XY Controller</h3>" QMessageBox::about(this, tr("About XY Controller"), tr("<h3>XY Controller</h3>"
"<br>Version %1" "<br>Version %1"
@@ -702,16 +821,9 @@ protected slots:
"<br>Copyright (C) 2012 falkTX").arg(VERSION)); "<br>Copyright (C) 2012 falkTX").arg(VERSION));
} }


void updateScreen()
void slot_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);
updateScreen();
} }


protected: protected:
@@ -757,7 +869,6 @@ protected:
{ {
QVariantList channels = settings.value("Channels").toList(); QVariantList channels = settings.value("Channels").toList();



foreach (const QVariant& var, channels) foreach (const QVariant& var, channels)
{ {
bool ok; bool ok;
@@ -823,29 +934,32 @@ protected:
if (m_channels.contains(16)) if (m_channels.contains(16))
ui->act_ch_16->setChecked(true); ui->act_ch_16->setChecked(true);
} }

void timerEvent(QTimerEvent* event) void timerEvent(QTimerEvent* event)
{ {
if (event->timerId() == m_midiInTimerId) 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()
if (! qMidiInData.isEmpty())
{
unsigned char d1, d2, d3;
qMidiInInternal.copyDataFrom(&qMidiInData);

while (qMidiInInternal.get(&d1, &d2, &d3, false))
{
int channel = (d1 & 0x0F) + 1;
int mode = d1 & 0xF0;

if (m_channels.contains(channel))
{
if (mode == 0x80)
ui->keyboard->sendNoteOff(d2, false);
else if (mode == 0x90)
ui->keyboard->sendNoteOn(d2, false);
else if (mode == 0xB0)
scene.handleCC(d2, d3);
}
}
}


scene.updateSmooth(); scene.updateSmooth();
} }
@@ -872,16 +986,90 @@ private:


int m_midiInTimerId; int m_midiInTimerId;


XYGraphicsScene scene;
QSettings settings; QSettings settings;
XYGraphicsScene scene;
Ui::XYControllerW* const ui;


Ui::XYControllerW* ui;
Queue qMidiInInternal;
}; };


#include "xycontroller.moc" #include "xycontroller.moc"


// ------------------------------- // -------------------------------


int process_callback(const jack_nframes_t nframes, void*)
{
void* const midiInBuffer = jack_port_get_buffer(jMidiInPort, nframes);
void* const midiOutBuffer = jack_port_get_buffer(jMidiOutPort, nframes);

if (! (midiInBuffer && midiOutBuffer))
return 1;

// MIDI In
jack_midi_event_t midiEvent;
uint32_t midiEventCount = jack_midi_get_event_count(midiInBuffer);

qMidiInData.lock();

for (uint32_t i=0; i < midiEventCount; i++)
{
if (jack_midi_event_get(&midiEvent, midiInBuffer, i) != 0)
break;

if (midiEvent.size == 1)
qMidiInData.put(midiEvent.buffer[0], 0, 0, false);
else if (midiEvent.size == 2)
qMidiInData.put(midiEvent.buffer[0], midiEvent.buffer[1], 0, false);
else if (midiEvent.size >= 3)
qMidiInData.put(midiEvent.buffer[0], midiEvent.buffer[1], midiEvent.buffer[2], false);

if (qMidiInData.isFull())
break;
}
qMidiInData.unlock();

// MIDI Out
jack_midi_clear_buffer(midiOutBuffer);
qMidiOutData.lock();

if (! qMidiOutData.isEmpty())
{
unsigned char d1, d2, d3, data[3];

while (qMidiOutData.get(&d1, &d2, &d3, false))
{
data[0] = d1;
data[1] = d2;
data[2] = d3;
jack_midi_event_write(midiOutBuffer, 0, data, 3);
}
}
qMidiOutData.unlock();

return 0;
}

#ifdef HAVE_JACKSESSION
void session_callback(jack_session_event_t* const event, void* const arg)
{
#ifdef Q_OS_LINUX
QString filepath("cadence_xycontroller");
Q_UNUSED(arg);
#else
QString filepath((char*)arg);
#endif

event->command_line = strdup(filepath.toUtf8().constData());

jack_session_reply(jClient, event);

if (event->type == JackSessionSaveAndQuit)
QApplication::instance()->quit();

jack_session_event_free(event);
}
#endif

// ------------------------------- // -------------------------------


int main(int argc, char* argv[]) int main(int argc, char* argv[])
@@ -898,13 +1086,16 @@ int main(int argc, char* argv[])
app.setOrganizationName("Cadence"); app.setOrganizationName("Cadence");
//app.setWindowIcon(QIcon(":/48x48/xy-controller.png")); //app.setWindowIcon(QIcon(":/48x48/xy-controller.png"));


#if 0
// JACK initialization // JACK initialization
jack_status_t jStatus; jack_status_t jStatus;
jack_options_t jOptions = static_cast<JackOptions>(JackNoStartServer/*|JackSessionID*/);
jack_client = jack_client_open("XY-Controller", jOptions, &jStatus);
#ifdef HAVE_JACKSESSION
jack_options_t jOptions = static_cast<JackOptions>(JackNoStartServer|JackSessionID);
#else
jack_options_t jOptions = static_cast<JackOptions>(JackNoStartServer);
#endif
jClient = jack_client_open("XY-Controller", jOptions, &jStatus);


if (! jack_client)
if (! jClient)
{ {
std::string errorString(jack_status_get_error_string(jStatus)); std::string errorString(jack_status_get_error_string(jStatus));
QMessageBox::critical(nullptr, app.translate("XY-Controller", "Error"), app.translate("XY-Controller", QMessageBox::critical(nullptr, app.translate("XY-Controller", "Error"), app.translate("XY-Controller",
@@ -913,14 +1104,14 @@ int main(int argc, char* argv[])
return 1; 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);
jMidiInPort = jack_port_register(jClient, "midi_in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
jMidiOutPort = jack_port_register(jClient, "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);
jack_set_process_callback(jClient, process_callback, nullptr);
#ifdef HAVE_JACKSESSION
jack_set_session_callback(jClient, session_callback, argv[0]);
#endif #endif
jack_activate(jClient);


// Show GUI // Show GUI
XYControllerW gui; XYControllerW gui;
@@ -929,10 +1120,8 @@ int main(int argc, char* argv[])
// App-Loop // App-Loop
int ret = app.exec(); int ret = app.exec();


#if 0
jack_deactivate(jack_client);
jack_client_close(jack_client);
#endif
jack_deactivate(jClient);
jack_client_close(jClient);


return ret; return ret;
} }

+ 42
- 40
src/pixmapkeyboard.py View File

@@ -81,11 +81,13 @@ midi_keyboard2key_map = {


# MIDI Keyboard, using a pixmap for painting # MIDI Keyboard, using a pixmap for painting
class PixmapKeyboard(QWidget): class PixmapKeyboard(QWidget):
# enum Color
COLOR_CLASSIC = 0 COLOR_CLASSIC = 0
COLOR_ORANGE = 1
COLOR_ORANGE = 1


# enum Orientation
HORIZONTAL = 0 HORIZONTAL = 0
VERTICAL = 1
VERTICAL = 1


def __init__(self, parent): def __init__(self, parent):
QWidget.__init__(self, parent) QWidget.__init__(self, parent)
@@ -169,49 +171,19 @@ class PixmapKeyboard(QWidget):


self.update() self.update()


def keyPressEvent(self, event):
qKey = str(event.key())

if qKey in midi_keyboard2key_map.keys():
self.sendNoteOn(midi_keyboard2key_map.get(qKey))

QWidget.keyPressEvent(self, event)

def keyReleaseEvent(self, event):
qKey = str(event.key())

if qKey in midi_keyboard2key_map.keys():
self.sendNoteOff(midi_keyboard2key_map.get(qKey))

QWidget.keyReleaseEvent(self, event)

def mousePressEvent(self, event):
self.m_lastMouseNote = -1
self.handleMousePos(event.pos())
self.setFocus()
QWidget.mousePressEvent(self, event)

def mouseMoveEvent(self, event):
self.handleMousePos(event.pos())
QWidget.mousePressEvent(self, event)

def mouseReleaseEvent(self, event):
if self.m_lastMouseNote != -1:
self.sendNoteOff(self.m_lastMouseNote)
self.m_lastMouseNote = -1
QWidget.mouseReleaseEvent(self, event)

def handleMousePos(self, pos): def handleMousePos(self, pos):
if self.m_pixmap_mode == self.HORIZONTAL: if self.m_pixmap_mode == self.HORIZONTAL:
if pos.x() < 0 or pos.x() > self.m_octaves * 144: if pos.x() < 0 or pos.x() > self.m_octaves * 144:
return return
octave = int(pos.x() / self.p_width)
n_pos = QPointF(pos.x() % self.p_width, pos.y())
posX = pos.x() - 1
octave = int(posX / self.p_width)
n_pos = QPointF(posX % self.p_width, pos.y())
elif self.m_pixmap_mode == self.VERTICAL: elif self.m_pixmap_mode == self.VERTICAL:
if pos.y() < 0 or pos.y() > self.m_octaves * 144: if pos.y() < 0 or pos.y() > self.m_octaves * 144:
return return
octave = int(self.m_octaves - pos.y() / self.p_height)
n_pos = QPointF(pos.x(), pos.y() % self.p_height)
posY = pos.y() - 1
octave = int(self.m_octaves - posY / self.p_height)
n_pos = QPointF(pos.x(), posY % self.p_height)
else: else:
return return


@@ -254,6 +226,36 @@ class PixmapKeyboard(QWidget):


self.m_lastMouseNote = note self.m_lastMouseNote = note


def keyPressEvent(self, event):
if not event.isAutoRepeat():
qKey = str(event.key())
if qKey in midi_keyboard2key_map.keys():
self.sendNoteOn(midi_keyboard2key_map.get(qKey))
QWidget.keyPressEvent(self, event)

def keyReleaseEvent(self, event):
if not event.isAutoRepeat():
qKey = str(event.key())
if qKey in midi_keyboard2key_map.keys():
self.sendNoteOff(midi_keyboard2key_map.get(qKey))
QWidget.keyReleaseEvent(self, event)

def mousePressEvent(self, event):
self.m_lastMouseNote = -1
self.handleMousePos(event.pos())
self.setFocus()
QWidget.mousePressEvent(self, event)

def mouseMoveEvent(self, event):
self.handleMousePos(event.pos())
QWidget.mousePressEvent(self, event)

def mouseReleaseEvent(self, event):
if self.m_lastMouseNote != -1:
self.sendNoteOff(self.m_lastMouseNote)
self.m_lastMouseNote = -1
QWidget.mouseReleaseEvent(self, event)

def paintEvent(self, event): def paintEvent(self, event):
painter = QPainter(self) painter = QPainter(self)


@@ -283,7 +285,7 @@ class PixmapKeyboard(QWidget):
if self._isNoteBlack(note): if self._isNoteBlack(note):
continue continue


if note < 35:
if note < 36:
# cannot paint this note # cannot paint this note
continue continue
elif note < 48: elif note < 48:
@@ -345,7 +347,7 @@ class PixmapKeyboard(QWidget):
if not self._isNoteBlack(note): if not self._isNoteBlack(note):
continue continue


if note < 35:
if note < 36:
# cannot paint this note # cannot paint this note
continue continue
elif note < 48: elif note < 48:


+ 75
- 55
src/xycontroller.py View File

@@ -19,6 +19,7 @@
# Imports (Global) # Imports (Global)
from PyQt4.QtCore import pyqtSlot, Qt, QPointF, QRectF, QSettings, QTimer from PyQt4.QtCore import pyqtSlot, Qt, QPointF, QRectF, QSettings, QTimer
from PyQt4.QtGui import QApplication, QColor, QGraphicsItem, QGraphicsScene, QMainWindow, QPainter, QPen from PyQt4.QtGui import QApplication, QColor, QGraphicsItem, QGraphicsScene, QMainWindow, QPainter, QPen
#from Queue import Queue, Empty as QuequeEmpty
from queue import Queue, Empty as QuequeEmpty from queue import Queue, Empty as QuequeEmpty


# Imports (Custom) # Imports (Custom)
@@ -44,9 +45,9 @@ class XYGraphicsScene(QGraphicsScene):
self.m_channels = [] self.m_channels = []


self.m_mouseLock = False self.m_mouseLock = False
self.m_smooth = False
self.m_smooth_x = 0
self.m_smooth_y = 0
self.m_smooth = False
self.m_smooth_x = 0.0
self.m_smooth_y = 0.0


self.setBackgroundBrush(Qt.black) self.setBackgroundBrush(Qt.black)


@@ -70,26 +71,32 @@ class XYGraphicsScene(QGraphicsScene):
self.m_channels = channels self.m_channels = channels


def setPosX(self, x, forward=True): def setPosX(self, x, forward=True):
if not self.m_mouseLock:
pos_x = x * (self.p_size.x() + self.p_size.width())
self.m_cursor.setPos(pos_x, self.m_cursor.y())
self.m_lineV.setX(pos_x)
if self.m_mouseLock:
return

posX = x * (self.p_size.x() + self.p_size.width())
self.m_cursor.setPos(posX, self.m_cursor.y())
self.m_lineV.setX(posX)


if forward:
self.sendMIDI(pos_x / (self.p_size.x() + self.p_size.width()), None)
else:
self.m_smooth_x = pos_x
if forward:
value = posX / (self.p_size.x() + self.p_size.width())
self.sendMIDI(value, None)
else:
self.m_smooth_x = posX


def setPosY(self, y, forward=True): def setPosY(self, y, forward=True):
if not self.m_mouseLock:
pos_y = y * (self.p_size.y() + self.p_size.height())
self.m_cursor.setPos(self.m_cursor.x(), pos_y)
self.m_lineH.setY(pos_y)
if self.m_mouseLock:
return


if forward:
self.sendMIDI(None, pos_y / (self.p_size.y() + self.p_size.height()))
else:
self.m_smooth_y = pos_y
posY = y * (self.p_size.y() + self.p_size.height())
self.m_cursor.setPos(self.m_cursor.x(), posY)
self.m_lineH.setY(posY)

if forward:
value = posY / (self.p_size.y() + self.p_size.height())
self.sendMIDI(None, value)
else:
self.m_smooth_y = posY


def setSmooth(self, smooth): def setSmooth(self, smooth):
self.m_smooth = smooth self.m_smooth = smooth
@@ -104,28 +111,28 @@ class XYGraphicsScene(QGraphicsScene):


if param == self.cc_x: if param == self.cc_x:
sendUpdate = True sendUpdate = True
xp = (float(value) / 63) - 1.0
xp = float(value)/63 - 1.0
yp = self.m_cursor.y() / (self.p_size.y() + self.p_size.height()) yp = self.m_cursor.y() / (self.p_size.y() + self.p_size.height())


if xp < -1.0:
xp = -1.0
elif xp > 1.0:
xp = 1.0

self.setPosX(xp, False) self.setPosX(xp, False)


if param == self.cc_y: if param == self.cc_y:
sendUpdate = True sendUpdate = True
xp = self.m_cursor.x() / (self.p_size.x() + self.p_size.width()) xp = self.m_cursor.x() / (self.p_size.x() + self.p_size.width())
yp = (float(value) / 63) - 1.0

if yp < -1.0:
yp = -1.0
elif yp > 1.0:
yp = 1.0
yp = float(value)/63 - 1.0


self.setPosY(yp, False) self.setPosY(yp, False)


if xp < -1.0:
xp = -1.0
elif xp > 1.0:
xp = 1.0

if yp < -1.0:
yp = -1.0
elif yp > 1.0:
yp = 1.0

if sendUpdate: if sendUpdate:
self.emit(SIGNAL("cursorMoved(double, double)"), xp, yp) self.emit(SIGNAL("cursorMoved(double, double)"), xp, yp)


@@ -170,33 +177,37 @@ class XYGraphicsScene(QGraphicsScene):
jack_midi_out_data.put_nowait((0xB0 + channel - 1, self.cc_y, value)) jack_midi_out_data.put_nowait((0xB0 + channel - 1, self.cc_y, value))


def updateSize(self, size): def updateSize(self, size):
self.p_size.setRect(-(size.width() / 2), -(size.height() / 2), size.width(), size.height())
self.p_size.setRect(-(float(size.width())/2), -(float(size.height())/2), size.width(), size.height())


def updateSmooth(self): def updateSmooth(self):
if not self.m_smooth: if not self.m_smooth:
return return


if self.m_cursor.x() != self.m_smooth_x or self.m_cursor.y() != self.m_smooth_y:
if abs(self.m_cursor.x() - self.m_smooth_x) <= 0.001:
self.m_smooth_x = self.m_cursor.x()
return
elif abs(self.m_cursor.y() - self.m_smooth_y) <= 0.001:
self.m_smooth_y = self.m_cursor.y()
return
if self.m_cursor.x() == self.m_smooth_x and self.m_cursor.y() == self.m_smooth_y:
return


new_x = (self.m_smooth_x + self.m_cursor.x() * 3) / 4
new_y = (self.m_smooth_y + self.m_cursor.y() * 3) / 4
pos = QPointF(new_x, new_y)
if abs(self.m_cursor.x() - self.m_smooth_x) <= 0.001:
self.m_smooth_x = self.m_cursor.x()
return
if abs(self.m_cursor.y() - self.m_smooth_y) <= 0.001:
self.m_smooth_y = self.m_cursor.y()
return


self.m_cursor.setPos(pos)
self.m_lineH.setY(pos.y())
self.m_lineV.setX(pos.x())
print("updateSmooth() - %f %f | %f %f" % (self.m_cursor.x(), self.m_cursor.y(), self.m_smooth_x, self.m_smooth_y))


xp = pos.x() / (self.p_size.x() + self.p_size.width())
yp = pos.y() / (self.p_size.y() + self.p_size.height())
newX = float(self.m_smooth_x + self.m_cursor.x()*3) / 4
newY = float(self.m_smooth_y + self.m_cursor.y()*3) / 4
pos = QPointF(newX, newY)


self.sendMIDI(xp, yp)
self.emit(SIGNAL("cursorMoved(double, double)"), xp, yp)
self.m_cursor.setPos(pos)
#self.m_lineH.setY(pos.y())
#self.m_lineV.setX(pos.x())

xp = pos.x() / (self.p_size.x() + self.p_size.width())
yp = pos.y() / (self.p_size.y() + self.p_size.height())

#self.sendMIDI(xp, yp)
self.emit(SIGNAL("cursorMoved(double, double)"), xp, yp)


def keyPressEvent(self, event): def keyPressEvent(self, event):
event.accept() event.accept()
@@ -324,25 +335,34 @@ class XYControllerW(QMainWindow, ui_xycontroller.Ui_XYControllerW):
@pyqtSlot(int) @pyqtSlot(int)
def slot_updateSceneX(self, x): def slot_updateSceneX(self, x):
self.scene.setPosX(float(x) / 100, bool(self.sender())) self.scene.setPosX(float(x) / 100, bool(self.sender()))
print("slot_updateSceneX(%i)" % x)


@pyqtSlot(int) @pyqtSlot(int)
def slot_updateSceneY(self, y): def slot_updateSceneY(self, y):
self.scene.setPosY(float(y) / 100, bool(self.sender())) self.scene.setPosY(float(y) / 100, bool(self.sender()))
print("slot_updateSceneY(%i)" % y)


@pyqtSlot(str) @pyqtSlot(str)
def slot_checkCC_X(self, text): def slot_checkCC_X(self, text):
if text:
self.cc_x = int(text.split(" ")[0], 16)
self.scene.setControlX(self.cc_x)
if not text:
return

self.cc_x = int(text.split(" ")[0], 16)
self.scene.setControlX(self.cc_x)


@pyqtSlot(str) @pyqtSlot(str)
def slot_checkCC_Y(self, text): def slot_checkCC_Y(self, text):
if text:
self.cc_y = int(text.split(" ")[0], 16)
self.scene.setControlY(self.cc_y)
if not text:
return

self.cc_y = int(text.split(" ")[0], 16)
self.scene.setControlY(self.cc_y)


@pyqtSlot(bool) @pyqtSlot(bool)
def slot_checkChannel(self, clicked): def slot_checkChannel(self, clicked):
if not self.sender():
return

channel = int(self.sender().text()) channel = int(self.sender().text())
if clicked and channel not in self.m_channels: if clicked and channel not in self.m_channels:
self.m_channels.append(channel) self.m_channels.append(channel)


Loading…
Cancel
Save