52 std::wstring_convert<std::codecvt_utf8<wchar_t>> convertor; // TODO: local system encoding |
53 std::wstring_convert<std::codecvt_utf8<wchar_t>> convertor; // TODO: local system encoding |
53 |
54 |
54 jack_client_t* jackClient = nullptr; |
55 jack_client_t* jackClient = nullptr; |
55 jack_port_t* jackPort = nullptr; |
56 jack_port_t* jackPort = nullptr; |
56 jack_ringbuffer_t* ringBuffer = nullptr; |
57 jack_ringbuffer_t* ringBuffer = nullptr; |
57 pthread_mutex_t messageThreadLock = PTHREAD_MUTEX_INITIALIZER; |
|
58 pthread_cond_t dataReady = PTHREAD_COND_INITIALIZER; |
|
59 |
58 |
60 std::atomic<bool> continueProcessing{true}; |
59 std::atomic<bool> continueProcessing{true}; |
61 |
60 |
62 const int RING_BUFFER_SIZE = 100; |
61 const int RING_BUFFER_SIZE = 100; |
63 |
62 |
114 |
113 |
115 if (currentAttributeIndex < currentAttributeCount) { |
114 if (currentAttributeIndex < currentAttributeCount) { |
116 // memcpy(currentMidiMessage.buffer, ….buffer, ….size); |
115 // memcpy(currentMidiMessage.buffer, ….buffer, ….size); |
117 // currentMidiMessage.size = …; |
116 // currentMidiMessage.size = …; |
118 // currentMidiMessage.time = …; |
117 // currentMidiMessage.time = …; |
|
118 |
|
119 // TODO: correct timing? |
|
120 // TODO: real data |
|
121 currentMidiMessage.size = 3; |
|
122 currentMidiMessage.buffer[0] = 0x80; |
|
123 currentMidiMessage.buffer[1] = 0x34; |
|
124 currentMidiMessage.buffer[2] = 0x40; |
|
125 |
119 currentAttributeIndex++; |
126 currentAttributeIndex++; |
120 } else { |
127 } else { |
121 if (jack_ringbuffer_write_space(ringBuffer) >= sizeof (MidiMessage)) { |
128 if (jack_ringbuffer_write_space(ringBuffer) >= sizeof (MidiMessage)) { |
122 jack_ringbuffer_write(ringBuffer, (const char *) ¤tMidiMessage, sizeof (MidiMessage)); |
129 jack_ringbuffer_write(ringBuffer, (const char *) ¤tMidiMessage, sizeof (MidiMessage)); |
123 } else { |
130 } else { |
124 fwprintf(stderr, L"Error: ring buffer is full → skipping event.\n"); |
131 fwprintf(stderr, L"Error: ring buffer is full → skipping event.\n"); |
125 } |
|
126 |
|
127 if (pthread_mutex_trylock(&messageThreadLock) == 0) { |
|
128 pthread_cond_signal(&dataReady); |
|
129 pthread_mutex_unlock(&messageThreadLock); |
|
130 } |
132 } |
131 |
133 |
132 currentMidiMessage = MidiMessage(); |
134 currentMidiMessage = MidiMessage(); |
133 currentAttributeIndex = 0; |
135 currentAttributeIndex = 0; |
134 } |
136 } |
141 // Wait until the ring buffer is empty |
143 // Wait until the ring buffer is empty |
142 while (continueProcessing && jack_ringbuffer_read_space(ringBuffer)) usleep(1000); |
144 while (continueProcessing && jack_ringbuffer_read_space(ringBuffer)) usleep(1000); |
143 } |
145 } |
144 |
146 |
145 int dequeueMessages(jack_nframes_t frames) { |
147 int dequeueMessages(jack_nframes_t frames) { |
146 |
148 const size_t queuedMessages = jack_ringbuffer_read_space(ringBuffer) / sizeof (MidiMessage); |
147 std::cout << "dequeueMessages(" << frames << ")" << std::endl; // TODO: remove debug message |
149 for (size_t i = 0; i < queuedMessages && i < frames; i++) { |
148 |
150 // TODO: correct timing? |
149 // Process messages from the ring buffer queue: |
151 MidiMessage m; |
150 pthread_mutex_lock(&messageThreadLock); |
152 jack_ringbuffer_read(ringBuffer, (char*) &m, sizeof (MidiMessage)); |
151 while (continueProcessing) { // TODO: is continueProcessing needed? |
153 void* jackPortBuffer = jack_port_get_buffer(jackPort, frames); |
152 const size_t queuedMessages = jack_ringbuffer_read_space(ringBuffer) / sizeof (MidiMessage); |
154 jack_midi_data_t* midiData = jack_midi_event_reserve(jackPortBuffer, m.time, m.size); |
153 for (size_t i = 0; i < queuedMessages; ++i) { |
155 memcpy(midiData, m.buffer, m.size); |
154 MidiMessage m; |
|
155 jack_ringbuffer_read(ringBuffer, (char*) &m, sizeof (MidiMessage)); |
|
156 // TODO: send events from the ring buffer to JACK + correct timing |
|
157 // FIXME: do not block here in the while loop; check frames |
|
158 std::cout << "will process MidiMessage: " << &m << "" << std::endl; // TODO: remove debug message |
|
159 } |
|
160 pthread_cond_wait(&dataReady, &messageThreadLock); |
|
161 } |
156 } |
162 pthread_mutex_unlock(&messageThreadLock); |
|
163 |
|
164 |
|
165 return 0; |
157 return 0; |
166 } |
158 } |
167 |
159 |
168 void finish(int sig) { |
160 void finish(int sig) { |
169 continueProcessing = false; |
161 continueProcessing = false; |