169 } |
170 } |
170 |
171 |
171 return result.str(); |
172 return result.str(); |
172 } |
173 } |
173 |
174 |
|
175 void listPorts(std::shared_ptr<relpipe::writer::RelationalWriter> writer) { |
|
176 using namespace relpipe::writer; |
|
177 vector<AttributeMetadata> metadata; |
|
178 |
|
179 metadata.push_back({L"name", TypeId::STRING}); |
|
180 metadata.push_back({L"input", TypeId::BOOLEAN}); |
|
181 metadata.push_back({L"output", TypeId::BOOLEAN}); |
|
182 metadata.push_back({L"physical", TypeId::BOOLEAN}); |
|
183 metadata.push_back({L"terminal", TypeId::BOOLEAN}); |
|
184 metadata.push_back({L"mine", TypeId::BOOLEAN}); |
|
185 metadata.push_back({L"midi", TypeId::BOOLEAN}); |
|
186 metadata.push_back({L"type", TypeId::STRING}); |
|
187 writer->startRelation(L"port", metadata, true); |
|
188 |
|
189 const char** portNames = jack_get_ports(realTimeContext.jackClient, nullptr, nullptr, 0); |
|
190 |
|
191 std::regex midiTypePattern(".*midi$"); |
|
192 |
|
193 for (const char** portName = portNames; *portName; portName++) { |
|
194 jack_port_t* port = jack_port_by_name(realTimeContext.jackClient, *portName); |
|
195 |
|
196 const char* portType = jack_port_type(port); |
|
197 int portFlags = jack_port_flags(port); |
|
198 |
|
199 bool isInput = portFlags & JackPortFlags::JackPortIsInput; |
|
200 bool isOuputput = portFlags & JackPortFlags::JackPortIsOutput; |
|
201 bool isPhysical = portFlags & JackPortFlags::JackPortIsPhysical; |
|
202 bool isTerminal = portFlags & JackPortFlags::JackPortIsTerminal; |
|
203 bool isMine = jack_port_is_mine(realTimeContext.jackClient, port); |
|
204 bool isMidi = std::regex_search(portType, midiTypePattern); |
|
205 |
|
206 writer->writeAttribute(convertor.from_bytes(*portName)); |
|
207 writer->writeAttribute(&isInput, typeid (isInput)); |
|
208 writer->writeAttribute(&isOuputput, typeid (isOuputput)); |
|
209 writer->writeAttribute(&isPhysical, typeid (isPhysical)); |
|
210 writer->writeAttribute(&isTerminal, typeid (isTerminal)); |
|
211 writer->writeAttribute(&isMine, typeid (isMine)); |
|
212 writer->writeAttribute(&isMidi, typeid (isMidi)); |
|
213 writer->writeAttribute(convertor.from_bytes(portType)); |
|
214 } |
|
215 |
|
216 jack_free(portNames); |
|
217 } |
|
218 |
174 static void jackErrorCallback(const char * message) { |
219 static void jackErrorCallback(const char * message) { |
175 std::wstring_convert < std::codecvt_utf8<wchar_t>> convertor; // TODO: local system encoding |
220 std::wstring_convert < std::codecvt_utf8<wchar_t>> convertor; // TODO: local system encoding |
176 std::wcerr << L"JACK: " << convertor.from_bytes(message) << std::endl; |
221 std::wcerr << L"JACK: " << convertor.from_bytes(message) << std::endl; |
177 } |
222 } |
178 |
223 |
233 |
278 |
234 void processJackStream(std::shared_ptr<relpipe::writer::RelationalWriter> writer, std::function<void() > relationalWriterFlush) { |
279 void processJackStream(std::shared_ptr<relpipe::writer::RelationalWriter> writer, std::function<void() > relationalWriterFlush) { |
235 // Relation headers: |
280 // Relation headers: |
236 using namespace relpipe::writer; |
281 using namespace relpipe::writer; |
237 vector<AttributeMetadata> metadata; |
282 vector<AttributeMetadata> metadata; |
|
283 |
|
284 if (configuration.listJackPorts) listPorts(writer); |
|
285 if (!configuration.listMidiMessages) return; |
|
286 |
238 metadata.push_back({L"event", TypeId::STRING}); |
287 metadata.push_back({L"event", TypeId::STRING}); |
239 metadata.push_back({L"channel", TypeId::INTEGER}); |
288 metadata.push_back({L"channel", TypeId::INTEGER}); |
240 metadata.push_back({L"note_on", TypeId::BOOLEAN}); |
289 metadata.push_back({L"note_on", TypeId::BOOLEAN}); |
241 metadata.push_back({L"note_pitch", TypeId::INTEGER}); |
290 metadata.push_back({L"note_pitch", TypeId::INTEGER}); |
242 metadata.push_back({L"note_velocity", TypeId::INTEGER}); |
291 metadata.push_back({L"note_velocity", TypeId::INTEGER}); |