27 #include <functional> |
27 #include <functional> |
28 #include <iomanip> |
28 #include <iomanip> |
29 #include <regex> |
29 #include <regex> |
30 |
30 |
31 #include <jack/jack.h> |
31 #include <jack/jack.h> |
|
32 #include <jack/metadata.h> |
|
33 #include <jack/uuid.h> |
32 #include <jack/midiport.h> |
34 #include <jack/midiport.h> |
33 #include <jack/ringbuffer.h> |
35 #include <jack/ringbuffer.h> |
34 |
36 |
35 #include <relpipe/common/type/typedefs.h> |
37 #include <relpipe/common/type/typedefs.h> |
36 #include <relpipe/writer/RelationalWriter.h> |
38 #include <relpipe/writer/RelationalWriter.h> |
175 void listPorts(std::shared_ptr<relpipe::writer::RelationalWriter> writer) { |
177 void listPorts(std::shared_ptr<relpipe::writer::RelationalWriter> writer) { |
176 using namespace relpipe::writer; |
178 using namespace relpipe::writer; |
177 vector<AttributeMetadata> metadata; |
179 vector<AttributeMetadata> metadata; |
178 |
180 |
179 metadata.push_back({L"name", TypeId::STRING}); |
181 metadata.push_back({L"name", TypeId::STRING}); |
|
182 metadata.push_back({L"uuid", TypeId::STRING}); |
180 metadata.push_back({L"input", TypeId::BOOLEAN}); |
183 metadata.push_back({L"input", TypeId::BOOLEAN}); |
181 metadata.push_back({L"output", TypeId::BOOLEAN}); |
184 metadata.push_back({L"output", TypeId::BOOLEAN}); |
182 metadata.push_back({L"physical", TypeId::BOOLEAN}); |
185 metadata.push_back({L"physical", TypeId::BOOLEAN}); |
183 metadata.push_back({L"terminal", TypeId::BOOLEAN}); |
186 metadata.push_back({L"terminal", TypeId::BOOLEAN}); |
184 metadata.push_back({L"mine", TypeId::BOOLEAN}); |
187 metadata.push_back({L"mine", TypeId::BOOLEAN}); |
202 bool isTerminal = portFlags & JackPortFlags::JackPortIsTerminal; |
205 bool isTerminal = portFlags & JackPortFlags::JackPortIsTerminal; |
203 bool isMine = jack_port_is_mine(realTimeContext.jackClient, port); |
206 bool isMine = jack_port_is_mine(realTimeContext.jackClient, port); |
204 bool isMidi = std::regex_search(portType, midiTypePattern); |
207 bool isMidi = std::regex_search(portType, midiTypePattern); |
205 |
208 |
206 writer->writeAttribute(convertor.from_bytes(*portName)); |
209 writer->writeAttribute(convertor.from_bytes(*portName)); |
|
210 writer->writeAttribute(convertor.from_bytes(uuidToString(jack_port_uuid(port)))); |
207 writer->writeAttribute(&isInput, typeid (isInput)); |
211 writer->writeAttribute(&isInput, typeid (isInput)); |
208 writer->writeAttribute(&isOuputput, typeid (isOuputput)); |
212 writer->writeAttribute(&isOuputput, typeid (isOuputput)); |
209 writer->writeAttribute(&isPhysical, typeid (isPhysical)); |
213 writer->writeAttribute(&isPhysical, typeid (isPhysical)); |
210 writer->writeAttribute(&isTerminal, typeid (isTerminal)); |
214 writer->writeAttribute(&isTerminal, typeid (isTerminal)); |
211 writer->writeAttribute(&isMine, typeid (isMine)); |
215 writer->writeAttribute(&isMine, typeid (isMine)); |
244 } |
248 } |
245 |
249 |
246 jack_free(sourcePortNames); |
250 jack_free(sourcePortNames); |
247 } |
251 } |
248 |
252 |
|
253 std::string uuidToString(jack_uuid_t uuid) { |
|
254 char buffer[JACK_UUID_STRING_SIZE] = {0}; |
|
255 jack_uuid_unparse(uuid, buffer); |
|
256 return buffer; |
|
257 } |
|
258 |
|
259 void listProperties(std::shared_ptr<relpipe::writer::RelationalWriter> writer) { |
|
260 using namespace relpipe::writer; |
|
261 vector<AttributeMetadata> metadata; |
|
262 |
|
263 metadata.push_back({L"uuid", TypeId::STRING}); |
|
264 //metadata.push_back({L"port", TypeId::STRING}); // TODO: port name |
|
265 metadata.push_back({L"name", TypeId::STRING}); |
|
266 metadata.push_back({L"type", TypeId::STRING}); |
|
267 metadata.push_back({L"value", TypeId::STRING}); |
|
268 writer->startRelation(L"property", metadata, true); |
|
269 |
|
270 jack_description_t* descriptions = nullptr; |
|
271 |
|
272 int descriptionsCount = jack_get_all_properties(&descriptions); |
|
273 |
|
274 for (int i = 0; i < descriptionsCount; i++) { |
|
275 jack_description_t* description = &descriptions[i]; |
|
276 for (uint32_t j = 0; j < description->property_cnt; j++) { |
|
277 jack_property_t* property = &description->properties[j]; |
|
278 writer->writeAttribute(convertor.from_bytes(uuidToString(description->subject))); |
|
279 //writer->writeAttribute(L"TODO: port name"); // TODO: port name |
|
280 writer->writeAttribute(convertor.from_bytes(property->key)); |
|
281 writer->writeAttribute(convertor.from_bytes(property->type)); |
|
282 writer->writeAttribute(convertor.from_bytes(property->data)); // TODO: format value (some in HEX), according to .type |
|
283 } |
|
284 jack_free_description(description, false); |
|
285 } |
|
286 jack_free(descriptions); |
|
287 } |
|
288 |
249 void applyConnectionRecipes() { |
289 void applyConnectionRecipes() { |
250 for (Configuration::ConnectionRecipe recipe : configuration.connectionRecipes) { |
290 for (Configuration::ConnectionRecipe recipe : configuration.connectionRecipes) { |
251 auto operation = recipe.connected ? jack_connect : jack_disconnect; |
291 auto operation = recipe.connected ? jack_connect : jack_disconnect; |
252 int result = operation(realTimeContext.jackClient, convertor.to_bytes(recipe.sourcePort).c_str(), convertor.to_bytes(recipe.destinationPort).c_str()); |
292 int result = operation(realTimeContext.jackClient, convertor.to_bytes(recipe.sourcePort).c_str(), convertor.to_bytes(recipe.destinationPort).c_str()); |
253 if (result != 0 && result != EEXIST) std::wcerr << L"Unable to " << (recipe.connected ? L"connect" : L"disconnect") << L": „" << recipe.sourcePort << L"“ to: „" << recipe.destinationPort << L"“." << std::endl; |
293 if (result != 0 && result != EEXIST) std::wcerr << L"Unable to " << (recipe.connected ? L"connect" : L"disconnect") << L": „" << recipe.sourcePort << L"“ to: „" << recipe.destinationPort << L"“." << std::endl; |
321 |
361 |
322 applyConnectionRecipes(); |
362 applyConnectionRecipes(); |
323 |
363 |
324 if (configuration.listPorts) listPorts(writer); |
364 if (configuration.listPorts) listPorts(writer); |
325 if (configuration.listConnections) listConnections(writer); |
365 if (configuration.listConnections) listConnections(writer); |
|
366 if (configuration.listProperties) listProperties(writer); |
326 if (!configuration.listMidiMessages) return; |
367 if (!configuration.listMidiMessages) return; |
327 |
368 |
328 metadata.push_back({L"event", TypeId::STRING}); |
369 metadata.push_back({L"event", TypeId::STRING}); |
329 metadata.push_back({L"channel", TypeId::INTEGER}); |
370 metadata.push_back({L"channel", TypeId::INTEGER}); |
330 metadata.push_back({L"note_on", TypeId::BOOLEAN}); |
371 metadata.push_back({L"note_on", TypeId::BOOLEAN}); |