20#define __STDC_LIMIT_MACROS
24#include <libremidi/libremidi.hpp>
25#include <libremidi/reader.hpp>
28#include <condition_variable>
32static libremidi::midi_in midiin;
33static libremidi::midi_out midiout;
36 void midiin_C_callback(
const libremidi::message * msg);
38void midiin_callback(libremidi::message& msg)
40 midiin_C_callback(&msg);
42void set_midiin_callback() {
43 std::cout <<
"setting input callback" << std::endl;
45 [](
const libremidi::message& message)
62 midiin_C_callback(&message);
84 std::lock_guard<std::mutex> lock(m);
89 if (q.empty())
return true;
96 std::unique_lock<std::mutex> lock(m);
110 mutable std::mutex m;
111 std::condition_variable c;
121#define GLDOUBLE double
128#include "../lib/vrml_parser/Structs.h"
130typedef unsigned short ushort;
131void midiump_packet2values(
double packet, ubyte* channel, ubyte*
command, ubyte* note, ushort* velocity);
134typedef struct MidiNode {
139 std::list<MidiNode*> outputs;
140 void (*takemessage)(MidiNode*,
const struct libremidi::message *);
141 void (*takepacket)(MidiNode*, timedpacket packet);
142 libremidi::reader* reader;
146 int instrument, last_instrument;
147 double delay,starttime,lasttime;
154 std::map<int, MidiNode*> nodes;
155 std::map<int, int> nodetype;
157static int next_midi_context = 0;
158static std::map<int, struct mcstruct*> midi_contexts;
168int libmidi_createContext0() {
172 if (next_midi_context == 0) {
175 struct mcstruct *ac =
new mcstruct();
177 midi_contexts[next_midi_context] = ac;
181 return next_midi_context;
203uint32_t power_of_2(uint8_t exp)
208uint32_t scaleUp(uint32_t srcVal, uint8_t srcBits, uint8_t dstBits)
210 uint8_t scaleBits = (dstBits - srcBits);
211 uint32_t srcCenter = power_of_2(srcBits - 1);
215 uint32_t bitShiftedValue = srcVal << scaleBits;
216 if (srcVal <= srcCenter) {
217 return bitShiftedValue;
220 uint8_t repeatBits = srcBits - 1;
221 uint32_t repeatMask = power_of_2(repeatBits) - 1;
222 uint32_t repeatValue = srcVal & repeatMask;
223 if (scaleBits > repeatBits) {
224 repeatValue <<= (scaleBits - repeatBits);
227 repeatValue >>= (repeatBits - scaleBits);
229 while (repeatValue != 0) {
230 bitShiftedValue |= repeatValue;
231 repeatValue >>= repeatBits;
233 return bitShiftedValue;
236uint16_t scaleUp7to16(uint8_t value7) {
237 uint16_t bitShiftedValue = (uint16_t)value7 << 9;
239 return bitShiftedValue;
242 uint16_t repeatValue6 = (uint16_t)value7 & 0x3F;
243 return bitShiftedValue
244 | (repeatValue6 << 3)
245 | (repeatValue6 >> 3);
253int msg2ump(
int nbytes,
const unsigned char* bytes,
double* packets,
int fixvelocity) {
259 printf(
"in msg2ump\n");
263 ubyte channel, note,
command, velocity7;
264 channel = (bytes[0] & 0xF);
267 velocity7 = bytes[2];
271 ump.bytes[1] = bytes[0];
272 ump.bytes[2] = bytes[1];
276 ump.bytes[1] = channel | NOTE_OFF;
278 if (fixvelocity && velocity7 < 64) velocity7 = 63;
279 ump.u16[2] = scaleUp7to16(bytes[2]);
282 packets[npacket] = ump.packet;
286 if (
command == POLY_PRESSURE) {
287 ump.bytes[1] = bytes[0];
288 ump.bytes[2] = bytes[1];
289 ump.u32[1] = scaleUp(bytes[2], 7, 32);
290 packets[npacket] = ump.packet;
294 if (
command == CONTROL_CHANGE) {
295 ump.bytes[1] = bytes[0];
296 ump.bytes[2] = bytes[1];
297 ump.u32[1] = scaleUp(bytes[2], 7, 32);
298 packets[npacket] = ump.packet;
302 if (nbytes > 3 && bytes[2] > 0 && bytes[2] < 32 && bytes[3] > 0 && bytes[3] < 64) {
304 ump.bytes[1] = bytes[0];
305 ump.bytes[2] = bytes[1];
306 ump.u32[1] = scaleUp(bytes[3], 7, 32);
307 packets[npacket] = ump.packet;
312 if (
command == PROGRAM_CHANGE) {
313 ump.bytes[1] = bytes[0];
314 ump.bytes[4] = bytes[1];
315 static ubyte bankselect_msb = 0, bankselect_lsb = 0;
316 if (bankselect_msb && bankselect_lsb) {
317 ump.bytes[6] = bankselect_msb;
318 ump.bytes[7] = bankselect_lsb;
320 packets[npacket] = ump.packet;
325 if (
command == CHANNEL_PRESSURE) {
326 ump.bytes[1] = bytes[0];
327 ump.u32[1] = scaleUp(bytes[1], 7, 32);
328 packets[npacket] = ump.packet;
333 ump.bytes[1] = bytes[0];
334 ushort pitchbend = bytes[1] | (bytes[2] << 7);
335 ump.u32[1] = scaleUp(pitchbend, 14, 32);
336 packets[npacket] = ump.packet;
340 if (
command == SYSTEM_EXCLUSIVE) {
341 int mbytes = channel;
342 ump.bytes[1] = bytes[0];
346 for (
int i = 0; i < mbytes; i++) {
347 if (!(bytes[i + 1] == 0xF0 || bytes[i + 1] == 0xF7)) {
348 ump.bytes[2 + j] = bytes[1 + i];
359 packets[npacket] = ump.packet;
363 packets[0] = ump.packet;
367uint32_t scaleDown(uint32_t srcVal, uint8_t srcBits, uint8_t dstBits) {
369 uint8_t scaleBits = (srcBits - dstBits);
370 return srcVal >> scaleBits;
373int ump2msg(
double packet, ubyte **msg,
int *nbytes, ubyte* bytearray) {
381 printf(
"in ump2msg\n");
382 ubyte
command, channel, note, mt, group, * bytes;
388 midiump_packet2values(packet, &channel, &
command, ¬e, &velocity);
390 printf(
"ump2msg chan %d com %d note %d vel %d\n", channel,
command, note, velocity);
391 mt = ump.bytes[0] >> 4;
392 group = ump.bytes[0] & (0xF >> 4);
397 static ubyte cumbytes[100];
400 if (ncum == 0 ||
command == 0x10) {
402 cumbytes[0] = SYSTEM_EXCLUSIVE;
405 for (
int i = 0; i < channel; i++) {
406 cumbytes[ncum] = ump.bytes[i + 2];
411 cumbytes[ncum] = EOX;
413 memcpy(bytes, cumbytes, ncum);
430 bytes[0] =
command | channel | 1 << 7;
431 bytes[1] = ump.bytes[2];
432 bytes[2] = (ubyte)scaleDown(ump.u16[2], 16, 7);
433 if (
command == NOTE_ON && bytes[2] == 0) bytes[2] = 0x01;
441 case CHANNEL_PRESSURE:
444 bytes[0] =
command | channel | 1 << 7;
445 bytes[1] = (ubyte)scaleDown(ump.bytes[4], 8, 7);
456 if (ump.bytes[3] & 1) {
459 bytes[0] =
command | channel | 1 << 7;
460 bytes[2] = ump.bytes[6] & (0xF >> 1);
467 bytes[0] =
command | channel | 1 << 7;
468 bytes[2] = ump.bytes[7] & (0xF >> 1);
477 bytes[0] = ump.bytes[1];
478 bytes[1] = ump.bytes[4];
489 bytes[0] =
command | channel | 1 << 7;
490 bytes[1] = (ubyte)scaleDown(ump.bytes[5], 8, 6) | ((ump.bytes[4] & 1) << 6);
491 bytes[2] = (ubyte)scaleDown(ump.bytes[4], 8, 7);
506void midifilesourcefunction(MidiNode* mnode) {
508 libremidi::reader* r = mnode->reader;
510 printf(
"ticks per beat %f\n", r->ticksPerBeat);
512 for (
const auto& track : r->tracks)
515 std::cout <<
"\nNew track\n\n";
516 for (
const libremidi::track_event& event : track)
518 while (mnode->run != TRUE) std::this_thread::sleep_for(std::chrono::milliseconds(50));
519 std::cout <<
"Event at " <<
event.tick <<
" : ";
522 int elapsed_ticks =
event.tick - last_tick;
523 float beats_per_second = 2.0f;
524 float elapsed_seconds = ((float)elapsed_ticks / (r->ticksPerBeat * beats_per_second));
525 int elapsed_msec = (int)(elapsed_seconds * 1000.0f);
526 std::this_thread::sleep_for(std::chrono::milliseconds(elapsed_msec));
527 last_tick =
event.tick;
529 if (event.m.is_meta_event())
531 std::cout <<
"Meta event";
535 libremidi::message msg =
event.m;
538 if(MIDITransport() == 2)
539 npackets = msg2ump(msg.bytes.size(), msg.bytes.data(), packets,FALSE);
541 std::wcout <<
"outputs.count" << mnode->outputs.size() << std::endl;
542 for (std::list<MidiNode*>::iterator it = mnode->outputs.begin(); it != mnode->outputs.end(); ++it)
544 MidiNode* mout = *it;
546 if (MIDITransport() == MIDI_UMP) {
548 for (
int j = 0; j < npackets; j++) {
550 tpacket.packet = packets[j];
551 tpacket.timestamp = msg.timestamp;
552 if (mout->takepacket) mout->takepacket(mout, tpacket);
557 if (mout->takemessage) mout->takemessage(mout, &msg);
560 if (0)
switch (event.m.get_message_type())
562 case libremidi::message_type::NOTE_ON:
563 std::cout <<
"Note ON: "
564 <<
"channel " <<
event.m.get_channel() <<
' '
565 <<
"note " << (int)event.m.bytes[1] <<
' '
566 <<
"velocity " << (
int)
event.m.bytes[2] <<
' ';
568 case libremidi::message_type::NOTE_OFF:
569 std::cout <<
"Note OFF: "
570 <<
"channel " <<
event.m.get_channel() <<
' '
571 <<
"note " << (int)event.m.bytes[1] <<
' '
572 <<
"velocity " << (
int)
event.m.bytes[2] <<
' ';
574 case libremidi::message_type::CONTROL_CHANGE:
575 std::cout <<
"Control: "
576 <<
"channel " <<
event.m.get_channel() <<
' '
577 <<
"control " << (int)event.m.bytes[1] <<
' '
578 <<
"value " << (
int)
event.m.bytes[2] <<
' ';
580 case libremidi::message_type::PROGRAM_CHANGE:
581 std::cout <<
"Program: "
582 <<
"channel " <<
event.m.get_channel() <<
' '
583 <<
"program " << (int)event.m.bytes[1] <<
' ';
585 case libremidi::message_type::AFTERTOUCH:
586 std::cout <<
"Aftertouch: "
587 <<
"channel " <<
event.m.get_channel() <<
' '
588 <<
"value " << (int)event.m.bytes[1] <<
' ';
590 case libremidi::message_type::POLY_PRESSURE:
591 std::cout <<
"Poly pressure: "
592 <<
"channel " <<
event.m.get_channel() <<
' '
593 <<
"note " << (int)event.m.bytes[1] <<
' '
594 <<
"value " << (
int)
event.m.bytes[2] <<
' ';
596 case libremidi::message_type::PITCH_BEND:
597 std::cout <<
"Poly pressure: "
598 <<
"channel " <<
event.m.get_channel() <<
' '
599 <<
"bend " << (int)(event.m.bytes[1] << 7 + event.m.bytes[2]) <<
' ';
602 std::cout <<
"Unsupported.";
609 std::cout <<
"end of tracks" << std::endl;
610 }
while (mnode->loop == TRUE);
611 std::cout <<
"bye bye" << std::endl;
613void midiPortDestination_takemessage(MidiNode* midiNode,
const struct libremidi::message* msg) {
614 const struct libremidi::message& m = *msg;
615 std::vector<unsigned char> messout(m.size());
616 auto nBytes = m.size();
618 for (
auto i = 0U; i < nBytes; i++)
619 std::cout <<
"Byte " << i <<
" = " << (
int)m[i] <<
", ";
621 std::cout <<
"stamp = " << m.timestamp << std::endl;
625 if (messout[2] > 0 && messout[2] < 64)
627 libremidi::message mout = libremidi::message(messout,m.timestamp);
628 midiout.send_message(mout);
631void midiPortDestination_takepacket(MidiNode* midiNode,
timedpacket tpacket) {
633 ubyte bytearray[200];
636 double packet = tpacket.packet;
637 int nmsg = ump2msg(packet, msgs, nbytes, bytearray);
638 for(
int j=0;j<nmsg;j++) {
639 ubyte* bytes = msgs[j];
640 int nbyte = nbytes[j];
641 std::vector<unsigned char> messout(nbyte);
642 for (
int i = 0; i < nbyte; i++)
643 messout[i] = bytes[i];
644 libremidi::message mout = libremidi::message(messout, tpacket.timestamp);
645 midiout.send_message(mout);
648void midiPrintDestination_takemessage(MidiNode* midiNode,
const struct libremidi::message * msg) {
649 const struct libremidi::message& m = *msg;
650 printf(
"in midiPrintDestination_takemessage\n");
651 switch (m.get_message_type())
653 case libremidi::message_type::NOTE_ON:
654 std::cout <<
"Note ON: "
655 <<
"channel " << m.get_channel() <<
' '
656 <<
"note " << (int)m.bytes[1] <<
' '
657 <<
"velocity " << (
int)m.bytes[2] <<
' ';
659 case libremidi::message_type::NOTE_OFF:
660 std::cout <<
"Note OFF: "
661 <<
"channel " << m.get_channel() <<
' '
662 <<
"note " << (int)m.bytes[1] <<
' '
663 <<
"velocity " << (
int)m.bytes[2] <<
' ';
665 case libremidi::message_type::CONTROL_CHANGE:
666 std::cout <<
"Control: "
667 <<
"channel " << m.get_channel() <<
' '
668 <<
"control " << (int)m.bytes[1] <<
' '
669 <<
"value " << (
int)m.bytes[2] <<
' ';
671 case libremidi::message_type::PROGRAM_CHANGE:
672 std::cout <<
"Program: "
673 <<
"channel " << m.get_channel() <<
' '
674 <<
"program " << (int)m.bytes[1] <<
' ';
676 case libremidi::message_type::AFTERTOUCH:
677 std::cout <<
"Aftertouch: "
678 <<
"channel " << m.get_channel() <<
' '
679 <<
"value " << (int)m.bytes[1] <<
' ';
681 case libremidi::message_type::POLY_PRESSURE:
682 std::cout <<
"Poly pressure: "
683 <<
"channel " << m.get_channel() <<
' '
684 <<
"note " << (int)m.bytes[1] <<
' '
685 <<
"value " << (
int)m.bytes[2] <<
' ';
687 case libremidi::message_type::PITCH_BEND:
688 std::cout <<
"Poly pressure: "
689 <<
"channel " << m.get_channel() <<
' '
690 <<
"bend " << (int)(m.bytes[1] << 7 + m.bytes[2]) <<
' ';
693 std::cout <<
"Unsupported.";
697 std::cout <<
" PrintDest\n";
700void midiPrintDestination_takepacket(MidiNode* midiNode,
timedpacket tpacket) {
701 ubyte bytearray[200];
704 double packet = tpacket.packet;
705 printf(
"in midiPrintDestination_takepacket\n");
706 int nmsg = ump2msg(packet, msgs, nbytes, bytearray);
707 for(
int j=0;j<nmsg;j++) {
708 ubyte *bytes = msgs[j];
709 int nbyte = nbytes[j];
710 std::vector<unsigned char> messout(nbyte);
711 for (
int i = 0; i < nbyte; i++)
712 messout[i] = bytes[i];
713 libremidi::message mout = libremidi::message(messout, tpacket.timestamp);
714 midiPrintDestination_takemessage(midiNode, &mout);
717void midiOut_takemessage(MidiNode* midiNode,
const struct libremidi::message* msg) {
718 const struct libremidi::message& m = *msg;
719 if (!midiNode->queue)
720 midiNode->queue = (
void*)
new SafeQueue<const struct libremidi::message*>();
721 SafeQueue<const struct libremidi::message*> *que = (SafeQueue<const struct libremidi::message*>*)midiNode->queue;
722 std::cout <<
"enqueuing one" << std::endl;
723 que->enqueue(
new libremidi::message(*msg));
724 std::cout <<
"enqueued one" << std::endl;
750void midiOut_takepacket(MidiNode* midiNode,
timedpacket tpacket) {
751 if (!midiNode->queue)
752 midiNode->queue = (
void*)
new SafeQueue<timedpacket>();
753 SafeQueue<timedpacket>* que = (SafeQueue<timedpacket>*)midiNode->queue;
754 std::cout <<
"enqueuing one" << std::endl;
755 que->enqueue(tpacket);
756 std::cout <<
"enqueued one" << std::endl;
759void midiProgram_takemessage(MidiNode* mnode,
const struct libremidi::message* msg) {
760 struct libremidi::message m = libremidi::message(*msg);
761 if (msg->get_message_type() == libremidi::message_type::PROGRAM_CHANGE) {
762 std::vector<unsigned char> mess(msg->size());
763 mess[0] = msg->bytes[0];
764 mess[1] = mnode->instrument - 1;
765 m = libremidi::message(mess, msg->timestamp);
766 mnode->last_instrument = mnode->instrument;
768 else if (mnode->instrument != mnode->last_instrument) {
773 channel = (msg->bytes[0] & 0xF);
775 std::vector<unsigned char> mess(2);
777 mess[1] = mnode->instrument - 1;
778 mnode->last_instrument = mnode->instrument;
779 struct libremidi::message mi = libremidi::message(mess, msg->timestamp);
780 for (std::list<MidiNode*>::iterator it = mnode->outputs.begin(); it != mnode->outputs.end(); ++it)
782 MidiNode* mout = *it;
783 if (mout->takemessage) mout->takemessage(mout, &mi);
787 for (std::list<MidiNode*>::iterator it = mnode->outputs.begin(); it != mnode->outputs.end(); ++it)
789 MidiNode* mout = *it;
790 if (mout->takemessage) mout->takemessage(mout, &m);
794void midiProgram_takepacket(MidiNode* mnode,
timedpacket tpacket) {
797 midiump_packet2values(tpacket.packet, &channel, &
command, ¬e, &velocity);
798 if (
command == PROGRAM_CHANGE) {
800 UMP* ump = (
UMP*)&tpacket.packet;
801 ump->bytes[4] = mnode->instrument -1;
802 mnode->last_instrument = mnode->instrument;
804 else if (mnode->instrument != mnode->last_instrument) {
811 ump.bytes[1] =
command | (channel-1);
812 ump.bytes[4] = mnode->instrument-1;
813 mnode->last_instrument = mnode->instrument;
815 tp.packet = ump.packet;
816 tp.timestamp = tpacket.timestamp;
817 for (std::list<MidiNode*>::iterator it = mnode->outputs.begin(); it != mnode->outputs.end(); ++it)
819 MidiNode* mout = *it;
821 if (mout->takepacket) mout->takepacket(mout, tp);
825 for (std::list<MidiNode*>::iterator it = mnode->outputs.begin(); it != mnode->outputs.end(); ++it)
827 MidiNode* mout = *it;
829 if (mout->takepacket) mout->takepacket(mout, tpacket);
834void midiDelay_takemessage(MidiNode* mnode,
const struct libremidi::message* msg) {
835 struct libremidi::message m = *msg;
837 mnode->queue = (
void*)
new SafeQueue<const struct libremidi::message*>();
838 SafeQueue<const struct libremidi::message*>* que = (SafeQueue<const struct libremidi::message*>*)mnode->queue;
839 std::cout <<
"enqueuing one" << std::endl;
840 m.timestamp = Time1970sec();
841 que->enqueue(
new libremidi::message(m));
842 std::cout <<
"enqueued one" << std::endl;
845void midiDelay_takepacket(MidiNode* mnode,
timedpacket tpacket) {
847 mnode->queue = (
void*)
new SafeQueue<timedpacket>();
848 SafeQueue<timedpacket>* que = (SafeQueue<timedpacket>*)mnode->queue;
849 std::cout <<
"enqueuing one" << std::endl;
850 tpacket.timestamp = Time1970sec();
851 que->enqueue(tpacket);
852 std::cout <<
"enqueued one" << std::endl;
856void mididelayfunctionMSG(MidiNode* mnode) {
857 double now, diff, diff1, diff2;
859 mnode->queue = (
void*)
new SafeQueue<const struct libremidi::message*>();
860 SafeQueue<const struct libremidi::message*>* que = (SafeQueue<const struct libremidi::message*>*)mnode->queue;
863 mnode->starttime = Time1970sec();
864 mnode->lasttime = 0.0;
866 while (que->empty()) std::this_thread::sleep_for(std::chrono::milliseconds(50));
867 libremidi::message msg = *(que->dequeue());
869 diff1 = (now - mnode->starttime);
870 diff2 = (msg.timestamp + mnode->delay - mnode->starttime);
871 diff = diff2 - diff1;
874 std::this_thread::sleep_for(std::chrono::milliseconds((
long long)(diff * 1000.0)));
875 msg.timestamp = Time1970sec() - mnode->lasttime;
876 mnode->lasttime = msg.timestamp;
877 for (std::list<MidiNode*>::iterator it = mnode->outputs.begin(); it != mnode->outputs.end(); ++it)
879 MidiNode* mout = *it;
881 if (mout->takepacket) mout->takemessage(mout, &msg);
884 std::cout <<
"bye bye" << std::endl;
887void mididelayfunctionUMP(MidiNode* mnode) {
888 double now, diff, diff1, diff2;
890 mnode->queue = (
void*)
new SafeQueue<timedpacket>();
891 SafeQueue<timedpacket>* que = (SafeQueue<timedpacket>*)mnode->queue;
894 mnode->starttime = Time1970sec();
895 mnode->lasttime = 0.0;
897 while (que->empty()) std::this_thread::sleep_for(std::chrono::milliseconds(50));
900 diff1 = (now - mnode->starttime);
901 diff2 = (tpacket.timestamp + mnode->delay - mnode->starttime);
902 diff = diff2 - diff1;
905 std::this_thread::sleep_for(std::chrono::milliseconds((
long long) ( diff * 1000.0)));
906 tpacket.timestamp = Time1970sec() - mnode->lasttime;
907 mnode->lasttime = tpacket.timestamp;
908 for (std::list<MidiNode*>::iterator it = mnode->outputs.begin(); it != mnode->outputs.end(); ++it)
910 MidiNode* mout = *it;
912 if (mout->takepacket) mout->takepacket(mout, tpacket);
915 std::cout <<
"bye bye" << std::endl;
918void mididelayfunction(MidiNode* mnode) {
919 if (MIDITransport() == MIDI_MSG)
920 mididelayfunctionMSG(mnode);
921 else if (MIDITransport() == MIDI_UMP)
922 mididelayfunctionUMP(mnode);
927void midimsg_uint2values(
unsigned int msg, ubyte* channel, ubyte*
command, ubyte* note, ubyte* velocity);
928unsigned int midimsg_values2uint(ubyte channel, ubyte
command, ubyte note, ubyte velocity);
929void midiump_packet2values(
double packet, ubyte* channel, ubyte*
command, ubyte* note, ushort* velocity);
930double midiump_values2packet(ubyte channel, ubyte
command, ubyte note, ushort velocity);
932void mark_event(
struct X3D_Node* from,
int totalptr);
934void midiOut_message2fields(MidiNode* midiNode,
struct X3D_MIDIOut* node) {
936 struct X3D_Node* anode = X3D_NODE(node);
937 const struct libremidi::message *msg;
938 if (!midiNode->queue)
939 midiNode->queue = (
void*)
new SafeQueue<const struct libremidi::message*>();
940 SafeQueue<const struct libremidi::message*>* que = (SafeQueue<const struct libremidi::message*>*)midiNode->queue;
942 unsigned int cur[1000], n = 0;
947 while (!que->empty()) {
948 msg = que->dequeue();
949 std::cout <<
"dequed one" << std::endl;
951 const struct libremidi::message& m = *msg;
952 switch (m.get_message_type())
954 case libremidi::message_type::NOTE_ON:
955 std::cout <<
"Note ON: "
956 <<
"channel " << m.get_channel() <<
' '
957 <<
"note " << (int)m.bytes[1] <<
' '
958 <<
"velocity " << (
int)m.bytes[2] <<
' ';
960 cur[n] = midimsg_values2uint(m.get_channel(), (ubyte)m.get_message_type(), m.bytes[1], m.bytes[2]);
963 case libremidi::message_type::NOTE_OFF:
964 std::cout <<
"Note OFF: "
965 <<
"channel " << m.get_channel() <<
' '
966 <<
"note " << (int)m.bytes[1] <<
' '
967 <<
"velocity " << (
int)m.bytes[2] <<
' ';
969 cur[n] = midimsg_values2uint(m.get_channel(), (ubyte)m.get_message_type(), m.bytes[1], m.bytes[2]);
972 case libremidi::message_type::CONTROL_CHANGE:
973 std::cout <<
"Control: "
974 <<
"channel " << m.get_channel() <<
' '
975 <<
"control " << (int)m.bytes[1] <<
' '
976 <<
"value " << (
int)m.bytes[2] <<
' ';
980 cur[n] = midimsg_values2uint(m.get_channel(), (ubyte)m.get_message_type(), m.bytes[1], m.bytes[2]);
992 node->midiMsg.p = (
int *)realloc(node->midiMsg.p, n *
sizeof(
int));
993 memcpy(node->midiMsg.p, cur, n *
sizeof(
int));
995 MARK_EVENT(anode, offsetof(
struct X3D_MIDIOut, midiMsg));
1004void midiOut_packet2fields(MidiNode* midiNode,
struct X3D_MIDIOut* node) {
1006 struct X3D_Node* anode = X3D_NODE(node);
1007 if (!midiNode->queue)
1008 midiNode->queue = (
void*)
new SafeQueue<timedpacket>();
1009 SafeQueue<timedpacket>* que = (SafeQueue<timedpacket>*)midiNode->queue;
1017 while (!que->empty()) {
1018 tpacket = que->dequeue();
1019 ump.packet = tpacket.packet;
1023 midiump_packet2values(ump.packet, &channel, &
command, ¬e, &velocity);
1024 printf(
"chan %d comm %d note %d vel %d", channel,
command, note, velocity);
1026 std::cout <<
"dequed one in midiOut_packet2fields" << std::endl;
1028 cur[n] = ump.packet;
1029 n = n >= 999 ? 999 : n + 1;
1032 node->midiUmp.p = (
double*)realloc(node->midiUmp.p, n *
sizeof(
double));
1033 memcpy(node->midiUmp.p, cur, n *
sizeof(
double));
1034 node->midiUmp.n = n;
1035 MARK_EVENT(anode, offsetof(
struct X3D_MIDIOut, midiUmp));
1038 node->midiUmp.n = 0;
1044void midiin_midinote2messages(MidiNode* mnode,
struct X3D_MIDIIn* pnode) {
1045 static double lasttime = 0.0;
1046 if (lasttime == 0.0) lasttime = TickTime();
1047 for (
int i = 0; i < pnode->midiMsg.n; i++) {
1049 ubyte channel,
command, note, velocity;
1050 midimsg_uint2values(pnode->midiMsg.p[i], &channel, &
command, ¬e, &velocity);
1057 double now = TickTime();
1058 double timestamp = now - lasttime;
1060 libremidi::message msg;
1061 std::vector<unsigned char> messout(3);
1062 messout[0] =
command | channel;
1064 messout[2] = velocity;
1065 msg = libremidi::message(messout, timestamp);
1066 printf(
"MI %d %d %d %lf", messout[0], messout[1], messout[2], timestamp);
1067 for (std::list<MidiNode*>::iterator it = mnode->outputs.begin(); it != mnode->outputs.end(); ++it)
1069 MidiNode* mout = *it;
1071 if (mout->takemessage) mout->takemessage(mout, &msg);
1075 pnode->midiMsg.n = 0;
1077void midiin_midinote2packets(MidiNode* mnode,
struct X3D_MIDIIn* pnode) {
1078 static double lasttime = 0.0;
1079 if (lasttime == 0.0) lasttime = TickTime();
1080 for (
int i = 0; i < pnode->midiUmp.n; i++) {
1081 double packet = pnode->midiUmp.p[i];
1082 double now = TickTime();
1083 double timestamp = now - lasttime;
1086 tpacket.packet = packet;
1090 midiump_packet2values(packet, &channel, &
command, ¬e, &velocity);
1091 printf(
"midiin_midinote2packets chan %d comm %d not %d vel %d\n", channel,
command, note, velocity);
1093 tpacket.timestamp = timestamp;
1094 for (std::list<MidiNode*>::iterator it = mnode->outputs.begin(); it != mnode->outputs.end(); ++it)
1096 MidiNode* mout = *it;
1097 if (mout->takepacket) mout->takepacket(mout, tpacket);
1100 pnode->midiMsg.n = 0;
1104static int ports_printed = FALSE;
1107 midiout.close_port();
1108 midiin.close_port();
1109 printf(
"MIDI Output ports:\n");
1110 std::string portName;
1111 unsigned int i = 0, nPorts = midiout.get_port_count();
1113 std::cout <<
"No ports available!" << std::endl;
1115 for (i = 0; i < nPorts; i++)
1117 portName = midiout.get_port_name(i);
1118 std::cout <<
" port #" << i <<
": " << portName <<
'\n';
1120 printf(
"MIDI Input ports:\n");
1121 i = 0, nPorts = midiin.get_port_count();
1123 std::cout <<
"No ports available!" << std::endl;
1125 for (i = 0; i < nPorts; i++)
1127 portName = midiin.get_port_name(i);
1128 std::cout <<
" port #" << i <<
": " << portName <<
'\n';
1131 ports_printed = TRUE;
1133MidiNode* midiin_node = NULL;
1135void midiin_C_callback(
const libremidi::message* msg){
1137 const struct libremidi::message& messin = *msg;
1139 MidiNode* mnode = midiin_node;
1140 auto nBytes = messin.size();
1141 if (MIDITransport() == MIDI_UMP) {
1143 double packets[100];
1144 const libremidi::midi_bytes bytes[200];
1145 double npacket = msg2ump(nBytes, messin.bytes.data(), packets, TRUE);
1147 for (std::list<MidiNode*>::iterator it = mnode->outputs.begin(); it != mnode->outputs.end(); ++it)
1149 MidiNode* mout = *it;
1150 if (mout->takepacket)
1151 for (
int i = 0; i < npacket; i++) {
1153 tpacket.packet = packets[i];
1154 tpacket.timestamp = messin.timestamp;
1155 mout->takepacket(mout, tpacket);
1160 else if(MIDITransport() == MIDI_MSG) {
1162 std::vector<unsigned char> messout(messin.size());
1165 for (
auto i = 0U; i < nBytes; i++)
1166 std::cout <<
"Byte " << i <<
" = " << (
int)messin[i] <<
", ";
1168 std::cout <<
"stamp = " << messin.timestamp << std::endl;
1169 messout[0] = messin[0];
1170 messout[1] = messin[1];
1171 messout[2] = messin[2];
1172 if (messout[2] > 0 && messout[2] < 64)
1174 libremidi::message msgo = libremidi::message(messout, messin.timestamp);
1176 for (std::list<MidiNode*>::iterator it = mnode->outputs.begin(); it != mnode->outputs.end(); ++it)
1178 MidiNode* mout = *it;
1180 if (mout->takemessage) mout->takemessage(mout, &msgo);
1186void libmidi_updateNode3(
int icontext,
icset connect_parent,
struct X3D_Node* node) {
1188 struct mcstruct* ac = midi_contexts[icontext];
1191 if (!ports_printed) print_ports();
1192 switch (node->_nodeType) {
1193 case NODE_MIDIPortSource:
1197 if (!srepn->inode) {
1198 input =
new MidiNode();
1200 input->numberOfOutputs = 0;
1201 input->numberOfInputs = 1;
1202 input->takemessage = NULL;
1203 midiin_node = input;
1204 midiin.open_port(pnode->port,
"libremidi Input");
1206 printf(
"opened source port %d\n", pnode->port);
1207 printf(
"have a MIDIPortSource node, handling it'n");
1208 set_midiin_callback();
1230 midiin.ignore_types(
false,
false,
false);
1233 ac->nodes[ac->next_node] = input;
1234 ac->nodetype[ac->next_node] = NODE_MIDIPortSource;
1235 srepn->inode = ac->next_node;
1236 srepn->icontext = icontext;
1241 case NODE_MIDIPortDestination:
1245 if (!srepn->inode) {
1246 input =
new MidiNode();
1248 input->numberOfOutputs = 0;
1249 input->numberOfInputs = 1;
1250 input->takemessage = midiPortDestination_takemessage;
1251 input->takepacket = midiPortDestination_takepacket;
1252 midiout.open_port(pnode->port,
"libremidi Output");
1253 printf(
"opened destination port %d\n", pnode->port);
1258 ac->nodes[ac->next_node] = input;
1259 ac->nodetype[ac->next_node] = NODE_MIDIPortDestination;
1260 srepn->inode = ac->next_node;
1261 srepn->icontext = icontext;
1267 case NODE_MIDIFileSource:
1271 if (!srepn->inode) {
1272 input =
new MidiNode();
1274 input->numberOfOutputs = 1;
1275 input->numberOfInputs = 0;
1276 input->takemessage = NULL;
1277 input->loop = FALSE;
1280 libremidi::reader *midireader =
new libremidi::reader(
true);
1283 libremidi::reader::parse_result result = midireader->parse((uint8_t*)pnode->__blob.p,pnode->__blob.n);
1284 printf(
"updateNod3 for FileSource");
1286 if (result != libremidi::reader::invalid) {
1287 input->reader = midireader;
1288 printf(
"starting filesource thread\n");
1289 std::thread filesource(midifilesourcefunction, input);
1290 filesource.detach();
1299 ac->nodes[ac->next_node] = input;
1300 ac->nodetype[ac->next_node] = NODE_MIDIFileSource;
1301 srepn->inode = ac->next_node;
1302 srepn->icontext = icontext;
1307 input = ac->nodes[srepn->inode];
1314 case NODE_MIDIPrintDestination:
1318 if (!srepn->inode) {
1319 input =
new MidiNode();
1321 input->numberOfOutputs = 0;
1322 input->numberOfInputs = 1;
1323 input->takemessage = midiPrintDestination_takemessage;
1324 input->takepacket = midiPrintDestination_takepacket;
1326 ac->nodes[ac->next_node] = input;
1327 ac->nodetype[ac->next_node] = NODE_MIDIPrintDestination;
1328 srepn->inode = ac->next_node;
1329 srepn->icontext = icontext;
1338 if (!srepn->inode) {
1339 input =
new MidiNode();
1341 input->numberOfOutputs = 0;
1342 input->numberOfInputs = 1;
1343 input->takemessage = midiOut_takemessage;
1344 input->takepacket = midiOut_takepacket;
1347 ac->nodes[ac->next_node] = input;
1348 ac->nodetype[ac->next_node] = NODE_MIDIOut;
1349 srepn->inode = ac->next_node;
1350 srepn->icontext = icontext;
1353 input = ac->nodes[srepn->inode];
1355 if(MIDITransport() == MIDI_MSG)
1356 midiOut_message2fields(input, pnode);
1357 if (MIDITransport() == MIDI_UMP)
1358 midiOut_packet2fields(input, pnode);
1365 if (!srepn->inode) {
1366 input =
new MidiNode();
1368 input->numberOfOutputs = 1;
1369 input->numberOfInputs = 0;
1370 input->takemessage = NULL;
1371 input->takepacket = NULL;
1374 ac->nodes[ac->next_node] = input;
1375 ac->nodetype[ac->next_node] = NODE_MIDIIn;
1376 srepn->inode = ac->next_node;
1377 srepn->icontext = icontext;
1379 input = ac->nodes[srepn->inode];
1381 if(MIDITransport() == MIDI_MSG)
1382 midiin_midinote2messages(input, pnode);
1383 if (MIDITransport() == MIDI_UMP)
1384 midiin_midinote2packets(input, pnode);
1388 case NODE_MIDIProgram:
1392 if (!srepn->inode) {
1393 input =
new MidiNode();
1395 input->numberOfOutputs = 1;
1396 input->numberOfInputs = 1;
1397 input->takemessage = midiProgram_takemessage;
1398 input->takepacket = midiProgram_takepacket;
1399 input->last_instrument = 0;
1402 ac->nodes[ac->next_node] = input;
1403 ac->nodetype[ac->next_node] = NODE_MIDIProgram;
1404 srepn->inode = ac->next_node;
1405 srepn->icontext = icontext;
1407 input = ac->nodes[srepn->inode];
1408 input->instrument = pnode->instrument;
1409 input = ac->nodes[srepn->inode];
1413 case NODE_MIDIDelay:
1417 if (!srepn->inode) {
1418 input =
new MidiNode();
1420 input->numberOfOutputs = 1;
1421 input->numberOfInputs = 1;
1422 input->takemessage = midiDelay_takemessage;
1423 input->takepacket = midiDelay_takepacket;
1425 std::thread mididelay(mididelayfunction, input);
1429 ac->nodes[ac->next_node] = input;
1430 ac->nodetype[ac->next_node] = NODE_MIDIDelay;
1431 srepn->inode = ac->next_node;
1432 srepn->icontext = icontext;
1434 input = ac->nodes[srepn->inode];
1435 input->delay = pnode->delay;
1436 input = ac->nodes[srepn->inode];
1446void libmidi_pauseContext0(
int icontext) {}
1447void libmidi_resumeContext0(
int icontext) {}
1450static struct type_name {
1454{NODE_MIDIPortDestination,
"MPD"},
1455{NODE_MIDIPortSource,
"MPS"},
1456{NODE_MIDIFileDestination,
"MFD"},
1457{NODE_MIDIFileSource,
"MFS"},
1458{NODE_MIDIIn,
"MIn"},
1459{NODE_MIDIOut,
"MOut"},
1460{NODE_MIDIProgram,
"PRG"},
1461{NODE_MIDIDelay,
"DLY"},
1464static const char* nodetype_lookup(
int itype) {
1467 struct type_name* tn;
1471 tn = &type_names[i];
1472 if (tn->iname == itype) {
1477 }
while (tn->iname != 0);
1482struct midiconnection {
1491static std::list<midiconnection> midiconnections;
1492void context_disconnect(MidiNode* destination, MidiNode* source,
int indexDst,
int indexSrc) {
1493 source->outputs.remove(destination);
1496void context_connect(MidiNode* destination, MidiNode* source,
int indexDst,
int indexSrc) {
1497 source->outputs.push_back(destination);
1500void libmidi_connect2(
int icontext,
int idestination,
int isource,
int indexDst,
int indexSrc) {
1501 struct mcstruct* ac = midi_contexts[icontext];
1502 MidiNode* destination = ac->nodes[idestination];
1503 MidiNode* source = ac->nodes[isource];
1504 int dstInputs = destination->numberOfInputs;
1505 int srcOutputs = source->numberOfOutputs;
1506 if (indexDst > dstInputs) {
1507 printf(
"destination number of inputs %d destination idx %d\n", destination->numberOfInputs, indexDst);
1514 if (indexSrc > srcOutputs) {
1515 printf(
"source number of outputs %d source idx %d\n", srcOutputs, indexSrc);
1524 context_connect(destination, source, indexDst, indexSrc);
1525 int iparent_type = ac->nodetype[idestination];
1526 int ichild_type = ac->nodetype[isource];
1527 struct midiconnection cc; cc.icontext = icontext; cc.iparent = idestination; cc.iparent_type = iparent_type;
1528 cc.ichild = isource; cc.ichild_type = ichild_type; cc.srcindex = indexSrc; cc.dstindex = indexDst;
1529 midiconnections.push_back(cc);
1532void libmidi_disconnect2(
int icontext,
int idestination,
int isource,
int indexDst,
int indexSrc) {
1533 struct mcstruct* ac = midi_contexts[icontext];
1534 MidiNode* destination = ac->nodes[idestination];
1535 MidiNode* source = ac->nodes[isource];
1536 int dstInputs = destination->numberOfInputs;
1537 int srcOutputs = source->numberOfOutputs;
1538 if (indexDst > dstInputs) {
1539 printf(
"destination number of inputs %d destination idx %d\n", destination->numberOfInputs, indexDst);
1546 if (indexSrc > srcOutputs) {
1547 printf(
"source number of outputs %d source idx %d\n", srcOutputs, indexSrc);
1556 context_disconnect(destination, source, indexDst, indexSrc);
1559 int iparent_type = ac->nodetype[idestination];
1560 int ichild_type = ac->nodetype[isource];
1561 struct midiconnection cc; cc.icontext = icontext; cc.iparent = idestination; cc.iparent_type = iparent_type;
1562 cc.ichild = isource; cc.ichild_type = ichild_type; cc.srcindex = indexSrc; cc.dstindex = indexDst;
1564 std::list<midiconnection>::iterator it;
1565 for (it = midiconnections.begin(); it != midiconnections.end(); ++it) {
1566 midiconnection cn = *it;
1567 if (cn.icontext = cc.icontext && cn.iparent == cc.iparent && cn.ichild == cc.ichild
1568 && cn.srcindex == cc.srcindex && cn.dstindex == cc.dstindex) {
1569 midiconnections.erase(it);
1576void libmidi_connect(
int icontext,
icset iparent) {
1578 libmidi_connect2(icontext, iparent.p, iparent.n, iparent.d, iparent.s);
1580void libmidi_disconnect(
int icontext,
icset iparent) {
1581 libmidi_disconnect2(icontext, iparent.p, iparent.n, iparent.ld, iparent.ls);
1584void libmidi_print_connections() {
1586 printf(
"%2s %7s %4s %7s %7s %6s %4s\n",
"ic",
"iparent",
"type",
"dstIndx",
"srcIndex",
"ichild",
"type");
1589 std::list<midiconnection>::iterator it;
1590 for (it = midiconnections.begin(); it != midiconnections.end(); ++it) {
1591 midiconnection cc = *it;
1593 const char* ptype = nodetype_lookup(cc.iparent_type);
1594 const char* ctype = nodetype_lookup(cc.ichild_type);
1596 printf(
"%2d %7d %4s %7d %7d %6d %4s\n", cc.icontext, cc.iparent, ptype, cc.dstindex, cc.srcindex, cc.ichild, ctype);
1598 printf(
"count %d\n", (
int)midiconnections.size());