add „connect“ and „disconnect“ events + „source_port“ and „destination_port“ attributes to allow connecting and disconnecting arbitrary JACK ports v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Wed, 07 Oct 2020 23:10:28 +0200
branchv_0
changeset 24 427b8d799a4a
parent 23 d2ad84dcf249
child 25 e0627da77dad
add „connect“ and „disconnect“ events + „source_port“ and „destination_port“ attributes to allow connecting and disconnecting arbitrary JACK ports
src/JackHandler.h
--- a/src/JackHandler.h	Wed Oct 07 22:30:09 2020 +0200
+++ b/src/JackHandler.h	Wed Oct 07 23:10:28 2020 +0200
@@ -130,6 +130,8 @@
 				NOTE,
 				CONTROL,
 				SYSEX,
+				CONNECT,
+				DISCONNECT,
 				UNKNOWN
 			};
 
@@ -137,6 +139,8 @@
 				if (name == L"note") return Event::NOTE;
 				else if (name == L"control") return Event::CONTROL;
 				else if (name == L"sysex") return Event::SYSEX;
+				else if (name == L"connect") return Event::CONNECT;
+				else if (name == L"disconnect") return Event::DISCONNECT;
 				else return Event::UNKNOWN;
 			}
 
@@ -148,6 +152,8 @@
 			relpipe::common::type::Integer controllerId;
 			relpipe::common::type::Integer controllerValue;
 			relpipe::common::type::StringX raw;
+			relpipe::common::type::StringX connectionSourcePort;
+			relpipe::common::type::StringX connectionDestinationPort;
 
 			size_t attributeIndex = 0;
 
@@ -225,9 +231,9 @@
 
 		// TODO: configurable relation name
 
-		if (!relationContext.hasAttribute(L"raw")) {
+		if (!relationContext.hasAttribute(L"event")) {
 			relationContext.skip = true;
-			fwprintf(stderr, L"Relation „%ls“ will be ignored because mandatory attribute „raw“ is missing.\n", name.c_str());
+			fwprintf(stderr, L"Relation „%ls“ will be ignored because mandatory attribute „event“ is missing.\n", name.c_str());
 		}
 
 	}
@@ -249,6 +255,8 @@
 		else if (attributeName == L"note_pitch") rec.notePitch = std::stoi(value);
 		else if (attributeName == L"note_velocity") rec.noteVelocity = std::stoi(value);
 		else if (attributeName == L"raw") rec.raw = value;
+		else if (attributeName == L"source_port") rec.connectionSourcePort = value;
+		else if (attributeName == L"destination_port") rec.connectionDestinationPort = value;
 
 		rec.attributeIndex++;
 
@@ -261,6 +269,7 @@
 
 			// TODO: correct timing?
 			m.time = 0;
+			m.size = 0;
 
 			if (rec.event == RelationContext::RecordContext::Event::NOTE) {
 				m.size = 3;
@@ -272,8 +281,13 @@
 				m.buffer[0] = 0xB0 | rec.channel;
 				m.buffer[1] = rec.controllerId;
 				m.buffer[2] = rec.controllerValue;
+			} else if (rec.event == RelationContext::RecordContext::Event::CONNECT) {
+				int result = jack_connect(realTimeContext.jackClient, convertor.to_bytes(rec.connectionSourcePort).c_str(), convertor.to_bytes(rec.connectionDestinationPort).c_str());
+				if (result != 0 && result != EEXIST) std::wcerr << L"Unable to connect: „" << rec.connectionSourcePort << L"“ to: „" << rec.connectionDestinationPort << L"“." << std::endl;
+			} else if (rec.event == RelationContext::RecordContext::Event::DISCONNECT) {
+				int result = jack_disconnect(realTimeContext.jackClient, convertor.to_bytes(rec.connectionSourcePort).c_str(), convertor.to_bytes(rec.connectionDestinationPort).c_str());
+				if (result != 0) std::wcerr << L"Unable to disconnect: „" << rec.connectionSourcePort << L"“ from: „" << rec.connectionDestinationPort << L"“." << std::endl;
 			} else { // SysEx and other raw messages
-				m.size = 0;
 				size_t nibble = 0;
 				for (int i = 0; i < rec.raw.size() && m.size < sizeof (m.buffer); i++) {
 					wchar_t ch = rec.raw[i];
@@ -289,9 +303,7 @@
 				}
 			}
 
-			// TODO: if (m.size == 0) fwprintf(stderr, L"Missing data\n");
-
-			jack_ringbuffer_write(realTimeContext.ringBuffer, (const char *) &m, sizeof (m));
+			if (m.size > 0) jack_ringbuffer_write(realTimeContext.ringBuffer, (const char *) &m, sizeof (m));
 
 			relationContext.recordContext = RelationContext::RecordContext();
 		}