184 |
184 |
185 JackHandler(Configuration& configuration) : configuration(configuration) { |
185 JackHandler(Configuration& configuration) : configuration(configuration) { |
186 pthread_mutex_lock(&realTimeContext.processingLock); |
186 pthread_mutex_lock(&realTimeContext.processingLock); |
187 |
187 |
188 // Initialize JACK connection: |
188 // Initialize JACK connection: |
189 std::string clientName = convertor.to_bytes(configuration.jackClientName); |
189 std::string clientName = convertor.to_bytes(configuration.client); |
190 realTimeContext.jackClient = jack_client_open(clientName.c_str(), JackNullOption, nullptr); |
190 realTimeContext.jackClient = jack_client_open(clientName.c_str(), JackNullOption, nullptr); |
191 if (realTimeContext.jackClient == nullptr) failInConstructor(L"Could not create JACK client."); |
191 if (realTimeContext.jackClient == nullptr) failInConstructor(L"Could not create JACK client."); |
192 |
192 |
193 realTimeContext.ringBuffer = jack_ringbuffer_create(realTimeContext.RING_BUFFER_SIZE * sizeof (MidiMessage)); |
193 realTimeContext.ringBuffer = jack_ringbuffer_create(realTimeContext.RING_BUFFER_SIZE * sizeof (MidiMessage)); |
194 |
194 |
196 jack_set_sync_callback(realTimeContext.jackClient, RealTimeContext::syncCallback, &realTimeContext); |
196 jack_set_sync_callback(realTimeContext.jackClient, RealTimeContext::syncCallback, &realTimeContext); |
197 // TODO: report also other events (connections etc.) |
197 // TODO: report also other events (connections etc.) |
198 jack_set_error_function(jackErrorCallback); |
198 jack_set_error_function(jackErrorCallback); |
199 jack_set_info_function(jackErrorCallback); |
199 jack_set_info_function(jackErrorCallback); |
200 |
200 |
201 realTimeContext.jackPort = jack_port_register(realTimeContext.jackClient, "output", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); |
201 realTimeContext.jackPort = jack_port_register(realTimeContext.jackClient, convertor.to_bytes(configuration.port).c_str(), JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); |
202 if (realTimeContext.jackPort == nullptr) failInConstructor(L"Could not register the JACK port."); |
202 if (realTimeContext.jackPort == nullptr) failInConstructor(L"Could not register the JACK port."); |
203 |
203 |
204 if (mlockall(MCL_CURRENT | MCL_FUTURE)) fwprintf(stderr, L"Warning: Can not lock memory.\n"); |
204 if (mlockall(MCL_CURRENT | MCL_FUTURE)) fwprintf(stderr, L"Warning: Can not lock memory.\n"); |
205 |
205 |
206 int jackError = jack_activate(realTimeContext.jackClient); |
206 int jackError = jack_activate(realTimeContext.jackClient); |
207 if (jackError) failInConstructor(L"Could not activate the JACK client."); |
207 if (jackError) failInConstructor(L"Could not activate the JACK client."); |
208 |
208 |
209 |
209 |
210 // Connect to configured destination ports: |
210 // Connect to configured destination ports: |
211 const char* jackPortName = jack_port_name(realTimeContext.jackPort); |
211 const char* jackPortName = jack_port_name(realTimeContext.jackPort); |
212 for (auto destinationPort : configuration.portsToConnect) { |
212 for (auto destinationPort : configuration.connectTo) { |
213 int error = jack_connect(realTimeContext.jackClient, jackPortName, convertor.to_bytes(destinationPort).c_str()); |
213 int error = jack_connect(realTimeContext.jackClient, jackPortName, convertor.to_bytes(destinationPort).c_str()); |
214 if (error) failInConstructor(L"Connection to the JACK port failed: " + destinationPort); |
214 if (error) failInConstructor(L"Connection to the JACK port failed: " + destinationPort); |
215 } |
215 } |
216 |
216 |
217 // Wait for a port connection, because it does not make much sense to send MIDI events nowhere: |
217 // Wait for a port connection, because it does not make much sense to send MIDI events nowhere: |
218 while (jack_port_connected(realTimeContext.jackPort) < configuration.requiredJackConnections) usleep(10000); |
218 while (jack_port_connected(realTimeContext.jackPort) < configuration.requiredConnections) usleep(10000); |
219 |
219 |
220 } |
220 } |
221 |
221 |
222 void startRelation(const relpipe::common::type::StringX name, std::vector<relpipe::reader::handlers::AttributeMetadata> attributes) override { |
222 void startRelation(const relpipe::common::type::StringX name, std::vector<relpipe::reader::handlers::AttributeMetadata> attributes) override { |
223 relationContext = RelationContext(); |
223 relationContext = RelationContext(); |