Browse Source

Enable midisequencer plugin, prepare it for the upcoming UI

tags/1.9.6
falkTX 10 years ago
parent
commit
d783d19df9
6 changed files with 243 additions and 45 deletions
  1. +2
    -0
      source/backend/Makefile
  2. +1
    -0
      source/native-plugins/Makefile
  3. +6
    -6
      source/native-plugins/_all.c
  4. +41
    -0
      source/native-plugins/midi-base.hpp
  5. +2
    -1
      source/native-plugins/midi-file.cpp
  6. +191
    -38
      source/native-plugins/midi-sequencer.cpp

+ 2
- 0
source/backend/Makefile View File

@@ -54,6 +54,7 @@ UTILS_LIBS += $(MODULEDIR)/juce_audio_formats.a
UTILS_LIBS += $(MODULEDIR)/juce_core.a UTILS_LIBS += $(MODULEDIR)/juce_core.a
UTILS_LIBS += $(MODULEDIR)/lilv.a UTILS_LIBS += $(MODULEDIR)/lilv.a
UTILS_LIBS += $(MODULEDIR)/native-plugins.a UTILS_LIBS += $(MODULEDIR)/native-plugins.a
UTILS_LIBS += $(MODULEDIR)/rtmempool.a


ifeq ($(HAVE_DGL),true) ifeq ($(HAVE_DGL),true)
UTILS_LIBS += $(MODULEDIR)/dgl.a UTILS_LIBS += $(MODULEDIR)/dgl.a
@@ -109,6 +110,7 @@ UTILS_LINK_FLAGS += $(JUCE_AUDIO_FORMATS_LIBS)
UTILS_LINK_FLAGS += $(JUCE_CORE_LIBS) UTILS_LINK_FLAGS += $(JUCE_CORE_LIBS)
UTILS_LINK_FLAGS += $(LILV_LIBS) UTILS_LINK_FLAGS += $(LILV_LIBS)
UTILS_LINK_FLAGS += $(NATIVE_PLUGINS_LIBS) UTILS_LINK_FLAGS += $(NATIVE_PLUGINS_LIBS)
UTILS_LINK_FLAGS += $(RTMEMPOOL_LIBS)


ifneq ($(HAIKU),true) ifneq ($(HAIKU),true)
UTILS_LINK_FLAGS += -lpthread UTILS_LINK_FLAGS += -lpthread


+ 1
- 0
source/native-plugins/Makefile View File

@@ -72,6 +72,7 @@ OBJS += \
$(OBJDIR)/audio-file.cpp.o \ $(OBJDIR)/audio-file.cpp.o \
$(OBJDIR)/bigmeter.cpp.o \ $(OBJDIR)/bigmeter.cpp.o \
$(OBJDIR)/midi-file.cpp.o \ $(OBJDIR)/midi-file.cpp.o \
$(OBJDIR)/midi-sequencer.cpp.o \
$(OBJDIR)/notes.cpp.o $(OBJDIR)/notes.cpp.o


# ---------------------------------------------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------------------------------------------


+ 6
- 6
source/native-plugins/_all.c View File

@@ -32,11 +32,12 @@ extern void carla_register_native_plugin_midithrough(void);
extern void carla_register_native_plugin_miditranspose(void); extern void carla_register_native_plugin_miditranspose(void);
extern void carla_register_native_plugin_nekofilter(void); extern void carla_register_native_plugin_nekofilter(void);


// Audio File
// Audio file
extern void carla_register_native_plugin_audiofile(void); extern void carla_register_native_plugin_audiofile(void);


// MIDI File
// MIDI file and sequencer
extern void carla_register_native_plugin_midifile(void); extern void carla_register_native_plugin_midifile(void);
extern void carla_register_native_plugin_midisequencer(void);


// Carla // Carla
extern void carla_register_native_plugin_carla(void); extern void carla_register_native_plugin_carla(void);
@@ -70,8 +71,6 @@ extern void carla_register_native_plugin_zita_jaaa(void);


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


void carla_register_all_plugins(void);

void carla_register_all_plugins(void) void carla_register_all_plugins(void)
{ {
// Simple plugins // Simple plugins
@@ -83,11 +82,12 @@ void carla_register_all_plugins(void)
carla_register_native_plugin_miditranspose(); carla_register_native_plugin_miditranspose();
carla_register_native_plugin_nekofilter(); carla_register_native_plugin_nekofilter();


// Audio File
// Audio file
carla_register_native_plugin_audiofile(); carla_register_native_plugin_audiofile();


// MIDI File
// MIDI file and sequencer
carla_register_native_plugin_midifile(); carla_register_native_plugin_midifile();
carla_register_native_plugin_midisequencer();


// Carla // Carla
carla_register_native_plugin_carla(); carla_register_native_plugin_carla();


+ 41
- 0
source/native-plugins/midi-base.hpp View File

@@ -186,6 +186,34 @@ public:
appendSorted(rawEvent); appendSorted(rawEvent);
} }


// -------------------------------------------------------------------
// remove data

void removeRaw(const uint64_t time, const uint8_t* const data, const uint8_t size)
{
const CarlaMutexLocker sl(fMutex);

for (LinkedList<const RawMidiEvent*>::Itenerator it = fData.begin(); it.valid(); it.next())
{
const RawMidiEvent* const rawMidiEvent(it.getValue(nullptr));
CARLA_SAFE_ASSERT_CONTINUE(rawMidiEvent != nullptr);

if (rawMidiEvent->time != time)
continue;
if (rawMidiEvent->size != size)
continue;
if (std::memcmp(rawMidiEvent->data, data, size) != 0)
continue;

delete rawMidiEvent;
fData.remove(it);

return;
}

carla_stderr("MidiPattern::removeRaw(" P_INT64 ", %p, %i) - unable to find event to remove", time, data, size);
}

// ------------------------------------------------------------------- // -------------------------------------------------------------------
// clear // clear


@@ -239,6 +267,19 @@ public:
} }


// ------------------------------------------------------------------- // -------------------------------------------------------------------
// special

const CarlaMutex& getLock() const noexcept
{
return fMutex;
}

LinkedList<const RawMidiEvent*>::Itenerator iteneratorBegin() const noexcept
{
return fData.begin();
}

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


private: private:
AbstractMidiPlayer* const kPlayer; AbstractMidiPlayer* const kPlayer;


+ 2
- 1
source/native-plugins/midi-file.cpp View File

@@ -199,7 +199,8 @@ static const NativePluginDescriptor midifileDesc = {
/* category */ NATIVE_PLUGIN_CATEGORY_UTILITY, /* category */ NATIVE_PLUGIN_CATEGORY_UTILITY,
/* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE
|NATIVE_PLUGIN_HAS_UI |NATIVE_PLUGIN_HAS_UI
|NATIVE_PLUGIN_NEEDS_UI_OPEN_SAVE),
|NATIVE_PLUGIN_NEEDS_UI_OPEN_SAVE
|NATIVE_PLUGIN_USES_TIME),
/* supports */ static_cast<NativePluginSupports>(0x0), /* supports */ static_cast<NativePluginSupports>(0x0),
/* audioIns */ 0, /* audioIns */ 0,
/* audioOuts */ 0, /* audioOuts */ 0,


+ 191
- 38
source/native-plugins/midi-sequencer.cpp View File

@@ -15,19 +15,24 @@
* For a full copy of the GNU General Public License see the doc/GPL.txt file. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
*/ */


#include "CarlaNative.hpp"
#include "CarlaNativeExtUI.hpp"
#include "RtLinkedList.hpp"

#include "midi-base.hpp" #include "midi-base.hpp"


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


class MidiSequencerPlugin : public NativePluginClass,
class MidiSequencerPlugin : public NativePluginAndUiClass,
public AbstractMidiPlayer public AbstractMidiPlayer
{ {
public: public:
MidiSequencerPlugin(const NativeHostDescriptor* const host) MidiSequencerPlugin(const NativeHostDescriptor* const host)
: NativePluginClass(host),
: NativePluginAndUiClass(host, CARLA_OS_SEP_STR "midiseq-ui"),
fWantInEvents(false), fWantInEvents(false),
fMidiOut(this)
fWasPlayingBefore(false),
fInEvents(),
fMidiOut(this),
leakDetector_MidiSequencerPlugin()
{ {
// TEST SONG (unsorted to test RtList API) // TEST SONG (unsorted to test RtList API)


@@ -122,22 +127,10 @@ public:
fMidiOut.addNote(3456*m, 0, 62, 90, 325*m); fMidiOut.addNote(3456*m, 0, 62, 90, 325*m);
} }


~MidiSequencerPlugin() override
{
}

protected: protected:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Plugin process calls // Plugin process calls


void activate() override
{
}

void deactivate() override
{
}

void process(float**, float**, const uint32_t frames, const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount) override void process(float**, float**, const uint32_t frames, const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount) override
{ {
const NativeTimeInfo* const timePos = getTimeInfo(); const NativeTimeInfo* const timePos = getTimeInfo();
@@ -155,26 +148,80 @@ protected:
rawMidiEvent.data[2] = midiEvent->data[2]; rawMidiEvent.data[2] = midiEvent->data[2];
rawMidiEvent.data[3] = midiEvent->data[3]; rawMidiEvent.data[3] = midiEvent->data[3];
rawMidiEvent.size = midiEvent->size; rawMidiEvent.size = midiEvent->size;
rawMidiEvent.time = timePos->frame + midiEvent->time;
rawMidiEvent.time = timePos->playing ? timePos->frame + midiEvent->time : 0;


fInEvents.appendRT(rawMidiEvent); fInEvents.appendRT(rawMidiEvent);
} }


if (fInEvents.mutex.tryLock())
{
fInEvents.splice();
fInEvents.mutex.unlock();
}
fInEvents.trySplice();
} }


if (timePos->playing) if (timePos->playing)
{
fMidiOut.play(timePos->frame, frames); fMidiOut.play(timePos->frame, frames);
}
else if (fWasPlayingBefore)
{
NativeMidiEvent midiEvent;

midiEvent.port = 0;
midiEvent.time = 0;
midiEvent.data[0] = MIDI_STATUS_CONTROL_CHANGE;
midiEvent.data[1] = MIDI_CONTROL_ALL_NOTES_OFF;
midiEvent.data[2] = 0;
midiEvent.data[3] = 0;
midiEvent.size = 3;

for (int i=0; i < MAX_MIDI_CHANNELS; ++i)
{
midiEvent.data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE+i);
NativePluginAndUiClass::writeMidiEvent(&midiEvent);
}

carla_stdout("WAS PLAYING BEFORE, NOW STOPPED");
}

fWasPlayingBefore = timePos->playing;
} }


// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Plugin process calls
// Plugin UI calls


void writeMidiEvent(const uint8_t port, const uint32_t timePosFrame, const RawMidiEvent* const event) override
void uiShow(const bool show) override
{
NativePluginAndUiClass::uiShow(show);

if (show)
_sendEventsToUI();
}

// -------------------------------------------------------------------
// Plugin state calls

char* getState() const override
{
// TODO: malloc list of events

return nullptr;
}

void setState(const char* const data) override
{
CARLA_SAFE_ASSERT_RETURN(data != nullptr,);

return;

fMidiOut.clear();

// TODO: set events according to data

_sendEventsToUI();
}

// -------------------------------------------------------------------
// AbstractMidiPlayer calls

void writeMidiEvent(const uint8_t port, const uint64_t timePosFrame, const RawMidiEvent* const event) override
{ {
NativeMidiEvent midiEvent; NativeMidiEvent midiEvent;


@@ -186,48 +233,151 @@ protected:
midiEvent.data[3] = event->data[3]; midiEvent.data[3] = event->data[3];
midiEvent.size = event->size; midiEvent.size = event->size;


NativePluginClass::writeMidiEvent(&midiEvent);
NativePluginAndUiClass::writeMidiEvent(&midiEvent);
}

// -------------------------------------------------------------------
// Pipe Server calls

bool msgReceived(const char* const msg) noexcept override
{
if (NativePluginAndUiClass::msgReceived(msg))
return true;

if (std::strcmp(msg, "midi-clear-all") == 0)
{
fMidiOut.clear();
return true;
}

if (std::strcmp(msg, "midievent-add") == 0)
{
uint64_t time;
uint8_t size;

CARLA_SAFE_ASSERT_RETURN(readNextLineAsULong(time), true);
CARLA_SAFE_ASSERT_RETURN(readNextLineAsByte(size), true);

uint8_t data[size], dvalue;

for (uint8_t i=0; i<size; ++i)
{
CARLA_SAFE_ASSERT_RETURN(readNextLineAsByte(dvalue), true);
data[i] = dvalue;
}

fMidiOut.addRaw(time, data, size);

return true;
}

if (std::strcmp(msg, "midievent-remove") == 0)
{
uint64_t time;
uint8_t size;

CARLA_SAFE_ASSERT_RETURN(readNextLineAsULong(time), true);
CARLA_SAFE_ASSERT_RETURN(readNextLineAsByte(size), true);

uint8_t data[size], dvalue;

for (uint8_t i=0; i<size; ++i)
{
CARLA_SAFE_ASSERT_RETURN(readNextLineAsByte(dvalue), true);
data[i] = dvalue;
}

fMidiOut.removeRaw(time, data, size);

return true;
}

return false;
} }


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

private: private:
bool fWantInEvents; bool fWantInEvents;
bool fWasPlayingBefore;


struct InRtEvents { struct InRtEvents {
CarlaMutex mutex; CarlaMutex mutex;
RtList<RawMidiEvent>::Pool dataPool;
RtList<RawMidiEvent> data;
RtList<RawMidiEvent> dataPendingRT;
RtLinkedList<RawMidiEvent>::Pool dataPool;
RtLinkedList<RawMidiEvent> data;
RtLinkedList<RawMidiEvent> dataPendingRT;


InRtEvents()
: dataPool(MIN_PREALLOCATED_EVENT_COUNT, MAX_PREALLOCATED_EVENT_COUNT),
InRtEvents() noexcept
: mutex(),
dataPool(MIN_PREALLOCATED_EVENT_COUNT, MAX_PREALLOCATED_EVENT_COUNT),
data(dataPool), data(dataPool),
dataPendingRT(dataPool) {} dataPendingRT(dataPool) {}


~InRtEvents()
~InRtEvents() noexcept
{ {
clear(); clear();
} }


void appendRT(const RawMidiEvent& event)
void appendRT(const RawMidiEvent& event) noexcept
{ {
dataPendingRT.append(event); dataPendingRT.append(event);
} }


void clear()
void clear() noexcept
{ {
mutex.lock();
data.clear(); data.clear();
dataPendingRT.clear(); dataPendingRT.clear();
mutex.unlock();
} }


void splice()
void trySplice() noexcept
{ {
dataPendingRT.spliceAppend(data);
if (mutex.tryLock())
{
if (dataPendingRT.count() > 0)
dataPendingRT.moveTo(data, true);
mutex.unlock();
}
} }


CARLA_DECLARE_NON_COPY_STRUCT(InRtEvents);

} fInEvents; } fInEvents;


MidiPattern fMidiOut; MidiPattern fMidiOut;


void _sendEventsToUI() const noexcept
{
char strBuf[0xff+1];
strBuf[0xff] = '\0';

const CarlaMutexLocker cml1(getPipeLock());
const CarlaMutexLocker cml2(fMidiOut.getLock());

writeMessage("midi-clear-all\n", 16);

for (LinkedList<const RawMidiEvent*>::Itenerator it = fMidiOut.iteneratorBegin(); it.valid(); it.next())
{
const RawMidiEvent* const rawMidiEvent(it.getValue(nullptr));
CARLA_SAFE_ASSERT_CONTINUE(rawMidiEvent != nullptr);

writeMessage("midievent-add\n", 14);

std::snprintf(strBuf, 0xff, P_INT64 "\n", rawMidiEvent->time);
writeMessage(strBuf);

std::snprintf(strBuf, 0xff, "%i\n", rawMidiEvent->size);
writeMessage(strBuf);

for (uint8_t i=0, size=rawMidiEvent->size; i<size; ++i)
{
std::snprintf(strBuf, 0xff, "%i\n", rawMidiEvent->data[i]);
writeMessage(strBuf);
}
}
}

PluginClassEND(MidiSequencerPlugin) PluginClassEND(MidiSequencerPlugin)
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MidiSequencerPlugin) CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MidiSequencerPlugin)
}; };
@@ -236,8 +386,11 @@ private:


static const NativePluginDescriptor midisequencerDesc = { static const NativePluginDescriptor midisequencerDesc = {
/* category */ NATIVE_PLUGIN_CATEGORY_UTILITY, /* category */ NATIVE_PLUGIN_CATEGORY_UTILITY,
/* hints */ NATIVE_PLUGIN_IS_RTSAFE/*|NATIVE_PLUGIN_HAS_GUI*/,
/* supports */ static_cast<NativePluginSupports>(0x0),
/* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE
|NATIVE_PLUGIN_HAS_UI
|NATIVE_PLUGIN_USES_STATE
|NATIVE_PLUGIN_USES_TIME),
/* supports */ NATIVE_PLUGIN_SUPPORTS_EVERYTHING,
/* audioIns */ 0, /* audioIns */ 0,
/* audioOuts */ 0, /* audioOuts */ 0,
/* midiIns */ 1, /* midiIns */ 1,
@@ -246,7 +399,7 @@ static const NativePluginDescriptor midisequencerDesc = {
/* paramOuts */ 0, /* paramOuts */ 0,
/* name */ "MIDI Sequencer", /* name */ "MIDI Sequencer",
/* label */ "midisequencer", /* label */ "midisequencer",
/* maker */ "falkTX",
/* maker */ "falkTX, tatch",
/* copyright */ "GNU GPL v2+", /* copyright */ "GNU GPL v2+",
PluginDescriptorFILL(MidiSequencerPlugin) PluginDescriptorFILL(MidiSequencerPlugin)
}; };


Loading…
Cancel
Save