src/JackHandler.h
branchv_0
changeset 3 baa8055c5b10
parent 2 01553c2ffa1d
child 4 65dfbf0494a3
equal deleted inserted replaced
2:01553c2ffa1d 3:baa8055c5b10
    15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
    15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
    16  */
    16  */
    17 #pragma once
    17 #pragma once
    18 
    18 
    19 #include <memory>
    19 #include <memory>
       
    20 #include <atomic>
    20 #include <string>
    21 #include <string>
    21 #include <vector>
    22 #include <vector>
    22 #include <iostream>
    23 #include <iostream>
    23 #include <sstream>
    24 #include <sstream>
    24 #include <locale>
    25 #include <locale>
    25 #include <codecvt>
    26 #include <codecvt>
    26 #include <sys/mman.h>
    27 #include <sys/mman.h>
       
    28 #include <signal.h>
    27 
    29 
    28 #include <jack/jack.h>
    30 #include <jack/jack.h>
    29 #include <jack/midiport.h>
    31 #include <jack/midiport.h>
    30 #include <jack/ringbuffer.h>
    32 #include <jack/ringbuffer.h>
    31 
    33 
    39 
    41 
    40 namespace relpipe {
    42 namespace relpipe {
    41 namespace out {
    43 namespace out {
    42 namespace jack {
    44 namespace jack {
    43 
    45 
       
    46 int dequeueMessages(jack_nframes_t frames, void* arg);
       
    47 
    44 class JackHandler : public relpipe::reader::handlers::RelationalReaderStringHandler {
    48 class JackHandler : public relpipe::reader::handlers::RelationalReaderStringHandler {
    45 private:
    49 private:
    46 	Configuration& configuration;
    50 	Configuration& configuration;
    47 	std::wstring_convert<std::codecvt_utf8<wchar_t>> convertor; // TODO: local system encoding
    51 	std::wstring_convert<std::codecvt_utf8<wchar_t>> convertor; // TODO: local system encoding
    48 
    52 
    49 	jack_client_t* jackClient = nullptr;
    53 	jack_client_t* jackClient = nullptr;
    50 	jack_port_t* jackPort = nullptr;
    54 	jack_port_t* jackPort = nullptr;
    51 	//jack_ringbuffer_t* ringBuffer = nullptr;
    55 	jack_ringbuffer_t* ringBuffer = nullptr;
       
    56 
       
    57 	std::atomic<bool> continueProcessing{true};
       
    58 
       
    59 	const int RING_BUFFER_SIZE = 100;
       
    60 
       
    61 	struct MidiMessage {
       
    62 		uint8_t buffer[4096];
       
    63 		uint32_t size;
       
    64 		uint32_t time;
       
    65 	};
       
    66 
    52 public:
    67 public:
    53 
    68 
    54 	JackHandler(Configuration& configuration) : configuration(configuration) {
    69 	JackHandler(Configuration& configuration) : configuration(configuration) {
    55 		// Initialize JACK connection:
    70 		// Initialize JACK connection:
    56 		std::string clientName = convertor.to_bytes(configuration.jackClientName);
    71 		std::string clientName = convertor.to_bytes(configuration.jackClientName);
    57 		jackClient = jack_client_open(clientName.c_str(), JackNullOption, nullptr);
    72 		jackClient = jack_client_open(clientName.c_str(), JackNullOption, nullptr);
    58 		if (jackClient == nullptr) throw JackException(L"Could not create JACK client.");
    73 		if (jackClient == nullptr) throw JackException(L"Could not create JACK client.");
    59 
    74 
    60 		//ringBuffer = jack_ringbuffer_create(RING_BUFFER_SIZE * sizeof (MidiMessage));
    75 		ringBuffer = jack_ringbuffer_create(RING_BUFFER_SIZE * sizeof (MidiMessage));
    61 
    76 
    62 		//jack_set_process_callback(jackClient, relpipe::in::jack::enqueueMessage, this);
    77 		jack_set_process_callback(jackClient, relpipe::out::jack::dequeueMessages, this);
    63 		// TODO: report also other events (connections etc.)
    78 		// TODO: report also other events (connections etc.)
    64 
    79 
    65 		jackPort = jack_port_register(jackClient, "output", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
    80 		jackPort = jack_port_register(jackClient, "output", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
    66 		if (jackPort == nullptr) throw JackException(L"Could not register port.");
    81 		if (jackPort == nullptr) throw JackException(L"Could not register port.");
    67 
    82 
    70 		int jackError = jack_activate(jackClient);
    85 		int jackError = jack_activate(jackClient);
    71 		if (jackError) throw JackException(L"Could not activate client.");
    86 		if (jackError) throw JackException(L"Could not activate client.");
    72 	}
    87 	}
    73 
    88 
    74 	void startRelation(const relpipe::common::type::StringX name, std::vector<relpipe::reader::handlers::AttributeMetadata> attributes) override {
    89 	void startRelation(const relpipe::common::type::StringX name, std::vector<relpipe::reader::handlers::AttributeMetadata> attributes) override {
    75 		
    90 		// TODO: validate metadata and prepare attribute mappings (names and types are important, order does not matter)
       
    91 
    76 	}
    92 	}
    77 
    93 
    78 	void attribute(const relpipe::common::type::StringX& value) override {
    94 	void attribute(const relpipe::common::type::StringX& value) override {
    79 		
    95 		// TODO: append to current message + if this is last attribute, put whole message to the ring buffer
       
    96 		// TODO: if (continueProcessing) {} ?
    80 	}
    97 	}
    81 
    98 
    82 	void endOfPipe() {
    99 	void endOfPipe() {
    83 		
   100 		// TODO: send optional (configurable) MIDI events
       
   101 		// TODO: wait until the ring buffer is empty
       
   102 	}
       
   103 
       
   104 	int dequeueMessages(jack_nframes_t frames) {
       
   105 
       
   106 
       
   107 		// TODO: send events from the ring buffer to JACK + correct timing
       
   108 		std::cout << "dequeueMessages(" << frames << ")" << std::endl;
       
   109 
       
   110 
       
   111 		return 0;
       
   112 	}
       
   113 
       
   114 	void finish(int sig) {
       
   115 		continueProcessing = false;
    84 	}
   116 	}
    85 
   117 
    86 	virtual ~JackHandler() {
   118 	virtual ~JackHandler() {
    87 		// Close JACK connection:
   119 		// Close JACK connection:
    88 		jack_deactivate(jackClient);
   120 		jack_deactivate(jackClient);
    89 		jack_client_close(jackClient);
   121 		jack_client_close(jackClient);
    90 		//jack_ringbuffer_free(ringBuffer);
   122 		jack_ringbuffer_free(ringBuffer);
    91 	}
   123 	}
    92 
   124 
    93 };
   125 };
    94 
   126 
       
   127 int dequeueMessages(jack_nframes_t frames, void* arg) {
       
   128 	JackHandler* instance = (JackHandler*) arg;
       
   129 	return instance->dequeueMessages(frames);
       
   130 }
       
   131 
    95 }
   132 }
    96 }
   133 }
    97 }
   134 }