src/JackHandler.h
branchv_0
changeset 6 4174fc0c2e7c
parent 5 6be3464ccb2b
child 7 b2fc99295546
equal deleted inserted replaced
5:6be3464ccb2b 6:4174fc0c2e7c
    17 #pragma once
    17 #pragma once
    18 
    18 
    19 #include <memory>
    19 #include <memory>
    20 #include <atomic>
    20 #include <atomic>
    21 #include <string>
    21 #include <string>
       
    22 #include <cstring>
    22 #include <vector>
    23 #include <vector>
    23 #include <iostream>
    24 #include <iostream>
    24 #include <sstream>
    25 #include <sstream>
    25 #include <locale>
    26 #include <locale>
    26 #include <codecvt>
    27 #include <codecvt>
    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 *) &currentMidiMessage, sizeof (MidiMessage));
   129 				jack_ringbuffer_write(ringBuffer, (const char *) &currentMidiMessage, 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;