diff options
Diffstat (limited to 'muse_qt4_evolution/midiplugins/splitlayer')
5 files changed, 651 insertions, 0 deletions
diff --git a/muse_qt4_evolution/midiplugins/splitlayer/CMakeLists.txt b/muse_qt4_evolution/midiplugins/splitlayer/CMakeLists.txt new file mode 100644 index 00000000..b6803d8b --- /dev/null +++ b/muse_qt4_evolution/midiplugins/splitlayer/CMakeLists.txt @@ -0,0 +1,45 @@ +#============================================================================= +# MusE +# Linux Music Editor +# $Id:$ +# +# Copyright (C) 2002-2006 by Werner Schweer and others +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +#============================================================================= + +QT4_WRAP_CPP ( splitlayer_mocs splitlayergui.h ) +## QT4_WRAP_UI ( splitlayer_uis splitlayergui.ui ) + +add_library ( splitlayer SHARED + splitlayer.cpp + splitlayergui.cpp + splitlayergui.h + ${splitlayer_mocs} + ) +target_link_libraries( splitlayer + midiplugin + ${QT_LIBRARIES} + ) + +# - tell cmake to name target splitlayer.so instead of +# libsplitlayer.so +# - use precompiled header files +# +set_target_properties ( splitlayer + PROPERTIES PREFIX "" + COMPILE_FLAGS "-include ${PROJECT_BINARY_DIR}/all-pic.h" + ) + +install_targets ( /${CMAKE_INSTALL_LIBDIR}/${MusE_INSTALL_NAME}/midiplugins/ splitlayer ) + diff --git a/muse_qt4_evolution/midiplugins/splitlayer/splitlayer.cpp b/muse_qt4_evolution/midiplugins/splitlayer/splitlayer.cpp new file mode 100644 index 00000000..7ea4ba3e --- /dev/null +++ b/muse_qt4_evolution/midiplugins/splitlayer/splitlayer.cpp @@ -0,0 +1,209 @@ +//============================================================================= +// MusE +// Linux Music Editor +// $Id:$ +// +// Copyright (C) 2006 by Werner Schweer +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +//============================================================================= + +#include "splitlayergui.h" +#include "splitlayer.h" +#include "midi.h" +#include "midievent.h" + +//--------------------------------------------------------- +// SplitLayer +//--------------------------------------------------------- + +SplitLayer::SplitLayer(const char* name, const MempiHost* h) + : Mempi(name, h) + { + gui = 0; + } + +//--------------------------------------------------------- +// SplitLayer +//--------------------------------------------------------- + +SplitLayer::~SplitLayer() + { + if (gui) + delete gui; + } + +//--------------------------------------------------------- +// init +//--------------------------------------------------------- + +bool SplitLayer::init() + { + data.startVelo[0] = 0; + data.endVelo[0] = 128; + data.startPitch[0] = 0; + data.endPitch[0] = 128; + data.pitchOffset[0] = 0; + data.veloOffset[0] = 0; + for (int i = 1; i < MIDI_CHANNELS; ++i) { + data.startVelo[i] = 0; + data.endVelo[i] = 0; + data.startPitch[i] = 0; + data.endPitch[i] = 0; + data.pitchOffset[i] = 0; + data.veloOffset[i] = 0; + } + memset(notes, 0, 128 * sizeof(int)); + learnMode = false; + gui = new SplitLayerGui(this, 0); + gui->hide(); + gui->setWindowTitle(QString(name())); + gui->init(); + return false; + } + +//--------------------------------------------------------- +// getGeometry +//--------------------------------------------------------- + +void SplitLayer::getGeometry(int* x, int* y, int* w, int* h) const + { + QPoint pos(gui->pos()); + QSize size(gui->size()); + *x = pos.x(); + *y = pos.y(); + *w = size.width(); + *h = size.height(); + } + +//--------------------------------------------------------- +// setGeometry +//--------------------------------------------------------- + +void SplitLayer::setGeometry(int x, int y, int w, int h) + { + gui->resize(QSize(w, h)); + gui->move(QPoint(x, y)); + } + +//--------------------------------------------------------- +// process +//--------------------------------------------------------- + +void SplitLayer::process(unsigned, unsigned, MidiEventList* il, MidiEventList* ol) + { + for (iMidiEvent i = il->begin(); i != il->end(); ++i) { + if (i->type() != ME_NOTEON && i->type() != ME_NOTEOFF) { + ol->insert(*i); + continue; + } + int pitch = i->dataA(); + int velo = i->dataB(); + if (learnMode) { + if (learnStartPitch) + data.startPitch[learnChannel] = pitch; + else + data.endPitch[learnChannel] = pitch; + learnMode = false; + gui->sendResetLearnMode(); + return; + } + if (i->type() == ME_NOTEON && velo) { + for (int ch = 0; ch < MIDI_CHANNELS; ++ch) { + MidiEvent event(*i); + if (pitch >= data.startPitch[ch] + && pitch <= data.endPitch[ch] + && velo >= data.startVelo[ch] + && velo <= data.endVelo[ch]) { + notes[pitch] |= (1 << ch); + event.setChannel(ch); + int p = pitch; + int v = velo; + p += data.pitchOffset[ch]; + if (p > 127) + p = 127; + else if (p < 0) + p = 0; + v += data.veloOffset[ch]; + if (v > 127) + v = 127; + else if (v < 0) + v = 0; + event.setA(p); + event.setB(v); + ol->insert(event); + } + } + } + else { + for (int ch = 0; ch < MIDI_CHANNELS; ++ch) { + if (notes[pitch] & (1 << ch)) { + MidiEvent event(*i); + event.setChannel(ch); + int p = pitch + data.pitchOffset[ch]; + if (p < 0) + p = 0; + else if (p > 127) + p = 127; + event.setA(p); + ol->insert(event); + } + } + notes[pitch] = 0; + } + } + } + +//--------------------------------------------------------- +// getInitData +//--------------------------------------------------------- + +void SplitLayer::getInitData(int* n, const unsigned char** p) const + { + *n = sizeof(data); + *p = (unsigned char*)&data; + } + +//--------------------------------------------------------- +// setInitData +//--------------------------------------------------------- + +void SplitLayer::setInitData(int n, const unsigned char* p) + { + memcpy((void*)&data, p, n); + if (gui) + gui->init(); + } + +//--------------------------------------------------------- +// inst +//--------------------------------------------------------- + +static Mempi* instantiate(const char* name, const MempiHost* h) + { + return new SplitLayer(name, h); + } + +extern "C" { + static MEMPI descriptor = { + "SplitLayer", + "MusE Midi Splits and Layers", + "0.1", // version string + MEMPI_FILTER, + MEMPI_MAJOR_VERSION, MEMPI_MINOR_VERSION, + instantiate + }; + + const MEMPI* mempi_descriptor() { return &descriptor; } + } + diff --git a/muse_qt4_evolution/midiplugins/splitlayer/splitlayer.h b/muse_qt4_evolution/midiplugins/splitlayer/splitlayer.h new file mode 100644 index 00000000..7c213c01 --- /dev/null +++ b/muse_qt4_evolution/midiplugins/splitlayer/splitlayer.h @@ -0,0 +1,69 @@ +//============================================================================= +// MusE +// Linux Music Editor +// $Id:$ +// +// Copyright (C) 2006 by Werner Schweer +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +//============================================================================= + +#ifndef __METRONOM_H__ +#define __METRONOM_H__ + +#include "../libmidiplugin/mempi.h" + +static const int MIDI_CHANNELS = 16; + +//--------------------------------------------------------- +// SplitLayer - splits and layers for midi input +//--------------------------------------------------------- + +class SplitLayer : public Mempi { + + protected: + struct InitData { + int startVelo[MIDI_CHANNELS]; + int endVelo[MIDI_CHANNELS]; + int startPitch[MIDI_CHANNELS]; + int endPitch[MIDI_CHANNELS]; + int pitchOffset[MIDI_CHANNELS]; + int veloOffset[MIDI_CHANNELS]; + } data; + int notes[128]; // bitmapped note-on/channel values + bool learnMode; + int learnChannel; + bool learnStartPitch; + + SplitLayerGui* gui; + friend class SplitLayerGui; + + virtual void process(unsigned, unsigned, MidiEventList*, MidiEventList*); + + public: + SplitLayer(const char* name, const MempiHost*); + ~SplitLayer(); + virtual bool init(); + + virtual bool hasGui() const { return true; } + virtual bool guiVisible() const { return gui->isVisible(); } + virtual void showGui(bool val) { gui->setShown(val); } + virtual void getGeometry(int* x, int* y, int* w, int* h) const; + virtual void setGeometry(int, int, int, int); + + virtual void getInitData(int*, const unsigned char**) const; + virtual void setInitData(int, const unsigned char*); + }; + +#endif + diff --git a/muse_qt4_evolution/midiplugins/splitlayer/splitlayergui.cpp b/muse_qt4_evolution/midiplugins/splitlayer/splitlayergui.cpp new file mode 100644 index 00000000..b5d2bdb4 --- /dev/null +++ b/muse_qt4_evolution/midiplugins/splitlayer/splitlayergui.cpp @@ -0,0 +1,263 @@ +//============================================================================= +// MusE +// Linux Music Editor +// $Id:$ +// +// Copyright (C) 2006 by Werner Schweer +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +//============================================================================= + +#include "splitlayergui.h" +#include "splitlayer.h" +#include "gui.h" + +//--------------------------------------------------------- +// SplitLayerGui +//--------------------------------------------------------- + +SplitLayerGui::SplitLayerGui(SplitLayer* f, QWidget* parent) + : QWidget(parent) + { + sl = f; + QGridLayout* grid = new QGridLayout; + grid->setSpacing(1); + setLayout(grid); + QSignalMapper* m1 = new QSignalMapper(this); + QSignalMapper* m2 = new QSignalMapper(this); + QSignalMapper* m3 = new QSignalMapper(this); + QSignalMapper* m4 = new QSignalMapper(this); + QSignalMapper* m5 = new QSignalMapper(this); + QSignalMapper* m6 = new QSignalMapper(this); + connect(m1, SIGNAL(mapped(int)), SLOT(startPitchChanged(int))); + connect(m2, SIGNAL(mapped(int)), SLOT(endPitchChanged(int))); + connect(m3, SIGNAL(mapped(int)), SLOT(pitchOffsetChanged(int))); + connect(m4, SIGNAL(mapped(int)), SLOT(startVeloChanged(int))); + connect(m5, SIGNAL(mapped(int)), SLOT(endVeloChanged(int))); + connect(m6, SIGNAL(mapped(int)), SLOT(veloOffsetChanged(int))); + for (int i = 0; i < MIDI_CHANNELS; ++i) { + QLabel* l = new QLabel(QString("Ch %1").arg(i+1)); + grid->addWidget(l, i, 0); + + p1[i] = new Awl::PitchEdit(0); + p1[i]->setToolTip(tr("start pitch for split")); + connect(p1[i], SIGNAL(valueChanged(int)), m1, SLOT(map())); + m1->setMapping(p1[i], i); + + a1[i] = new QAction(this); + a1[i]->setToolTip(tr("enable learn mode for start pitch")); + a1[i]->setCheckable(true); + QIcon icon; + icon.addFile(":/xpm/recordOn.svg", ICON_SIZE, QIcon::Normal, QIcon::On); + icon.addFile(":/xpm/recordOff.svg", ICON_SIZE, QIcon::Normal, QIcon::Off); + a1[i]->setIcon(icon); + a1[i]->setData(i); + QToolButton* rb1 = new QToolButton; + rb1->setDefaultAction(a1[i]); + connect(rb1, SIGNAL(triggered(QAction*)), SLOT(learnStartPitch(QAction*))); + + p2[i] = new Awl::PitchEdit(0); + p2[i]->setToolTip(tr("end pitch for split")); + connect(p2[i], SIGNAL(valueChanged(int)), m2, SLOT(map())); + m2->setMapping(p2[i], i); + + a2[i] = new QAction(this); + a2[i]->setToolTip(tr("enable learn mode for end pitch")); + a2[i]->setCheckable(true); + a2[i]->setIcon(icon); + a2[i]->setData(i); + QToolButton* rb2 = new QToolButton; + rb2->setDefaultAction(a2[i]); + connect(rb2, SIGNAL(triggered(QAction*)), SLOT(learnEndPitch(QAction*))); + + p3[i] = new Awl::PitchEdit(0); + p3[i]->setToolTip(tr("pitch offset for split")); + p3[i]->setDeltaMode(true); + connect(p3[i], SIGNAL(valueChanged(int)), m3, SLOT(map())); + m3->setMapping(p3[i], i); + + p4[i] = new QSpinBox; + p4[i]->setRange(0, 127); + p4[i]->setToolTip(tr("start velocity for split")); + connect(p4[i], SIGNAL(valueChanged(int)), m4, SLOT(map())); + m4->setMapping(p4[i], i); + + p5[i] = new QSpinBox; + p5[i]->setRange(0, 127); + p5[i]->setToolTip(tr("end velocity for split")); + connect(p5[i], SIGNAL(valueChanged(int)), m5, SLOT(map())); + m5->setMapping(p5[i], i); + + p6[i] = new QSpinBox; + p6[i]->setRange(-127, 127); + p6[i]->setToolTip(tr("velocity offset for split")); + connect(p6[i], SIGNAL(valueChanged(int)), m6, SLOT(map())); + m6->setMapping(p6[i], i); + + grid->addWidget(p1[i], i, 1); + grid->addWidget(rb1, i, 2); + grid->addWidget(p2[i], i, 3); + grid->addWidget(rb2, i, 4); + grid->addWidget(p3[i], i, 5); + grid->addWidget(p4[i], i, 7); + grid->addWidget(p5[i], i, 8); + grid->addWidget(p6[i], i, 9); + } + QFrame* fr = new QFrame; + fr->setFrameStyle(QFrame::VLine | QFrame::Raised); + fr->setLineWidth(4); + grid->addWidget(fr, 0, 6, MIDI_CHANNELS, 1); + + int filedes[2]; // 0 - reading 1 - writing + if (pipe(filedes) == -1) { + perror("SplitLayerGui:creating pipe"); + exit(-1); + } + fd2 = filedes[0]; + fd1 = filedes[1]; + + QSocketNotifier* socket = new QSocketNotifier(fd2, + QSocketNotifier::Read, this); + connect(socket, SIGNAL(activated(int)), SLOT(resetLearnMode(int))); + init(); + } + +//--------------------------------------------------------- +// init +//--------------------------------------------------------- + +void SplitLayerGui::init() + { + for (int i = 0; i < MIDI_CHANNELS; ++i) { + p1[i]->setValue(sl->data.startPitch[i]); + p2[i]->setValue(sl->data.endPitch[i]); + p3[i]->setValue(sl->data.pitchOffset[i]); + p4[i]->setValue(sl->data.startVelo[i]); + p5[i]->setValue(sl->data.endVelo[i]); + p6[i]->setValue(sl->data.veloOffset[i]); + } + } + +//--------------------------------------------------------- +// learnStartPitch +//--------------------------------------------------------- + +void SplitLayerGui::learnStartPitch(QAction* a) + { + sl->learnChannel = a->data().toInt(); + sl->learnStartPitch = true; + sl->learnMode = true; + for (int i = 0; i < MIDI_CHANNELS; ++i) { + if (a != a1[i]) + a1[i]->setChecked(false); + if (a != a2[i]) + a2[i]->setChecked(false); + } + } + +//--------------------------------------------------------- +// learnEndPitch +//--------------------------------------------------------- + +void SplitLayerGui::learnEndPitch(QAction* a) + { + sl->learnChannel = a->data().toInt(); + sl->learnStartPitch = false; + sl->learnMode = true; + for (int i = 0; i < MIDI_CHANNELS; ++i) { + if (a != a1[i]) + a1[i]->setChecked(false); + if (a != a2[i]) + a2[i]->setChecked(false); + } + } + +//--------------------------------------------------------- +// startPitchChanged +//--------------------------------------------------------- + +void SplitLayerGui::startPitchChanged(int n) + { + sl->data.startPitch[n] = p1[n]->value(); + } + +//--------------------------------------------------------- +// endPitchChanged +//--------------------------------------------------------- + +void SplitLayerGui::endPitchChanged(int n) + { + sl->data.endPitch[n] = p2[n]->value(); + } + +//--------------------------------------------------------- +// pitchOffsetChanged +//--------------------------------------------------------- + +void SplitLayerGui::pitchOffsetChanged(int n) + { + sl->data.pitchOffset[n] = p3[n]->value(); + } + +//--------------------------------------------------------- +// startVeloChanged +//--------------------------------------------------------- + +void SplitLayerGui::startVeloChanged(int n) + { + sl->data.startVelo[n] = p4[n]->value(); + } + +//--------------------------------------------------------- +// endVeloChanged +//--------------------------------------------------------- + +void SplitLayerGui::endVeloChanged(int n) + { + sl->data.endVelo[n] = p5[n]->value(); + } + +//--------------------------------------------------------- +// veloOffsetChanged +//--------------------------------------------------------- + +void SplitLayerGui::veloOffsetChanged(int n) + { + sl->data.veloOffset[n] = p6[n]->value(); + } + +//--------------------------------------------------------- +// resetLearnMode +//--------------------------------------------------------- + +void SplitLayerGui::resetLearnMode(int fd) + { + char buffer[16]; + read(fd, buffer, 16); + + for (int i = 0; i < MIDI_CHANNELS; ++i) { + a1[i]->setChecked(false); + a2[i]->setChecked(false); + } + init(); + } + +//--------------------------------------------------------- +// sendResetLearnMode +//--------------------------------------------------------- + +void SplitLayerGui::sendResetLearnMode() + { + write(fd1, "X", 1); + } + diff --git a/muse_qt4_evolution/midiplugins/splitlayer/splitlayergui.h b/muse_qt4_evolution/midiplugins/splitlayer/splitlayergui.h new file mode 100644 index 00000000..4f2006ca --- /dev/null +++ b/muse_qt4_evolution/midiplugins/splitlayer/splitlayergui.h @@ -0,0 +1,65 @@ +//============================================================================= +// MusE +// Linux Music Editor +// $Id:$ +// +// Copyright (C) 2006 by Werner Schweer +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +//============================================================================= + +#ifndef __SPLITLAYERGUI_H__ +#define __SPLITLAYERGUI_H__ + +#include "awl/pitchedit.h" + +class SplitLayer; + +//--------------------------------------------------------- +// SplitLayerGui +//--------------------------------------------------------- + +class SplitLayerGui : public QWidget { + Q_OBJECT + SplitLayer* sl; + + Awl::PitchEdit* p1[16]; + Awl::PitchEdit* p2[16]; + Awl::PitchEdit* p3[16]; + QSpinBox* p4[16]; + QSpinBox* p5[16]; + QSpinBox* p6[16]; + + QAction* a1[16]; + QAction* a2[16]; + int fd1, fd2; + + private slots: + void learnStartPitch(QAction*); + void learnEndPitch(QAction*); + void startPitchChanged(int); + void endPitchChanged(int); + void pitchOffsetChanged(int); + void resetLearnMode(int); + void startVeloChanged(int); + void endVeloChanged(int); + void veloOffsetChanged(int); + + public: + SplitLayerGui(SplitLayer*, QWidget* parent=0); + void init(); + void sendResetLearnMode(); + }; + +#endif + |